llm-router / apps /api /src /services /expense /shared /image-processing.ts
ClaraSu's picture
Upload folder using huggingface_hub
747e1c6 verified
Raw History Blame Contribute Delete
1.2 kB
import sharp from 'sharp'
const MAX_DIMENSION = 1800
const JPEG_QUALITY = 80
// Shared by every image-ingestion entry point (slip queue, payment-slip
// reconciliation, ad-hoc expense parsing) — runs before any LLM call and
// before any persistence. sharp strips EXIF on re-encode by default, which
// also drops embedded GPS data as a privacy side-benefit.
export async function compressImage(base64: string): Promise<string> {
const inputBuffer = Buffer.from(base64, 'base64')
const outputBuffer = await sharp(inputBuffer)
.resize(MAX_DIMENSION, MAX_DIMENSION, { fit: 'inside', withoutEnlargement: true })
.jpeg({ quality: JPEG_QUALITY })
.toBuffer()
return outputBuffer.toString('base64')
}
// Cheap real-image check — reads only the header (via sharp's metadata
// probe), not the full pixel data, so it's far cheaper than compressImage.
// Used at enqueue time now that compression itself has moved to after OCR
// succeeds (see slip-queue.service.ts), so something still rejects a
// non-image upload immediately instead of silently queuing it.
export async function validateImage(base64: string): Promise<void> {
await sharp(Buffer.from(base64, 'base64')).metadata()
}