label-printer 0.7.4 → 0.7.6

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/dist/index.mjs CHANGED
@@ -305,12 +305,13 @@ function parsePNG(buffer2) {
305
305
  }
306
306
  const scanlineLength = width * bytesPerPixel;
307
307
  const data = new Uint8Array(width * height * outputChannels);
308
+ let prevUnfilteredScanline = Buffer.alloc(scanlineLength);
308
309
  for (let y = 0; y < height; y++) {
309
310
  const scanlineStart = y * (scanlineLength + 1);
310
311
  const filterType = decompressedData[scanlineStart];
311
312
  const scanline = decompressedData.subarray(scanlineStart + 1, scanlineStart + 1 + scanlineLength);
312
- const prevScanline = y > 0 ? decompressedData.subarray((y - 1) * (scanlineLength + 1) + 1, (y - 1) * (scanlineLength + 1) + 1 + scanlineLength) : Buffer.alloc(scanlineLength);
313
- const unfilteredScanline = applyPNGFilter(filterType, scanline, prevScanline, bytesPerPixel);
313
+ const unfilteredScanline = applyPNGFilter(filterType, scanline, prevUnfilteredScanline, bytesPerPixel);
314
+ prevUnfilteredScanline = unfilteredScanline;
314
315
  for (let x = 0; x < width; x++) {
315
316
  const outIdx = (y * width + x) * outputChannels;
316
317
  if (colorType === 0) {
@@ -804,7 +805,8 @@ var ImageProcessor_default = ImageProcessor;
804
805
  // src/helpers/ImageUtils.ts
805
806
  var BLACK_PIXEL = 0;
806
807
  var WHITE_PIXEL = 1;
807
- var DEFAULT_THRESHOLD = 200;
808
+ var DEFAULT_THRESHOLD = 240;
809
+ var DEFAULT_CROP_ALPHA_THRESHOLD = 16;
808
810
  var ImageUtils = class {
809
811
  /**
810
812
  * Get pixel information about an image
@@ -823,11 +825,11 @@ var ImageUtils = class {
823
825
  * input size as only downscaling is performed
824
826
  *
825
827
  * @param image Image to process
826
- * @param destinationWidth Width of the ouput bitmap
828
+ * @param destinationWidth Width of the output bitmap
827
829
  * @param destinationHeight Height of the output bitmap
828
830
  * @returns
829
831
  */
830
- static getBWBitmap(image2, destinationWidth, destinationHeight) {
832
+ static getBWBitmap(image2, destinationWidth, destinationHeight, threshold, lsbFirst = false) {
831
833
  return __async(this, null, function* () {
832
834
  const {
833
835
  data,
@@ -838,43 +840,103 @@ var ImageUtils = class {
838
840
  image2,
839
841
  destinationWidth != null && destinationHeight != null ? { width: destinationWidth, height: destinationHeight } : void 0
840
842
  );
841
- const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
843
+ let cropX0 = 0;
844
+ let cropY0 = 0;
845
+ let cropX1 = width - 1;
846
+ let cropY1 = height - 1;
847
+ if (bitsPerPixel > 3) {
848
+ let found = false;
849
+ let minX = width;
850
+ let minY = height;
851
+ let maxX = -1;
852
+ let maxY = -1;
853
+ for (let y = 0; y < height; y++) {
854
+ for (let x = 0; x < width; x++) {
855
+ const a = data[y * width * bitsPerPixel + x * bitsPerPixel + 3];
856
+ if (a >= DEFAULT_CROP_ALPHA_THRESHOLD) {
857
+ found = true;
858
+ if (x < minX) minX = x;
859
+ if (y < minY) minY = y;
860
+ if (x > maxX) maxX = x;
861
+ if (y > maxY) maxY = y;
862
+ }
863
+ }
864
+ }
865
+ if (found) {
866
+ cropX0 = minX;
867
+ cropY0 = minY;
868
+ cropX1 = maxX;
869
+ cropY1 = maxY;
870
+ }
871
+ }
872
+ const cropWidth = cropX1 - cropX0 + 1;
873
+ const cropHeight = cropY1 - cropY0 + 1;
874
+ const dim = getSizePreserveAspect(cropWidth, cropHeight, destinationWidth, destinationHeight);
842
875
  const dWidth = dim.width;
843
876
  const dHeight = dim.height;
844
877
  const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
845
878
  const dividableDWidth = dWidth + differenceToDividable;
846
- const bitmapData = new Uint8Array(dividableDWidth * dHeight);
879
+ const luminances = new Uint8Array(dividableDWidth * dHeight);
847
880
  let destinationIndex = 0;
848
881
  for (let h = 0; h < dHeight; h++) {
849
- const originalHeight = Math.round(h * (height - 1) / (dHeight - 1));
882
+ const srcY0 = cropY0 + Math.floor(h * cropHeight / dHeight);
883
+ const srcY1 = Math.max(srcY0, cropY0 + Math.floor((h + 1) * cropHeight / dHeight) - 1);
850
884
  for (let w = 0; w < dWidth; w++) {
851
- const originalWidth = Math.round(w * (width - 1) / (dWidth - 1));
852
- const baseIndex = originalHeight * width * bitsPerPixel + originalWidth * bitsPerPixel;
853
- const r = data[baseIndex];
854
- const g = data[baseIndex + 1];
855
- const b = data[baseIndex + 2];
856
- const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255;
857
- const alpha = a / 255;
858
- const rC = r * alpha + 255 * (1 - alpha);
859
- const gC = g * alpha + 255 * (1 - alpha);
860
- const bC = b * alpha + 255 * (1 - alpha);
861
- const luminance = 0.299 * rC + 0.587 * gC + 0.114 * bC;
862
- if (luminance > DEFAULT_THRESHOLD) {
863
- bitmapData[destinationIndex] = WHITE_PIXEL;
864
- } else {
865
- bitmapData[destinationIndex] = BLACK_PIXEL;
885
+ const srcX0 = cropX0 + Math.floor(w * cropWidth / dWidth);
886
+ const srcX1 = Math.max(srcX0, cropX0 + Math.floor((w + 1) * cropWidth / dWidth) - 1);
887
+ let lumSum = 0;
888
+ let count = 0;
889
+ let opaqueCount = 0;
890
+ let opaqueLumSum = 0;
891
+ let opaqueWeightSum = 0;
892
+ let minOpaqueLum = 255;
893
+ for (let sy = srcY0; sy <= srcY1; sy++) {
894
+ for (let sx = srcX0; sx <= srcX1; sx++) {
895
+ const baseIndex = sy * width * bitsPerPixel + sx * bitsPerPixel;
896
+ const r = data[baseIndex];
897
+ const g = data[baseIndex + 1];
898
+ const b = data[baseIndex + 2];
899
+ const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255;
900
+ const alpha = a / 255;
901
+ const rC = r * alpha + 255 * (1 - alpha);
902
+ const gC = g * alpha + 255 * (1 - alpha);
903
+ const bC = b * alpha + 255 * (1 - alpha);
904
+ lumSum += 0.299 * rC + 0.587 * gC + 0.114 * bC;
905
+ count += 1;
906
+ if (a > 0) {
907
+ opaqueCount += 1;
908
+ const lum = 0.299 * r + 0.587 * g + 0.114 * b;
909
+ opaqueLumSum += lum * alpha;
910
+ opaqueWeightSum += alpha;
911
+ if (lum < minOpaqueLum) minOpaqueLum = lum;
912
+ }
913
+ }
866
914
  }
915
+ const avgLum = count > 0 ? lumSum / count : 255;
916
+ const avgOpaqueLum = opaqueWeightSum > 0 ? opaqueLumSum / opaqueWeightSum : 255;
917
+ const opaqueRatio = count > 0 ? opaqueCount / count : 0;
918
+ const luminance = opaqueCount === 0 ? 255 : opaqueRatio < 0.25 ? minOpaqueLum : avgOpaqueLum;
919
+ luminances[destinationIndex] = Math.max(0, Math.min(255, Math.round(luminance)));
867
920
  destinationIndex += 1;
868
921
  }
869
922
  for (let i = 0; i < differenceToDividable; i++) {
870
- bitmapData[destinationIndex] = WHITE_PIXEL;
923
+ luminances[destinationIndex] = 255;
871
924
  destinationIndex += 1;
872
925
  }
873
926
  }
927
+ const thresholdValue = threshold != null ? threshold : this.otsuThreshold(luminances, dWidth, dividableDWidth, dHeight);
928
+ const bitmapData = new Uint8Array(dividableDWidth * dHeight);
929
+ for (let h = 0; h < dHeight; h++) {
930
+ const rowOffset = h * dividableDWidth;
931
+ for (let w = 0; w < dividableDWidth; w++) {
932
+ const idx = rowOffset + w;
933
+ bitmapData[idx] = luminances[idx] > thresholdValue ? WHITE_PIXEL : BLACK_PIXEL;
934
+ }
935
+ }
874
936
  const byteArrays = this.chunk(bitmapData, 8);
875
937
  const widthInBytes = dividableDWidth / 8;
876
- const bytes = byteArrays.map(this.bitsToByte);
877
- const finalBytes = new Uint8Array(bytes);
938
+ const bytes2 = byteArrays.map((b) => this.bitsToByte(b, lsbFirst));
939
+ const finalBytes = new Uint8Array(bytes2);
878
940
  return {
879
941
  width: widthInBytes,
880
942
  height: dHeight,
@@ -882,6 +944,40 @@ var ImageUtils = class {
882
944
  };
883
945
  });
884
946
  }
947
+ static otsuThreshold(luminances, contentWidth, rowWidth, height) {
948
+ const hist = new Uint32Array(256);
949
+ let total = 0;
950
+ for (let y = 0; y < height; y++) {
951
+ const rowOffset = y * rowWidth;
952
+ for (let x = 0; x < contentWidth; x++) {
953
+ hist[luminances[rowOffset + x]] += 1;
954
+ total += 1;
955
+ }
956
+ }
957
+ if (total === 0) return DEFAULT_THRESHOLD;
958
+ let sum = 0;
959
+ for (let t = 0; t < 256; t++) sum += t * hist[t];
960
+ let sumB = 0;
961
+ let wB = 0;
962
+ let wF = 0;
963
+ let maxBetween = -1;
964
+ let threshold = DEFAULT_THRESHOLD;
965
+ for (let t = 0; t < 256; t++) {
966
+ wB += hist[t];
967
+ if (wB === 0) continue;
968
+ wF = total - wB;
969
+ if (wF === 0) break;
970
+ sumB += t * hist[t];
971
+ const mB = sumB / wB;
972
+ const mF = (sum - sumB) / wF;
973
+ const between = wB * wF * (mB - mF) * (mB - mF);
974
+ if (between > maxBetween) {
975
+ maxBetween = between;
976
+ threshold = t;
977
+ }
978
+ }
979
+ return threshold;
980
+ }
885
981
  /**
886
982
  * Splits an array into chunks.
887
983
  * @param originalArray
@@ -901,13 +997,95 @@ var ImageUtils = class {
901
997
  * @param bits
902
998
  * @returns
903
999
  */
904
- static bitsToByte(bits) {
1000
+ static bitsToByte(bits, lsbFirst) {
905
1001
  let byteValue = 0;
1002
+ if (lsbFirst) {
1003
+ for (let i = 0; i < bits.length; i++) {
1004
+ byteValue |= (bits[i] & 1) << i;
1005
+ }
1006
+ return byteValue;
1007
+ }
906
1008
  for (let i = 0; i < bits.length; i++) {
907
- byteValue = byteValue << 1 | bits[i];
1009
+ byteValue = byteValue << 1 | bits[i] & 1;
908
1010
  }
909
1011
  return byteValue;
910
1012
  }
1013
+ static dilateBWBitmap(bitmap2, iterations = 1) {
1014
+ let current = bitmap2;
1015
+ for (let i = 0; i < iterations; i++) {
1016
+ current = this.dilateOnce(current);
1017
+ }
1018
+ return current;
1019
+ }
1020
+ static bwBitmapToPBM(bitmap2, widthDots2) {
1021
+ var _a;
1022
+ const widthBytes = bitmap2.width;
1023
+ const height = bitmap2.height;
1024
+ const widthBits = widthDots2 != null ? widthDots2 : widthBytes * 8;
1025
+ const header = `P4
1026
+ ${widthBits} ${height}
1027
+ `;
1028
+ const headerBytes = new TextEncoder().encode(header);
1029
+ const rowBytes = Math.ceil(widthBits / 8);
1030
+ const out = new Uint8Array(headerBytes.length + rowBytes * height);
1031
+ out.set(headerBytes, 0);
1032
+ const src = bitmap2.bytes;
1033
+ let offset = headerBytes.length;
1034
+ for (let y = 0; y < height; y++) {
1035
+ const rowStart = y * widthBytes;
1036
+ for (let xb = 0; xb < rowBytes; xb++) {
1037
+ const b = (_a = src[rowStart + xb]) != null ? _a : 255;
1038
+ out[offset++] = ~b & 255;
1039
+ }
1040
+ const extraBits = rowBytes * 8 - widthBits;
1041
+ if (extraBits > 0) {
1042
+ const mask = 255 << extraBits;
1043
+ out[offset - 1] = out[offset - 1] & mask;
1044
+ }
1045
+ }
1046
+ return out;
1047
+ }
1048
+ static saveBWBitmapAsPBM(bitmap, filePath, widthDots) {
1049
+ return __async(this, null, function* () {
1050
+ if (typeof window !== "undefined") {
1051
+ throw new Error("pbm-export-not-supported-in-browser");
1052
+ }
1053
+ const fs = yield eval("require")("fs");
1054
+ const bytes = this.bwBitmapToPBM(bitmap, widthDots);
1055
+ fs.writeFileSync(filePath, bytes);
1056
+ });
1057
+ }
1058
+ static dilateOnce(bitmap2) {
1059
+ const widthBytes = bitmap2.width;
1060
+ const widthBits = widthBytes * 8;
1061
+ const height = bitmap2.height;
1062
+ const src = bitmap2.bytes;
1063
+ const dst = new Uint8Array(src.length);
1064
+ const getBit = (x, y) => {
1065
+ if (x < 0 || y < 0 || x >= widthBits || y >= height) return 1;
1066
+ const byteIndex = y * widthBytes + (x >> 3);
1067
+ const bitIndex = 7 - (x & 7);
1068
+ return src[byteIndex] >> bitIndex & 1;
1069
+ };
1070
+ const setBit = (x, y, value) => {
1071
+ if (x < 0 || y < 0 || x >= widthBits || y >= height) return;
1072
+ const byteIndex = y * widthBytes + (x >> 3);
1073
+ const mask = 1 << 7 - (x & 7);
1074
+ if (value === 1) dst[byteIndex] |= mask;
1075
+ else dst[byteIndex] &= ~mask & 255;
1076
+ };
1077
+ for (let y = 0; y < height; y++) {
1078
+ for (let x = 0; x < widthBits; x++) {
1079
+ const isBlack = getBit(x, y) === 0 || getBit(x - 1, y) === 0 || getBit(x + 1, y) === 0 || getBit(x, y - 1) === 0 || getBit(x, y + 1) === 0 || getBit(x - 1, y - 1) === 0 || getBit(x + 1, y - 1) === 0 || getBit(x - 1, y + 1) === 0 || getBit(x + 1, y + 1) === 0;
1080
+ setBit(x, y, isBlack ? 0 : 1);
1081
+ }
1082
+ }
1083
+ return {
1084
+ width: widthBytes,
1085
+ height,
1086
+ bytes: dst
1087
+ };
1088
+ }
911
1089
  };
912
1090
 
913
1091
  // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
@@ -919,9 +1097,9 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
919
1097
  * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by
920
1098
  * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values
921
1099
  */
922
- constructor(bitmap, x, y, mode) {
1100
+ constructor(bitmap2, x, y, mode) {
923
1101
  super(x, y);
924
- this.bitmap = bitmap;
1102
+ this.bitmap = bitmap2;
925
1103
  this.mode = mode != null ? mode : "overwrite";
926
1104
  }
927
1105
  get commandString() {
@@ -962,8 +1140,8 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
962
1140
  */
963
1141
  static forImageUrl(image2, x, y, imageWidth, imageHeight, mode) {
964
1142
  return __async(this, null, function* () {
965
- const bitmap = yield ImageUtils.getBWBitmap(image2, imageWidth, imageHeight);
966
- return new _TSPLBitmapCommand(bitmap, x, y, mode);
1143
+ const bitmap2 = yield ImageUtils.getBWBitmap(image2, imageWidth, imageHeight);
1144
+ return new _TSPLBitmapCommand(bitmap2, x, y, mode);
967
1145
  });
968
1146
  }
969
1147
  };
@@ -1348,6 +1526,16 @@ var Printer = class {
1348
1526
  yield command.writeTo(this.device);
1349
1527
  });
1350
1528
  }
1529
+ /**
1530
+ * Writes a raw string to the printer
1531
+ * @param text String to send to the printer
1532
+ */
1533
+ writeRawString(text) {
1534
+ return __async(this, null, function* () {
1535
+ if (!this.device.opened) yield this.device.openAndConfigure();
1536
+ yield this.device.writeString(text);
1537
+ });
1538
+ }
1351
1539
  /**
1352
1540
  * Check if the device is indeed a printer
1353
1541
  * @param device
@@ -1372,9 +1560,9 @@ var StringUtils = class {
1372
1560
  * @param bytes Bytes to decode
1373
1561
  * @returns A string
1374
1562
  */
1375
- toString(bytes) {
1563
+ toString(bytes2) {
1376
1564
  let decoder = new TextDecoder();
1377
- return decoder.decode(bytes);
1565
+ return decoder.decode(bytes2);
1378
1566
  }
1379
1567
  };
1380
1568
  var isWhitespace = (text) => text.trim() === "";
@@ -1447,6 +1635,10 @@ var UsbDevice = class {
1447
1635
  var _a;
1448
1636
  return (_a = this.endpoints.find((e) => e.direction == "out")) == null ? void 0 : _a.endpointNumber;
1449
1637
  }
1638
+ get outEndpointPacketSize() {
1639
+ var _a;
1640
+ return (_a = this.endpoints.find((e) => e.direction == "out")) == null ? void 0 : _a.packetSize;
1641
+ }
1450
1642
  /**
1451
1643
  * Endpoint for reading
1452
1644
  */
@@ -1495,8 +1687,8 @@ var UsbDevice = class {
1495
1687
  */
1496
1688
  writeString(text) {
1497
1689
  return __async(this, null, function* () {
1498
- const bytes = stringHelper.toUTF8Array(text);
1499
- yield this.writeData(bytes);
1690
+ const bytes2 = stringHelper.toUTF8Array(text);
1691
+ yield this.writeData(bytes2);
1500
1692
  });
1501
1693
  }
1502
1694
  /**
@@ -1524,8 +1716,8 @@ var UsbDevice = class {
1524
1716
  */
1525
1717
  readString(length) {
1526
1718
  return __async(this, null, function* () {
1527
- const bytes = yield this.readData(length);
1528
- if (bytes) return stringHelper.toString(bytes);
1719
+ const bytes2 = yield this.readData(length);
1720
+ if (bytes2) return stringHelper.toString(bytes2);
1529
1721
  return void 0;
1530
1722
  });
1531
1723
  }
@@ -1636,8 +1828,8 @@ var NetworkDevice = class {
1636
1828
  }
1637
1829
  writeString(text) {
1638
1830
  return __async(this, null, function* () {
1639
- const bytes = stringHelper2.toUTF8Array(text);
1640
- yield this.writeData(bytes);
1831
+ const bytes2 = stringHelper2.toUTF8Array(text);
1832
+ yield this.writeData(bytes2);
1641
1833
  });
1642
1834
  }
1643
1835
  readData(length) {
@@ -1681,8 +1873,8 @@ var NetworkDevice = class {
1681
1873
  }
1682
1874
  readString(length) {
1683
1875
  return __async(this, null, function* () {
1684
- const bytes = yield this.readData(length);
1685
- if (bytes) return stringHelper2.toString(bytes);
1876
+ const bytes2 = yield this.readData(length);
1877
+ if (bytes2) return stringHelper2.toString(bytes2);
1686
1878
  return void 0;
1687
1879
  });
1688
1880
  }
@@ -2330,7 +2522,7 @@ var BOLD_WEIGTH = 700;
2330
2522
  var BOLD_TAG = "b";
2331
2523
  var ITALIC_TAG = "i";
2332
2524
  var UNDERLINE_TAG = "u";
2333
- var STRIKE_TAG = "s";
2525
+ var STRIKE_TAG = ["s", "del", "strike"];
2334
2526
  var Text = class extends LabelField {
2335
2527
  constructor(content, x, y, formatted = true) {
2336
2528
  super();
@@ -2422,7 +2614,7 @@ var Text = class extends LabelField {
2422
2614
  let baseFeatures = [...features];
2423
2615
  if (tag == UNDERLINE_TAG) {
2424
2616
  baseFeatures.push("underline");
2425
- } else if (tag == STRIKE_TAG) {
2617
+ } else if (STRIKE_TAG.includes(tag)) {
2426
2618
  baseFeatures.push("strike");
2427
2619
  } else if (tag == BOLD_TAG) {
2428
2620
  baseFont.weight = BOLD_WEIGTH;
@@ -2647,8 +2839,8 @@ var Image2 = class _Image extends LabelField {
2647
2839
  */
2648
2840
  static create(image2, x, y, width, height) {
2649
2841
  return __async(this, null, function* () {
2650
- const bitmap = yield ImageUtils.getBWBitmap(image2, width, height);
2651
- return new _Image(x, y, bitmap);
2842
+ const bitmap2 = yield ImageUtils.getBWBitmap(image2, width, height);
2843
+ return new _Image(x, y, bitmap2);
2652
2844
  });
2653
2845
  }
2654
2846
  };