mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
- Convert all AI bridge inputs to PNG before writing to disk so PIL can read AVIF/WebP/TIFF (7 bridge files; face-detection and OCR already had this pattern) - Add title/author aliases to edit-metadata schema so common field names actually write EXIF tags instead of being silently stripped by Zod - Port extend/pad crop logic from passport-photo single endpoint to the batch pipeline so crop regions extending beyond the image get filled with background color instead of producing all-white output - Clamp quantized color channels to 255 in color-palette to prevent Math.round(255/16)*16=256 from producing invalid hex like #100100100 - Compare OCR fallback warning against expected engine name per tier instead of comparing engine name against tier name (always mismatch)
49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import { readFile, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import sharp from "sharp";
|
|
import { type ProgressCallback, parseStdoutJson, runPythonWithProgress } from "./bridge.js";
|
|
|
|
export interface ColorizeOptions {
|
|
intensity?: number;
|
|
model?: string;
|
|
}
|
|
|
|
export interface ColorizeResult {
|
|
buffer: Buffer;
|
|
width: number;
|
|
height: number;
|
|
method: string;
|
|
}
|
|
|
|
export async function colorize(
|
|
inputBuffer: Buffer,
|
|
outputDir: string,
|
|
options: ColorizeOptions = {},
|
|
onProgress?: ProgressCallback,
|
|
): Promise<ColorizeResult> {
|
|
const inputPath = join(outputDir, "input_colorize.png");
|
|
const outputPath = join(outputDir, "output_colorize.png");
|
|
|
|
const pngBuffer = await sharp(inputBuffer).png().toBuffer();
|
|
await writeFile(inputPath, pngBuffer);
|
|
const { stdout } = await runPythonWithProgress(
|
|
"colorize.py",
|
|
[inputPath, outputPath, JSON.stringify(options)],
|
|
{ onProgress },
|
|
);
|
|
|
|
const result = parseStdoutJson(stdout);
|
|
if (!result.success) {
|
|
throw new Error(result.error || "Colorization failed");
|
|
}
|
|
|
|
const actualOutputPath = result.output_path || outputPath;
|
|
const buffer = await readFile(actualOutputPath);
|
|
return {
|
|
buffer,
|
|
width: result.width,
|
|
height: result.height,
|
|
method: result.method ?? "unknown",
|
|
};
|
|
}
|