File size: 1,204 Bytes
6822ee4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747e1c6
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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()
}