Open Changes

This commit is contained in:
2025-12-05 11:49:33 +01:00
parent d6badafeb9
commit 407592680a
10 changed files with 1493 additions and 28 deletions

View File

@@ -1,4 +1,11 @@
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()
@@ -20,4 +27,117 @@ export const useNextNumberRangeNumber = async (server:FastifyInstance, tenantId:
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
}