feat: extract auto-orient utility and expand test coverage

Extract EXIF auto-orientation logic into a shared auto-orient module
used by both single-tool and batch routes. This ensures camera photos
display correctly after processing regardless of entry point.

Also expands e2e and integration tests significantly.
This commit is contained in:
Siddharth Kumar Sah
2026-03-24 20:37:14 +08:00
parent 06eabdd045
commit e5086ada6e
7 changed files with 1378 additions and 45 deletions
+3 -1
View File
@@ -14,6 +14,7 @@ import PQueue from "p-queue";
import { getToolConfig } from "./tool-factory.js";
import { validateImageBuffer } from "../lib/file-validation.js";
import { sanitizeFilename } from "../lib/filename.js";
import { autoOrient } from "../lib/auto-orient.js";
import { env } from "../config.js";
import { updateJobProgress, type JobProgress } from "./progress.js";
@@ -191,8 +192,9 @@ export async function registerBatchRoutes(
}
try {
const orientedBuffer = await autoOrient(file.buffer);
const result = await toolConfig.process(
file.buffer,
orientedBuffer,
settings,
file.filename,
);
+2 -14
View File
@@ -3,10 +3,10 @@ import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
import { z } from "zod";
import sharp from "sharp";
import { createWorkspace } from "../lib/workspace.js";
import { validateImageBuffer } from "../lib/file-validation.js";
import { sanitizeFilename } from "../lib/filename.js";
import { autoOrient } from "../lib/auto-orient.js";
export interface ToolRouteConfig<T> {
/** Unique tool identifier, used as the URL path segment. */
@@ -127,19 +127,7 @@ export function createToolRoute<T>(
}
// Auto-orient based on EXIF metadata before processing.
// Camera photos often have EXIF orientation tags (values 2-8) that browsers
// respect when displaying, but Sharp does NOT apply by default. Without this,
// processed images appear rotated because the output (PNG) strips EXIF data.
// Only re-encodes when orientation correction is actually needed.
let processBuffer = fileBuffer;
try {
const meta = await sharp(fileBuffer).metadata();
if (meta.orientation && meta.orientation > 1) {
processBuffer = await sharp(fileBuffer).rotate().toBuffer();
}
} catch {
// If metadata reading fails, proceed with original buffer
}
const processBuffer = await autoOrient(fileBuffer);
// Process the image
try {