imagenorm decoded and re-encoded to JPEG but ignored the EXIF Orientation tag. Phone cameras store the sensor pixels one way and set an EXIF flag to rotate on display, so a "portrait" JPEG is really a landscape bitmap tagged "rotate 90°" — and our re-encode strips EXIF, so without baking the rotation in, a packet photographed in portrait reaches the vision model sideways (bad OCR) and any future thumbnail is wrong. - exifOrientation: a small pure-Go parser that walks the JPEG APP1/Exif segment for tag 0x0112, returning 1 (normal) for non-JPEG or unparseable input — never guess a rotation onto a correct image. No cgo, no new dep. - applyOrientation: bakes in all 8 orientations (the 4 rotations + mirrors) after downscale (cheaper to rotate the small image; a 90° turn swaps the sides but not the longest edge, so the downscale bound still holds). - Non-JPEG paths (HEIC/webp/png) are untouched — their decoders own orientation and they carry no JPEG EXIF. Tests build oriented JPEGs (a corner marker + a spliced Exif APP1) and assert the marker lands where each orientation says, dims swapping for the quarter-turns; plus parser defaults for non-JPEG / no-EXIF / garbage. Stays CGO_ENABLED=0. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ