@risleylima/escpos 0.2.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -766
- package/dist/adapter/index.d.ts +29 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +25 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/network-adapter/index.d.ts +24 -0
- package/dist/network-adapter/index.d.ts.map +1 -0
- package/dist/network-adapter/index.js +263 -0
- package/dist/network-adapter/index.js.map +1 -0
- package/dist/printer/commands-types.d.ts +37 -0
- package/dist/printer/commands-types.d.ts.map +1 -0
- package/dist/printer/commands-types.js +63 -0
- package/dist/printer/commands-types.js.map +1 -0
- package/dist/printer/commands.d.ts +169 -0
- package/dist/printer/commands.d.ts.map +1 -0
- package/dist/printer/commands.js +192 -0
- package/dist/printer/commands.js.map +1 -0
- package/dist/printer/image-loader.d.ts +17 -0
- package/dist/printer/image-loader.d.ts.map +1 -0
- package/dist/printer/image-loader.js +462 -0
- package/dist/printer/image-loader.js.map +1 -0
- package/dist/printer/image.d.ts +43 -0
- package/dist/printer/image.d.ts.map +1 -0
- package/dist/printer/image.js +132 -0
- package/dist/printer/image.js.map +1 -0
- package/dist/printer/index.d.ts +158 -0
- package/dist/printer/index.d.ts.map +1 -0
- package/dist/printer/index.js +703 -0
- package/dist/printer/index.js.map +1 -0
- package/dist/printer/profiles/bematech/mp4200th.d.ts +13 -0
- package/dist/printer/profiles/bematech/mp4200th.d.ts.map +1 -0
- package/dist/printer/profiles/bematech/mp4200th.js +29 -0
- package/dist/printer/profiles/bematech/mp4200th.js.map +1 -0
- package/dist/printer/profiles/custom/bematech-mp4200th.d.ts +13 -0
- package/dist/printer/profiles/custom/bematech-mp4200th.d.ts.map +1 -0
- package/dist/printer/profiles/custom/bematech-mp4200th.js +21 -0
- package/dist/printer/profiles/custom/bematech-mp4200th.js.map +1 -0
- package/dist/printer/profiles/custom/vkp80iii.d.ts +19 -0
- package/dist/printer/profiles/custom/vkp80iii.d.ts.map +1 -0
- package/dist/printer/profiles/custom/vkp80iii.js +87 -0
- package/dist/printer/profiles/custom/vkp80iii.js.map +1 -0
- package/dist/printer/profiles/default.d.ts +7 -0
- package/dist/printer/profiles/default.d.ts.map +1 -0
- package/dist/printer/profiles/default.js +15 -0
- package/dist/printer/profiles/default.js.map +1 -0
- package/dist/printer/profiles/index.d.ts +41 -0
- package/dist/printer/profiles/index.d.ts.map +1 -0
- package/dist/printer/profiles/index.js +98 -0
- package/dist/printer/profiles/index.js.map +1 -0
- package/dist/printer/profiles/merge.d.ts +7 -0
- package/dist/printer/profiles/merge.d.ts.map +1 -0
- package/dist/printer/profiles/merge.js +58 -0
- package/dist/printer/profiles/merge.js.map +1 -0
- package/dist/printer/profiles/types.d.ts +99 -0
- package/dist/printer/profiles/types.d.ts.map +1 -0
- package/dist/printer/profiles/types.js +8 -0
- package/dist/printer/profiles/types.js.map +1 -0
- package/dist/printer/utils.d.ts +9 -0
- package/dist/printer/utils.d.ts.map +1 -0
- package/dist/printer/utils.js +54 -0
- package/dist/printer/utils.js.map +1 -0
- package/dist/serial-adapter/index.d.ts +17 -0
- package/dist/serial-adapter/index.d.ts.map +1 -0
- package/dist/serial-adapter/index.js +172 -0
- package/dist/serial-adapter/index.js.map +1 -0
- package/dist/usb-adapter/index.d.ts +20 -0
- package/dist/usb-adapter/index.d.ts.map +1 -0
- package/dist/usb-adapter/index.js +264 -0
- package/dist/usb-adapter/index.js.map +1 -0
- package/package.json +42 -15
- package/CHANGELOG.md +0 -74
- package/docs/COVERAGE_ANALYSIS.md +0 -98
- package/docs/DEPENDENCIES_REVIEW.md +0 -127
- package/docs/JSDOC_REVIEW.md +0 -122
- package/docs/LIBRARY_OVERVIEW.md +0 -383
- package/docs/PRE_PUBLISH_CHECKLIST.md +0 -331
- package/docs/PUBLIC_API_ANALYSIS.md +0 -223
- package/docs/README.md +0 -37
- package/docs/SERIALPORT_V13_MIGRATION_COMPLETE.md +0 -127
- package/docs/TESTS_IMPLEMENTED.md +0 -129
- package/docs/USB_V2_REVIEW.md +0 -148
- package/docs/VERIFICATION_RESULTS.md +0 -172
- package/docs/VERSIONING.md +0 -102
- package/examples/printTest.js +0 -59
- package/index.js +0 -7
- package/jest.config.js +0 -16
- package/src/adapter/index.js +0 -75
- package/src/printer/commands.js +0 -199
- package/src/printer/image.js +0 -159
- package/src/printer/index.js +0 -621
- package/src/printer/utils.js +0 -58
- package/src/serial-adapter/index.js +0 -198
- package/src/usb-adapter/index.js +0 -283
- package/tests/README.md +0 -67
- package/tests/integration/printer-flow.test.js +0 -128
- package/tests/unit/adapters/adapter.test.js +0 -49
- package/tests/unit/adapters/serial-adapter.test.js +0 -238
- package/tests/unit/adapters/usb-adapter.test.js +0 -319
- package/tests/unit/image/image.test.js +0 -157
- package/tests/unit/printer/buffer.test.js +0 -60
- package/tests/unit/printer/commands.test.js +0 -109
- package/tests/unit/printer/printer.test.js +0 -405
- package/tests/unit/utils/utils.test.js +0 -96
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Image loader: BMP and PNG with Node built-ins; JPEG via jpeg-js, GIF via omggif (port of get-pixels behaviour).
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.loadImageBuffer = loadImageBuffer;
|
|
40
|
+
exports.decodeImageBuffer = decodeImageBuffer;
|
|
41
|
+
exports.loadImagePixels = loadImagePixels;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const zlib = __importStar(require("zlib"));
|
|
44
|
+
const jpeg_js_1 = require("jpeg-js");
|
|
45
|
+
const omggif_1 = require("omggif");
|
|
46
|
+
const resvg_js_1 = require("@resvg/resvg-js");
|
|
47
|
+
const util_1 = require("util");
|
|
48
|
+
const inflate = (0, util_1.promisify)(zlib.inflate);
|
|
49
|
+
/** Parsed data URI: data:[mime];base64,<payload> */
|
|
50
|
+
function parseDataUri(uri) {
|
|
51
|
+
const comma = uri.indexOf(',');
|
|
52
|
+
if (!uri.startsWith('data:') || comma < 0) {
|
|
53
|
+
throw new Error('Invalid data URI format');
|
|
54
|
+
}
|
|
55
|
+
const header = uri.slice(5, comma);
|
|
56
|
+
const payload = uri.slice(comma + 1);
|
|
57
|
+
if (!payload)
|
|
58
|
+
throw new Error('Data URI has no payload');
|
|
59
|
+
const parts = header.split(';').filter(Boolean);
|
|
60
|
+
const mime = (parts[0] || 'application/octet-stream').trim().toLowerCase();
|
|
61
|
+
const isBase64 = parts.some((part) => part.trim().toLowerCase() === 'base64');
|
|
62
|
+
if (isBase64) {
|
|
63
|
+
return { buffer: Buffer.from(payload, 'base64'), mime };
|
|
64
|
+
}
|
|
65
|
+
return { buffer: Buffer.from(decodeURIComponent(payload), 'utf8'), mime };
|
|
66
|
+
}
|
|
67
|
+
function isPath(str) {
|
|
68
|
+
return !str.startsWith('http://') && !str.startsWith('https://') && !str.startsWith('data:');
|
|
69
|
+
}
|
|
70
|
+
async function loadImageBuffer(urlOrPath) {
|
|
71
|
+
if (urlOrPath.startsWith('data:')) {
|
|
72
|
+
return Promise.resolve(parseDataUri(urlOrPath).buffer);
|
|
73
|
+
}
|
|
74
|
+
if (isPath(urlOrPath)) {
|
|
75
|
+
return fs.promises.readFile(urlOrPath);
|
|
76
|
+
}
|
|
77
|
+
const res = await fetch(urlOrPath);
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
throw new Error(`Failed to fetch image: ${res.status} ${res.statusText}`);
|
|
80
|
+
const ab = await res.arrayBuffer();
|
|
81
|
+
return Buffer.from(ab);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parse 24-bit uncompressed BMP. Returns RGB (shape[2]==3).
|
|
85
|
+
*/
|
|
86
|
+
async function parseBmp(buffer) {
|
|
87
|
+
if (buffer.length < 54 || buffer[0] !== 0x42 || buffer[1] !== 0x4d) {
|
|
88
|
+
throw new Error('Invalid BMP: expected BM signature and minimal header');
|
|
89
|
+
}
|
|
90
|
+
const pixelOffset = buffer.readUInt32LE(10);
|
|
91
|
+
const width = buffer.readUInt32LE(18);
|
|
92
|
+
const height = Math.abs(buffer.readInt32LE(22));
|
|
93
|
+
const planes = buffer.readUInt16LE(26);
|
|
94
|
+
const bitCount = buffer.readUInt16LE(28);
|
|
95
|
+
const compression = buffer.readUInt32LE(30);
|
|
96
|
+
if (planes !== 1 || compression !== 0) {
|
|
97
|
+
throw new Error('BMP: only uncompressed supported');
|
|
98
|
+
}
|
|
99
|
+
const palette = [];
|
|
100
|
+
if (bitCount <= 8) {
|
|
101
|
+
const paletteSize = 1 << bitCount;
|
|
102
|
+
for (let i = 0; i < paletteSize; i++) {
|
|
103
|
+
const offset = 54 + i * 4;
|
|
104
|
+
palette.push(buffer[offset + 2], buffer[offset + 1], buffer[offset]); // RGB
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const rowSize = Math.ceil((width * bitCount) / 32) * 4;
|
|
108
|
+
const pixelData = buffer.subarray(pixelOffset);
|
|
109
|
+
const data = new Uint8Array(width * height * 3);
|
|
110
|
+
const flip = buffer.readInt32LE(22) > 0;
|
|
111
|
+
for (let y = 0; y < height; y++) {
|
|
112
|
+
if (y % 100 === 0)
|
|
113
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
114
|
+
const srcY = flip ? height - 1 - y : y;
|
|
115
|
+
const srcRow = pixelData.subarray(srcY * rowSize, (srcY + 1) * rowSize);
|
|
116
|
+
for (let x = 0; x < width; x++) {
|
|
117
|
+
const i = (y * width + x) * 3;
|
|
118
|
+
let r, g, b;
|
|
119
|
+
if (bitCount === 24) {
|
|
120
|
+
r = srcRow[x * 3 + 2];
|
|
121
|
+
g = srcRow[x * 3 + 1];
|
|
122
|
+
b = srcRow[x * 3];
|
|
123
|
+
}
|
|
124
|
+
else if (bitCount === 8) {
|
|
125
|
+
const idx = srcRow[x];
|
|
126
|
+
r = palette[idx * 3];
|
|
127
|
+
g = palette[idx * 3 + 1];
|
|
128
|
+
b = palette[idx * 3 + 2];
|
|
129
|
+
}
|
|
130
|
+
else if (bitCount === 4) {
|
|
131
|
+
const byte = srcRow[x >> 1];
|
|
132
|
+
const idx = (x & 1) === 0 ? byte >> 4 : byte & 0x0f;
|
|
133
|
+
r = palette[idx * 3];
|
|
134
|
+
g = palette[idx * 3 + 1];
|
|
135
|
+
b = palette[idx * 3 + 2];
|
|
136
|
+
}
|
|
137
|
+
else if (bitCount === 1) {
|
|
138
|
+
const byte = srcRow[x >> 3];
|
|
139
|
+
const idx = (byte >> (7 - (x & 7))) & 1;
|
|
140
|
+
r = palette[idx * 3];
|
|
141
|
+
g = palette[idx * 3 + 1];
|
|
142
|
+
b = palette[idx * 3 + 2];
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new Error(`BMP: unsupported bit count ${bitCount}`);
|
|
146
|
+
}
|
|
147
|
+
data[i] = r;
|
|
148
|
+
data[i + 1] = g;
|
|
149
|
+
data[i + 2] = b;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { shape: [width, height, 3], data };
|
|
153
|
+
}
|
|
154
|
+
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
155
|
+
async function parsePng(buffer) {
|
|
156
|
+
if (buffer.length < 24 || buffer.subarray(0, 8).compare(PNG_SIGNATURE) !== 0) {
|
|
157
|
+
throw new Error('Invalid PNG signature');
|
|
158
|
+
}
|
|
159
|
+
let pos = 8;
|
|
160
|
+
let width = 0;
|
|
161
|
+
let height = 0;
|
|
162
|
+
let depth = 0;
|
|
163
|
+
let colorType = 0;
|
|
164
|
+
let interlaceMethod = 0;
|
|
165
|
+
let palette = null;
|
|
166
|
+
let idatChunks = [];
|
|
167
|
+
while (pos < buffer.length) {
|
|
168
|
+
const len = buffer.readUInt32BE(pos);
|
|
169
|
+
const type = buffer.toString('ascii', pos + 4, pos + 8);
|
|
170
|
+
const payload = buffer.subarray(pos + 8, pos + 8 + len);
|
|
171
|
+
pos += 12 + len;
|
|
172
|
+
if (type === 'IHDR') {
|
|
173
|
+
if (len < 13)
|
|
174
|
+
throw new Error('PNG IHDR too short');
|
|
175
|
+
width = payload.readUInt32BE(0);
|
|
176
|
+
height = payload.readUInt32BE(4);
|
|
177
|
+
depth = payload[8];
|
|
178
|
+
colorType = payload[9];
|
|
179
|
+
interlaceMethod = payload[12];
|
|
180
|
+
// Allowed: 0 (Gray), 2 (RGB), 3 (Indexed), 6 (RGBA)
|
|
181
|
+
if (depth !== 8) {
|
|
182
|
+
throw new Error('PNG: only 8-bit depth supported');
|
|
183
|
+
}
|
|
184
|
+
if (interlaceMethod !== 0 && interlaceMethod !== 1) {
|
|
185
|
+
throw new Error(`PNG: unsupported interlace method ${interlaceMethod}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (type === 'PLTE') {
|
|
189
|
+
palette = payload;
|
|
190
|
+
}
|
|
191
|
+
else if (type === 'IDAT') {
|
|
192
|
+
idatChunks.push(payload);
|
|
193
|
+
}
|
|
194
|
+
else if (type === 'IEND') {
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (colorType !== 0 && colorType !== 2 && colorType !== 3 && colorType !== 6) {
|
|
199
|
+
throw new Error(`PNG: unsupported color type ${colorType}`);
|
|
200
|
+
}
|
|
201
|
+
const raw = await inflate(Buffer.concat(idatChunks));
|
|
202
|
+
// Channels in the output buffer (we always normalize to RGB or RGBA)
|
|
203
|
+
let channels = 3;
|
|
204
|
+
if (colorType === 6)
|
|
205
|
+
channels = 4; // RGBA
|
|
206
|
+
if (colorType === 0 || colorType === 3)
|
|
207
|
+
channels = 3; // Normalize Gray/Indexed to RGB
|
|
208
|
+
const bpp = colorType === 0 ? 1 : colorType === 2 ? 3 : colorType === 3 ? 1 : 4;
|
|
209
|
+
const paeth = (left, up, upLeft) => {
|
|
210
|
+
const p = left + up - upLeft;
|
|
211
|
+
const pa = Math.abs(p - left);
|
|
212
|
+
const pb = Math.abs(p - up);
|
|
213
|
+
const pc = Math.abs(p - upLeft);
|
|
214
|
+
return pa <= pb && pa <= pc ? left : pb <= pc ? up : upLeft;
|
|
215
|
+
};
|
|
216
|
+
const unfilter = (src, rowWidth, rowHeight) => {
|
|
217
|
+
const stride = rowWidth * bpp;
|
|
218
|
+
const rowBytes = 1 + stride;
|
|
219
|
+
const needed = rowBytes * rowHeight;
|
|
220
|
+
if (src.length < needed) {
|
|
221
|
+
throw new Error('PNG: corrupted IDAT data');
|
|
222
|
+
}
|
|
223
|
+
const out = new Uint8Array(stride * rowHeight);
|
|
224
|
+
let offset = 0;
|
|
225
|
+
let prevRecon = new Uint8Array(stride);
|
|
226
|
+
for (let y = 0; y < rowHeight; y++) {
|
|
227
|
+
const rowStart = offset;
|
|
228
|
+
const filter = src[rowStart];
|
|
229
|
+
if (filter > 4) {
|
|
230
|
+
throw new Error(`PNG: unsupported filter type ${filter}`);
|
|
231
|
+
}
|
|
232
|
+
const rowIn = src.subarray(rowStart + 1, rowStart + 1 + stride);
|
|
233
|
+
const rowOut = out.subarray(y * stride, (y + 1) * stride);
|
|
234
|
+
for (let i = 0; i < stride; i++) {
|
|
235
|
+
const left = i >= bpp ? rowOut[i - bpp] : 0;
|
|
236
|
+
const up = prevRecon[i] ?? 0;
|
|
237
|
+
const upLeft = i >= bpp ? (prevRecon[i - bpp] ?? 0) : 0;
|
|
238
|
+
let v = rowIn[i];
|
|
239
|
+
switch (filter) {
|
|
240
|
+
case 0:
|
|
241
|
+
break;
|
|
242
|
+
case 1:
|
|
243
|
+
v = (v + left) & 0xff;
|
|
244
|
+
break;
|
|
245
|
+
case 2:
|
|
246
|
+
v = (v + up) & 0xff;
|
|
247
|
+
break;
|
|
248
|
+
case 3:
|
|
249
|
+
v = (v + ((left + up) >>> 1)) & 0xff;
|
|
250
|
+
break;
|
|
251
|
+
case 4:
|
|
252
|
+
v = (v + paeth(left, up, upLeft)) & 0xff;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
rowOut[i] = v;
|
|
256
|
+
}
|
|
257
|
+
prevRecon = rowOut;
|
|
258
|
+
offset += rowBytes;
|
|
259
|
+
}
|
|
260
|
+
return { rows: out, consumed: needed };
|
|
261
|
+
};
|
|
262
|
+
const rawPixels = new Uint8Array(width * height * bpp);
|
|
263
|
+
if (interlaceMethod === 0) {
|
|
264
|
+
const { rows } = unfilter(raw, width, height);
|
|
265
|
+
rawPixels.set(rows);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
const passes = [
|
|
269
|
+
[0, 0, 8, 8],
|
|
270
|
+
[4, 0, 8, 8],
|
|
271
|
+
[0, 4, 4, 8],
|
|
272
|
+
[2, 0, 4, 4],
|
|
273
|
+
[0, 2, 2, 4],
|
|
274
|
+
[1, 0, 2, 2],
|
|
275
|
+
[0, 1, 1, 2],
|
|
276
|
+
];
|
|
277
|
+
let cursor = 0;
|
|
278
|
+
for (const [xStart, yStart, xStep, yStep] of passes) {
|
|
279
|
+
const passWidth = xStart >= width ? 0 : Math.ceil((width - xStart) / xStep);
|
|
280
|
+
const passHeight = yStart >= height ? 0 : Math.ceil((height - yStart) / yStep);
|
|
281
|
+
if (passWidth <= 0 || passHeight <= 0)
|
|
282
|
+
continue;
|
|
283
|
+
const { rows, consumed } = unfilter(raw.subarray(cursor), passWidth, passHeight);
|
|
284
|
+
cursor += consumed;
|
|
285
|
+
for (let py = 0; py < passHeight; py++) {
|
|
286
|
+
for (let px = 0; px < passWidth; px++) {
|
|
287
|
+
const dstX = xStart + px * xStep;
|
|
288
|
+
const dstY = yStart + py * yStep;
|
|
289
|
+
const srcIdx = (py * passWidth + px) * bpp;
|
|
290
|
+
const dstIdx = (dstY * width + dstX) * bpp;
|
|
291
|
+
for (let c = 0; c < bpp; c++) {
|
|
292
|
+
rawPixels[dstIdx + c] = rows[srcIdx + c];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const data = new Uint8Array(width * height * channels);
|
|
299
|
+
for (let y = 0; y < height; y++) {
|
|
300
|
+
if (y % 100 === 0)
|
|
301
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
302
|
+
for (let x = 0; x < width; x++) {
|
|
303
|
+
const outIdx = (y * width + x) * channels;
|
|
304
|
+
const srcIdx = (y * width + x) * bpp;
|
|
305
|
+
if (colorType === 0) {
|
|
306
|
+
const g = rawPixels[srcIdx];
|
|
307
|
+
data[outIdx] = g;
|
|
308
|
+
data[outIdx + 1] = g;
|
|
309
|
+
data[outIdx + 2] = g;
|
|
310
|
+
}
|
|
311
|
+
else if (colorType === 3) {
|
|
312
|
+
if (!palette)
|
|
313
|
+
throw new Error('PNG: Missing palette for indexed image');
|
|
314
|
+
const idx = rawPixels[srcIdx];
|
|
315
|
+
const p = idx * 3;
|
|
316
|
+
data[outIdx] = palette[p];
|
|
317
|
+
data[outIdx + 1] = palette[p + 1];
|
|
318
|
+
data[outIdx + 2] = palette[p + 2];
|
|
319
|
+
}
|
|
320
|
+
else if (colorType === 2) {
|
|
321
|
+
data[outIdx] = rawPixels[srcIdx];
|
|
322
|
+
data[outIdx + 1] = rawPixels[srcIdx + 1];
|
|
323
|
+
data[outIdx + 2] = rawPixels[srcIdx + 2];
|
|
324
|
+
}
|
|
325
|
+
else if (colorType === 6) {
|
|
326
|
+
data[outIdx] = rawPixels[srcIdx];
|
|
327
|
+
data[outIdx + 1] = rawPixels[srcIdx + 1];
|
|
328
|
+
data[outIdx + 2] = rawPixels[srcIdx + 2];
|
|
329
|
+
data[outIdx + 3] = rawPixels[srcIdx + 3];
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
throw new Error(`PNG: unsupported color type ${colorType}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return { shape: [width, height, channels], data };
|
|
337
|
+
}
|
|
338
|
+
function isSvgBuffer(buffer) {
|
|
339
|
+
const start = buffer.subarray(0, Math.min(buffer.length, 2048)).toString('utf8').trimStart();
|
|
340
|
+
return start.startsWith('<svg') || (start.startsWith('<?xml') && start.includes('<svg'));
|
|
341
|
+
}
|
|
342
|
+
async function parseSvg(buffer) {
|
|
343
|
+
if (!isSvgBuffer(buffer)) {
|
|
344
|
+
throw new Error('Invalid SVG: expected <svg root element');
|
|
345
|
+
}
|
|
346
|
+
const svgText = buffer.toString('utf8');
|
|
347
|
+
const resvg = new resvg_js_1.Resvg(svgText, {
|
|
348
|
+
fitTo: { mode: 'original' },
|
|
349
|
+
background: 'white',
|
|
350
|
+
});
|
|
351
|
+
const pngData = resvg.render().asPng();
|
|
352
|
+
const parsed = await parsePng(Buffer.from(pngData));
|
|
353
|
+
// Flatten RGBA over white background for better thermal binarization stability.
|
|
354
|
+
if (parsed.shape[2] === 4) {
|
|
355
|
+
const [w, h] = parsed.shape;
|
|
356
|
+
const rgb = new Uint8Array(w * h * 3);
|
|
357
|
+
for (let i = 0, j = 0; i < parsed.data.length; i += 4, j += 3) {
|
|
358
|
+
const r = parsed.data[i];
|
|
359
|
+
const g = parsed.data[i + 1];
|
|
360
|
+
const b = parsed.data[i + 2];
|
|
361
|
+
const a = parsed.data[i + 3];
|
|
362
|
+
rgb[j] = Math.round((r * a + 255 * (255 - a)) / 255);
|
|
363
|
+
rgb[j + 1] = Math.round((g * a + 255 * (255 - a)) / 255);
|
|
364
|
+
rgb[j + 2] = Math.round((b * a + 255 * (255 - a)) / 255);
|
|
365
|
+
}
|
|
366
|
+
return { shape: [w, h, 3], data: rgb };
|
|
367
|
+
}
|
|
368
|
+
return parsed;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Decode JPEG to RGB (shape[2]==3) using jpeg-js.
|
|
372
|
+
*/
|
|
373
|
+
async function parseJpeg(buffer) {
|
|
374
|
+
if (buffer.length < 2 || buffer[0] !== 0xff || buffer[1] !== 0xd8) {
|
|
375
|
+
throw new Error('Invalid JPEG: expected SOI marker FF D8');
|
|
376
|
+
}
|
|
377
|
+
// jpeg-js decode is synchronous but we wrap it to maintain API consistency
|
|
378
|
+
const raw = (0, jpeg_js_1.decode)(buffer, { useTArray: true, formatAsRGBA: false });
|
|
379
|
+
const data = raw.data instanceof Uint8Array ? raw.data : new Uint8Array(raw.data);
|
|
380
|
+
return { shape: [raw.width, raw.height, 3], data };
|
|
381
|
+
}
|
|
382
|
+
/** GIF signature: GIF87a or GIF89a */
|
|
383
|
+
function isGifBuffer(buffer) {
|
|
384
|
+
return (buffer.length >= 6 &&
|
|
385
|
+
buffer[0] === 0x47 &&
|
|
386
|
+
buffer[1] === 0x49 &&
|
|
387
|
+
buffer[2] === 0x46 &&
|
|
388
|
+
buffer[3] === 0x38 &&
|
|
389
|
+
(buffer[4] === 0x37 || buffer[4] === 0x39) &&
|
|
390
|
+
buffer[5] === 0x61);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Decode GIF to RGBA (shape[2]==4) using omggif. Returns the first frame only (static or animated).
|
|
394
|
+
*/
|
|
395
|
+
async function parseGif(buffer) {
|
|
396
|
+
if (!isGifBuffer(buffer)) {
|
|
397
|
+
throw new Error('Invalid GIF: expected GIF87a or GIF89a signature');
|
|
398
|
+
}
|
|
399
|
+
const reader = new omggif_1.GifReader(new Uint8Array(buffer));
|
|
400
|
+
const width = reader.width;
|
|
401
|
+
const height = reader.height;
|
|
402
|
+
const numFrames = reader.numFrames();
|
|
403
|
+
if (numFrames === 0) {
|
|
404
|
+
throw new Error('GIF has no image frames');
|
|
405
|
+
}
|
|
406
|
+
const data = new Uint8Array(width * height * 4);
|
|
407
|
+
reader.decodeAndBlitFrameRGBA(0, data);
|
|
408
|
+
return { shape: [width, height, 4], data };
|
|
409
|
+
}
|
|
410
|
+
async function decodeImageBuffer(buffer, mimeOrExt) {
|
|
411
|
+
const hint = (mimeOrExt ?? '').toLowerCase();
|
|
412
|
+
if (isSvgBuffer(buffer)) {
|
|
413
|
+
return parseSvg(buffer);
|
|
414
|
+
}
|
|
415
|
+
if (buffer[0] === 0x42 && buffer[1] === 0x4d) {
|
|
416
|
+
return parseBmp(buffer);
|
|
417
|
+
}
|
|
418
|
+
if (buffer.length >= 8 && buffer.subarray(0, 8).compare(PNG_SIGNATURE) === 0) {
|
|
419
|
+
return parsePng(buffer);
|
|
420
|
+
}
|
|
421
|
+
if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xd8) {
|
|
422
|
+
return parseJpeg(buffer);
|
|
423
|
+
}
|
|
424
|
+
if (buffer.length >= 6 && isGifBuffer(buffer)) {
|
|
425
|
+
return parseGif(buffer);
|
|
426
|
+
}
|
|
427
|
+
if (hint.includes('png') || hint.endsWith('.png')) {
|
|
428
|
+
return parsePng(buffer);
|
|
429
|
+
}
|
|
430
|
+
if (hint.includes('bmp') || hint.endsWith('.bmp')) {
|
|
431
|
+
return parseBmp(buffer);
|
|
432
|
+
}
|
|
433
|
+
if (hint.includes('jpeg') || hint.includes('jpg') || hint.endsWith('.jpg') || hint.endsWith('.jpeg')) {
|
|
434
|
+
return parseJpeg(buffer);
|
|
435
|
+
}
|
|
436
|
+
if (hint.includes('gif') || hint.endsWith('.gif')) {
|
|
437
|
+
return parseGif(buffer);
|
|
438
|
+
}
|
|
439
|
+
if (hint.includes('svg') || hint.endsWith('.svg')) {
|
|
440
|
+
return parseSvg(buffer);
|
|
441
|
+
}
|
|
442
|
+
throw new Error('Unsupported image format: use BMP, PNG, JPEG, GIF, or SVG; or pass pixels to new Image(pixels)');
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Load pixels from URL, path, data URI, or in-memory Buffer (like get-pixels).
|
|
446
|
+
* - string path / http(s) URL: type optional (inferred from extension or content).
|
|
447
|
+
* - data: URI: type taken from URI (e.g. data:image/png;base64,...).
|
|
448
|
+
* - Buffer: type required when format cannot be inferred from magic bytes.
|
|
449
|
+
*/
|
|
450
|
+
async function loadImagePixels(urlOrPathOrBuffer, type) {
|
|
451
|
+
if (Buffer.isBuffer(urlOrPathOrBuffer)) {
|
|
452
|
+
return decodeImageBuffer(urlOrPathOrBuffer, type);
|
|
453
|
+
}
|
|
454
|
+
const str = urlOrPathOrBuffer;
|
|
455
|
+
if (str.startsWith('data:')) {
|
|
456
|
+
const { buffer, mime } = parseDataUri(str);
|
|
457
|
+
return decodeImageBuffer(buffer, mime);
|
|
458
|
+
}
|
|
459
|
+
const buffer = await loadImageBuffer(str);
|
|
460
|
+
return decodeImageBuffer(buffer, type);
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=image-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-loader.js","sourceRoot":"","sources":["../../src/printer/image-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface PixelsObject {
|
|
2
|
+
shape: [number, number, number];
|
|
3
|
+
data: Uint8Array;
|
|
4
|
+
}
|
|
5
|
+
export interface ImageProcessingOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Binarization mode.
|
|
8
|
+
* - threshold: fixed threshold (fast, deterministic)
|
|
9
|
+
* - floydSteinberg: error-diffusion dithering (better gradients/logos/photos)
|
|
10
|
+
*/
|
|
11
|
+
mode?: 'threshold' | 'floydSteinberg';
|
|
12
|
+
/** Luma threshold for black/white split (0-255). Default: 200 */
|
|
13
|
+
threshold?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class Image {
|
|
16
|
+
pixels: PixelsObject;
|
|
17
|
+
data: number[];
|
|
18
|
+
size: {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
colors: number;
|
|
22
|
+
};
|
|
23
|
+
options: Required<ImageProcessingOptions>;
|
|
24
|
+
constructor(pixels: PixelsObject, options?: ImageProcessingOptions);
|
|
25
|
+
private toLumaArray;
|
|
26
|
+
private binarizeByThreshold;
|
|
27
|
+
private binarizeWithFloydSteinberg;
|
|
28
|
+
toBitmap(density?: number): {
|
|
29
|
+
data: number[][];
|
|
30
|
+
density: number;
|
|
31
|
+
};
|
|
32
|
+
toRaster(): {
|
|
33
|
+
data: number[];
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Load image from file path, URL, data URI (data:image/png;base64,...), or in-memory Buffer.
|
|
39
|
+
* Supports BMP (24-bit), PNG (8-bit RGB/RGBA), JPEG, and GIF (first frame, RGBA). For Buffer input, type is required if format cannot be inferred.
|
|
40
|
+
*/
|
|
41
|
+
static load(urlOrPathOrBuffer: string | Buffer, typeOrOptions?: string | ImageProcessingOptions, maybeOptions?: ImageProcessingOptions): Promise<Image>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/printer/image.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,gBAAgB,CAAC;IACtC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,KAAK;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,OAAO,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC;gBAE9B,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,sBAAsB;IA6BlE,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,0BAA0B;IA0BlC,QAAQ,CAAC,OAAO,GAAE,MAAW,GAAG;QAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAqBrE,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAsB7D;;;OAGG;IACH,MAAM,CAAC,IAAI,CACT,iBAAiB,EAAE,MAAM,GAAG,MAAM,EAClC,aAAa,CAAC,EAAE,MAAM,GAAG,sBAAsB,EAC/C,YAAY,CAAC,EAAE,sBAAsB,GACpC,OAAO,CAAC,KAAK,CAAC;CAKlB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Image = void 0;
|
|
4
|
+
const image_loader_1 = require("./image-loader");
|
|
5
|
+
class Image {
|
|
6
|
+
constructor(pixels, options) {
|
|
7
|
+
if (!pixels || typeof pixels !== 'object') {
|
|
8
|
+
throw new TypeError('Image(pixels): pixels must be an object { shape: [w,h,c], data: Uint8Array }');
|
|
9
|
+
}
|
|
10
|
+
if (!Array.isArray(pixels.shape) || pixels.shape.length < 3) {
|
|
11
|
+
throw new TypeError('Image(pixels): pixels.shape must be an array [width, height, colors]');
|
|
12
|
+
}
|
|
13
|
+
if (!pixels.data || !(pixels.data instanceof Uint8Array)) {
|
|
14
|
+
throw new TypeError('Image(pixels): pixels.data must be a Uint8Array');
|
|
15
|
+
}
|
|
16
|
+
this.pixels = pixels;
|
|
17
|
+
this.data = [];
|
|
18
|
+
this.options = {
|
|
19
|
+
mode: options?.mode ?? 'threshold',
|
|
20
|
+
threshold: Math.max(0, Math.min(255, Math.floor(options?.threshold ?? 200))),
|
|
21
|
+
};
|
|
22
|
+
this.size = {
|
|
23
|
+
width: this.pixels.shape[0],
|
|
24
|
+
height: this.pixels.shape[1],
|
|
25
|
+
colors: this.pixels.shape[2],
|
|
26
|
+
};
|
|
27
|
+
const luma = this.toLumaArray();
|
|
28
|
+
this.data =
|
|
29
|
+
this.options.mode === 'floydSteinberg'
|
|
30
|
+
? this.binarizeWithFloydSteinberg(luma)
|
|
31
|
+
: this.binarizeByThreshold(luma);
|
|
32
|
+
}
|
|
33
|
+
toLumaArray() {
|
|
34
|
+
const values = [];
|
|
35
|
+
for (let i = 0; i < this.pixels.data.length; i += this.size.colors) {
|
|
36
|
+
const r = this.pixels.data[i] ?? 0;
|
|
37
|
+
const g = this.pixels.data[i + 1] ?? 0;
|
|
38
|
+
const b = this.pixels.data[i + 2] ?? 0;
|
|
39
|
+
const a = this.pixels.data[i + 3] ?? 255;
|
|
40
|
+
if (a === 0) {
|
|
41
|
+
values.push(255);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Perceptual luma (BT.601).
|
|
45
|
+
values.push(0.299 * r + 0.587 * g + 0.114 * b);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return values;
|
|
49
|
+
}
|
|
50
|
+
binarizeByThreshold(luma) {
|
|
51
|
+
const t = this.options.threshold;
|
|
52
|
+
return luma.map((v) => (v <= t ? 1 : 0));
|
|
53
|
+
}
|
|
54
|
+
binarizeWithFloydSteinberg(luma) {
|
|
55
|
+
const width = this.size.width;
|
|
56
|
+
const height = this.size.height;
|
|
57
|
+
const t = this.options.threshold;
|
|
58
|
+
const work = luma.slice();
|
|
59
|
+
const out = new Array(work.length).fill(0);
|
|
60
|
+
for (let y = 0; y < height; y++) {
|
|
61
|
+
for (let x = 0; x < width; x++) {
|
|
62
|
+
const idx = y * width + x;
|
|
63
|
+
const oldVal = work[idx];
|
|
64
|
+
const newVal = oldVal <= t ? 0 : 255;
|
|
65
|
+
const err = oldVal - newVal;
|
|
66
|
+
out[idx] = newVal === 0 ? 1 : 0;
|
|
67
|
+
if (x + 1 < width)
|
|
68
|
+
work[idx + 1] += (err * 7) / 16;
|
|
69
|
+
if (y + 1 < height) {
|
|
70
|
+
if (x > 0)
|
|
71
|
+
work[idx + width - 1] += (err * 3) / 16;
|
|
72
|
+
work[idx + width] += (err * 5) / 16;
|
|
73
|
+
if (x + 1 < width)
|
|
74
|
+
work[idx + width + 1] += err / 16;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
toBitmap(density = 24) {
|
|
81
|
+
const result = [];
|
|
82
|
+
const c = density / 8;
|
|
83
|
+
const n = Math.ceil(this.size.height / density);
|
|
84
|
+
for (let y = 0; y < n; y++) {
|
|
85
|
+
const ld = (result[y] = []);
|
|
86
|
+
for (let x = 0; x < this.size.width; x++) {
|
|
87
|
+
for (let b = 0; b < density; b++) {
|
|
88
|
+
const i = x * c + (b >> 3);
|
|
89
|
+
if (ld[i] === undefined)
|
|
90
|
+
ld[i] = 0;
|
|
91
|
+
const l = y * density + b;
|
|
92
|
+
if (l < this.size.height && this.data[l * this.size.width + x]) {
|
|
93
|
+
ld[i] += 0x80 >> (b & 0x7);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { data: result, density };
|
|
99
|
+
}
|
|
100
|
+
toRaster() {
|
|
101
|
+
const width = this.size.width;
|
|
102
|
+
const height = this.size.height;
|
|
103
|
+
const data = this.data;
|
|
104
|
+
const n = Math.ceil(width / 8);
|
|
105
|
+
const result = [];
|
|
106
|
+
for (let y = 0; y < height; y++) {
|
|
107
|
+
for (let x = 0; x < n; x++) {
|
|
108
|
+
if (result[y * n + x] === undefined)
|
|
109
|
+
result[y * n + x] = 0;
|
|
110
|
+
for (let b = 0; b < 8; b++) {
|
|
111
|
+
const i = x * 8 + b;
|
|
112
|
+
const c = x * 8 + b;
|
|
113
|
+
if (c < width && data[y * width + i]) {
|
|
114
|
+
result[y * n + x] += 0x80 >> (b & 0x7);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { data: result, width: n, height };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Load image from file path, URL, data URI (data:image/png;base64,...), or in-memory Buffer.
|
|
123
|
+
* Supports BMP (24-bit), PNG (8-bit RGB/RGBA), JPEG, and GIF (first frame, RGBA). For Buffer input, type is required if format cannot be inferred.
|
|
124
|
+
*/
|
|
125
|
+
static load(urlOrPathOrBuffer, typeOrOptions, maybeOptions) {
|
|
126
|
+
const type = typeof typeOrOptions === 'string' ? typeOrOptions : undefined;
|
|
127
|
+
const options = typeof typeOrOptions === 'string' ? maybeOptions : typeOrOptions;
|
|
128
|
+
return (0, image_loader_1.loadImagePixels)(urlOrPathOrBuffer, type).then((pixels) => new Image(pixels, options));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.Image = Image;
|
|
132
|
+
//# sourceMappingURL=image.js.map
|