Fix duplex scan rotation and swap front/back image labels

Duplex scanners flip the sheet between sides, so odd pages (back) are
180° rotated relative to even pages (front). Landscape back pages now
rotate CCW instead of CW, and portrait back pages get a 180° flip.
Also swapped "Front"/"Back" labels to match the physical card sides.

Made-with: Cursor
This commit is contained in:
Randall Stillwell 2026-04-07 13:27:16 -05:00
parent 6cef79309b
commit 2fcdd687f7
2 changed files with 16 additions and 6 deletions

View file

@ -342,8 +342,8 @@ export default function CardDetailPage() {
</CardHeader>
<CardContent className="space-y-4">
<div className="grid gap-4 grid-cols-1 sm:grid-cols-2">
<ImagePanel label="Response Card (Back)" url={card.backImageUrl as string | null} />
<ImagePanel label="Survey (Front)" url={card.frontImageUrl as string | null} />
<ImagePanel label="Response Card (Front)" url={card.backImageUrl as string | null} />
<ImagePanel label="Survey (Back)" url={card.frontImageUrl as string | null} />
</div>
</CardContent>
</Card>

View file

@ -26,11 +26,21 @@ export async function pdfToImages(pdfBuffer: Buffer): Promise<PageImage[]> {
if (result.buffer) {
let buf = result.buffer as Buffer;
let meta = await sharp(buf).metadata();
const w = meta.width || 0;
const h = meta.height || 0;
// Scanners often store landscape content with a PDF /Rotate flag that
// pdf2pic may not apply. Detect and rotate to portrait orientation.
if ((meta.width || 0) > (meta.height || 0)) {
buf = await sharp(buf).rotate(90).jpeg({ quality: 90 }).toBuffer();
// Duplex scanners flip the sheet between sides, so odd pages
// (back/response card) are 180° rotated relative to even pages
// (front/survey). Landscape pages need rotation to portrait;
// the direction depends on which side of the sheet was scanned.
const isBackSide = i % 2 === 1;
if (w > h) {
const angle = isBackSide ? -90 : 90;
buf = await sharp(buf).rotate(angle).jpeg({ quality: 90 }).toBuffer();
meta = await sharp(buf).metadata();
} else if (isBackSide) {
buf = await sharp(buf).rotate(180).jpeg({ quality: 90 }).toBuffer();
meta = await sharp(buf).metadata();
}