Files
printerCentral/server/api/print/image.post.ts
josedario87 955584275b fix: Corregir configuración de estilos y componentes
- Agregar imports de Tailwind CSS v4 y Nuxt UI en main.css
- Renombrar QueueActions.vue -> Actions.vue y QueueItem.vue -> Item.vue para evitar conflictos de nombres de componentes
- Crear composable useMediaQuery para manejo de responsive
- Corregir referencias a componentes en index.vue y PrintQueue.vue
- Actualizar imports de servidor a rutas relativas
- Instalar @iconify-json/heroicons y @iconify-json/lucide
- Actualizar Jimp a sintaxis v1.x
2025-11-24 18:27:29 -06:00

119 lines
2.7 KiB
TypeScript

// 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
}
}
})