Skills › Scientific Agent Skills › latex-posters › review_poster.sh
review_poster.sh
144 lines · skills/latex-posters/scripts/review_poster.sh at 5f2bc03
1#!/bin/bash
2# Read-only Poppler preflight. Exit 0: automated checks passed; 1: failure;
3# 2: incomplete because a required inspector is missing. Visual review is always required.
4export LC_ALL=C
6usage() { printf 'Usage: %s <poster.pdf>\n' "$0"; }
7if [ "${1:-}" = '--help' ] || [ "${1:-}" = '-h' ]; then usage; exit 0; fi
8if [ "$#" -ne 1 ]; then usage; exit 1; fi
9POSTER_FILE=$1
10# A leading dash must not become an inspector option.
11case "$POSTER_FILE" in /*) ;; *) POSTER_FILE="./$POSTER_FILE" ;; esac
12if [ ! -f "$POSTER_FILE" ]; then
13 printf '[FAIL] File not found: %s\n' "$POSTER_FILE"
14 exit 1
15fi
16failed=0
17incomplete=0
18command_exists() { command -v "$1" >/dev/null 2>&1; }
19missing() { printf '[WARN] %s not installed; check incomplete. Install Poppler.\n' "$1"; incomplete=1; }
21printf 'Poster PDF Quality Check\nFile: %s\n\n' "$POSTER_FILE"
22printf '[1] Page Dimensions:\n'
23PDF_INFO=''
24if command_exists pdfinfo; then
25 if PDF_INFO=$(pdfinfo "$POSTER_FILE" 2>&1); then
26 printf '%s\n' "$PDF_INFO" | awk '/^Page size:/ {print; found=1} END {if (!found) exit 1}' || failed=1
27 printf '%s\n' "$PDF_INFO" | awk '
28 function near(a,b) {return (a-b < 2 && b-a < 2)}
29 /^Page size:/ {
30 w=$3; h=$5
31 if (near(w,2383.94) && near(h,3370.39)) label="A0 Portrait"
32 else if (near(w,3370.39) && near(h,2383.94)) label="A0 Landscape"
33 else if (near(w,1683.78) && near(h,2383.94)) label="A1 Portrait"
34 else if (near(w,2383.94) && near(h,1683.78)) label="A1 Landscape"
35 else if (near(w,2592) && near(h,3456)) label="36 x 48 inches Portrait"
36 else if (near(w,3456) && near(h,2592)) label="36 x 48 inches Landscape"
37 else label="Custom dimensions"
38 print "[INFO] " label "; compare exact dimensions with venue requirements."
39 }'
40 else
41 printf '[FAIL] pdfinfo could not read the PDF.\n%s\n' "$PDF_INFO"
42 PDF_INFO=''
43 failed=1
44 fi
45else
46 missing pdfinfo
47fi
49printf '\n[2] Page Count:\n'
50if [ -n "$PDF_INFO" ]; then
51 PAGE_COUNT=$(printf '%s\n' "$PDF_INFO" | awk '/^Pages:/ {print $2}')
52 if [ "$PAGE_COUNT" = 1 ]; then
53 printf '[OK] Single page.\n'
54 else
55 printf '[FAIL] Expected one page; found: %s\n' "${PAGE_COUNT:-unknown}"
56 failed=1
57 fi
58else
59 printf '[WARN] Page count unavailable.\n'
60fi
62printf '\n[3] File Size:\n'
63FILE_SIZE_BYTES=$(wc -c < "$POSTER_FILE")
64printf '%s bytes. File size alone does not establish image quality.\n' "$FILE_SIZE_BYTES"
65if [ "$FILE_SIZE_BYTES" -gt 52428800 ]; then
66 printf '[WARN] Over 50 MiB; check the submission limit before creating a separate compressed copy.\n'
67fi
69printf '\n[4] Font Embedding:\n'
70if command_exists pdffonts; then
71 if FONT_OUTPUT=$(pdffonts "$POSTER_FILE" 2>&1); then
72 printf '%s\n' "$FONT_OUTPUT"
73 # Font type names contain spaces. The five rightmost fields are stable:
74 # emb, sub, uni, object number, generation. Inspect ALL rows.
75 if ! printf '%s\n' "$FONT_OUTPUT" | awk '
76 NR==1 {if ($0 !~ /emb.*sub.*uni.*object ID/) invalid=1; next}
77 NR>2 && NF {
78 count++
79 if (NF<8 || ($(NF-4)!="yes" && $(NF-4)!="no")) invalid=1
80 else if ($(NF-4)=="no") bad++
81 }
82 END {
83 if (invalid || NR<2) {print "[FAIL] Unrecognized pdffonts output."; exit 1}
84 if (bad) {print "[FAIL] " bad " font(s) are NOT embedded."; exit 1}
85 if (count) print "[OK] All " count " listed fonts are embedded."
86 else print "[INFO] No PDF fonts listed; check for outlined or rasterized text."
87 }'; then
88 printf 'Rebuild the LaTeX or imported figure source with embeddable fonts.\n'
89 failed=1
90 fi
91 else
92 printf '[FAIL] pdffonts failed.\n%s\n' "$FONT_OUTPUT"
93 failed=1
94 fi
95else
96 missing pdffonts
97fi
99printf '\n[5] Image Quality:\n'
100if command_exists pdfimages; then
101 if IMAGE_OUTPUT=$(pdfimages -list "$POSTER_FILE" 2>&1); then
102 printf '%s\n' "$IMAGE_OUTPUT"
103 if ! printf '%s\n' "$IMAGE_OUTPUT" | awk '
104 NR==1 {if ($0 !~ /x-ppi.*y-ppi/) invalid=1; next}
105 NR>2 && NF {
106 if (NF<16 || $13 !~ /^[0-9.]+$/ || $14 !~ /^[0-9.]+$/) invalid=1
107 if ($3=="image") {count++; if ($13+0<300 || $14+0<300) low++}
108 }
109 END {
110 if (invalid || NR<2) {print "[FAIL] Unrecognized pdfimages output."; exit 1}
111 if (!count) print "[INFO] No raster images listed; vector artwork has no raster PPI."
112 else if (low) print "[WARN] " low " raster image(s) below 300 PPI at placed size; confirm print needs."
113 else print "[OK] Listed raster images are at least 300 PPI at placed size."
114 }'; then
115 failed=1
116 fi
117 else
118 printf '[FAIL] pdfimages failed.\n%s\n' "$IMAGE_OUTPUT"
119 failed=1
120 fi
121else
122 missing pdfimages
123fi
125printf '\n[6] Manual Visual Inspection Required:\n'
126printf '%s\n' \
127 ' [ ] No clipping or overlap at any edge, column, title, or footer.' \
128 ' [ ] Readable typography and figure labels at the intended viewing distance.' \
129 ' [ ] Correct data, units, uncertainty, citations, authors, and affiliations.' \
130 ' [ ] No draft placeholders; all figure captions and legends are accurate.' \
131 ' [ ] Suitable contrast; categories use labels or shapes as well as color.' \
132 ' [ ] QR codes scan and lead to the intended public resource.'
133printf '\n[7] Recommended Next Steps:\n'
134printf '%s\n' \
135 ' - Inspect a rendered PDF and its LaTeX log; automated checks do not detect all overflow.' \
136 ' - A0 to A4 is approximately 25% linear scale; 36 x 48 inches needs 9 x 12 inches at 25%.' \
137 ' - View a reduced proof at the same scale factor times the full-size viewing distance.' \
138 ' - Confirm exact dimensions, color profile, bleed, and any PDF/X requirement with the printer.' \
139 ' - Use assets/poster_quality_checklist.md for the remaining checks.'
140printf '\nQuality Check Complete\n'
141if [ "$failed" -ne 0 ]; then printf '[FAIL] Automated checks found errors.\n'; exit 1; fi
142if [ "$incomplete" -ne 0 ]; then printf '[WARN] Automated preflight incomplete.\n'; exit 2; fi
143printf '[OK] Automated checks passed; manual visual and scientific review still required.\n'
144exit 0