import {FastifyInstance} from "fastify"; import { PNG } from 'pngjs' import { ready as zplReady } from 'zpl-renderer-js' import { Utils } from '@mmote/niimbluelib' import { createCanvas } from 'canvas' import bwipjs from 'bwip-js' import Sharp from 'sharp' import fs from 'fs' export const useNextNumberRangeNumber = async (server:FastifyInstance, tenantId:number,numberRange)=> { const {data:tenant} = await server.supabase.from("tenants").select().eq("id",tenantId).single() const numberRanges = tenant.numberRanges const usedNumber = (numberRanges[numberRange].prefix ? numberRanges[numberRange].prefix : "") + numberRanges[numberRange].nextNumber + (numberRanges[numberRange].suffix ? numberRanges[numberRange].suffix : "") let newNumberRange = numberRanges newNumberRange[numberRange].nextNumber += 1 const {error} = await server.supabase.from("tenants").update({numberRanges: newNumberRange}).eq("id",tenantId) if(error) { console.log(error) } else { return { usedNumber } } } export async function encodeBase64ToNiimbot(base64Png, printDirection = 'top') { // 1️⃣ PNG dekodieren const buffer = Buffer.from(base64Png, 'base64') const png = PNG.sync.read(buffer) // liefert {width, height, data: Uint8Array(RGBA)} const { width, height, data } = png console.log(width, height, data) const cols = printDirection === 'left' ? height : width const rows = printDirection === 'left' ? width : height const rowsData = [] console.log(cols) if (cols % 8 !== 0) throw new Error('Column count must be multiple of 8') // 2️⃣ Zeilenweise durchgehen und Bits bilden for (let row = 0; row < rows; row++) { let isVoid = true let blackPixelsCount = 0 const rowData = new Uint8Array(cols / 8) for (let colOct = 0; colOct < cols / 8; colOct++) { let pixelsOctet = 0 for (let colBit = 0; colBit < 8; colBit++) { const x = printDirection === 'left' ? row : colOct * 8 + colBit const y = printDirection === 'left' ? height - 1 - (colOct * 8 + colBit) : row const idx = (y * width + x) * 4 const lum = 0.299 * data[idx] + 0.587 * data[idx + 1] + 0.114 * data[idx + 2] const isBlack = lum < 128 if (isBlack) { pixelsOctet |= 1 << (7 - colBit) isVoid = false blackPixelsCount++ } } rowData[colOct] = pixelsOctet } const newPart = { dataType: isVoid ? 'void' : 'pixels', rowNumber: row, repeat: 1, rowData: isVoid ? undefined : rowData, blackPixelsCount, } if (rowsData.length === 0) { rowsData.push(newPart) } else { const last = rowsData[rowsData.length - 1] let same = newPart.dataType === last.dataType if (same && newPart.dataType === 'pixels') { same = Utils.u8ArraysEqual(newPart.rowData, last.rowData) } if (same) last.repeat++ else rowsData.push(newPart) if (row % 200 === 199) { rowsData.push({ dataType: 'check', rowNumber: row, repeat: 0, rowData: undefined, blackPixelsCount: 0, }) } } } return { cols, rows, rowsData } } export async function generateLabel(context,width,height) { // Canvas für Hintergrund & Text const canvas = createCanvas(width, height) const ctx = canvas.getContext('2d') // Hintergrund weiß ctx.fillStyle = '#FFFFFF' ctx.fillRect(0, 0, width, height) // Überschrift ctx.fillStyle = '#000000' ctx.font = '32px Arial' ctx.fillText(context.text, 20, 40) // 3) DataMatrix const dataMatrixPng = await bwipjs.toBuffer({ bcid: 'datamatrix', text: context.datamatrix, scale: 6, }) // Basisbild aus Canvas const base = await Sharp(canvas.toBuffer()) .png() .toBuffer() // Alles zusammen compositen const final = await Sharp(base) .composite([ { input: dataMatrixPng, top: 60, left: 20 }, ]) .png() .toBuffer() fs.writeFileSync('label.png', final) // Optional: Base64 zurückgeben (z.B. für API) const base64 = final.toString('base64') return base64 }