// Endpoint para imprimir imágenes usando Jimp import { Jimp } from 'jimp' import { EposMessageBuilder } from '../../utils/eposBuilder' import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer' export default defineEventHandler(async (event) => { try { const config = useRuntimeConfig() const body = await readBody(event) const { path, width, threshold = 128, mode = 'mono' } = body as { path?: string width?: number threshold?: number mode?: string } if (!path) { return { ok: false, error: 'path required' } } // Leer y procesar imagen const img = await Jimp.read(path) let targetWidth = width || img.width if (targetWidth <= 0) targetWidth = img.width const scale = targetWidth / img.width const targetHeight = Math.max(1, Math.round(img.height * scale)) // Resize y convertir a escala de grises img.resize({ w: targetWidth, h: targetHeight }) img.greyscale() // Empaquetar bits MSB first por byte const bytesPerRow = Math.ceil(targetWidth / 8) const out = Buffer.alloc(bytesPerRow * targetHeight) let outIdx = 0 for (let y = 0; y < targetHeight; y++) { let byte = 0 let bit = 7 let rowBytes = 0 for (let x = 0; x < targetWidth; x++) { const color = img.getPixelColor(x, y) // Extraer componente rojo (ya es greyscale, todos los canales son iguales) const r = (color >> 24) & 0xFF const isBlack = r < threshold if (isBlack) byte |= (1 << bit) bit-- if (bit < 0) { out[outIdx++] = byte rowBytes++ byte = 0 bit = 7 } } // Rellenar bits restantes if (bit !== 7) { out[outIdx++] = byte rowBytes++ } // Rellenar a bytes completos si es necesario while (rowBytes < bytesPerRow) { out[outIdx++] = 0 rowBytes++ } } const base64 = out.toString('base64') // Construir mensaje ePOS const builder = new EposMessageBuilder() builder.imageRaw({ width: targetWidth, height: targetHeight, mode, base64 }) const soap = buildSoapEnvelope(builder.build()) const result = await sendToPrinter( soap, config.printerHost, config.printerDeviceId, parseInt(config.printerTimeoutMs) ) const { success, code } = parsePrinterResponse(result.data) return { ok: success, httpStatus: result.status, code, raw: result.data, width: targetWidth, height: targetHeight } } catch (err: any) { return { ok: false, error: err.message } } })