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/README.md CHANGED
@@ -279,6 +279,7 @@ print/display command sequences.
279
279
  - `display(label, direction?, mirror?)`
280
280
  - `getModelname()`
281
281
  - `getStatus()`
282
+ - `writeRawString(text)`
282
283
  - `close()`
283
284
 
284
285
  - **`PrinterStatus`**
package/dist/index.d.mts CHANGED
@@ -839,6 +839,11 @@ declare abstract class Printer {
839
839
  * @param command Command to send to the usb
840
840
  */
841
841
  writeCommand(command: Command): Promise<void>;
842
+ /**
843
+ * Writes a raw string to the printer
844
+ * @param text String to send to the printer
845
+ */
846
+ writeRawString(text: string): Promise<void>;
842
847
  /**
843
848
  * Check if the device is indeed a printer
844
849
  * @param device
package/dist/index.d.ts CHANGED
@@ -839,6 +839,11 @@ declare abstract class Printer {
839
839
  * @param command Command to send to the usb
840
840
  */
841
841
  writeCommand(command: Command): Promise<void>;
842
+ /**
843
+ * Writes a raw string to the printer
844
+ * @param text String to send to the printer
845
+ */
846
+ writeRawString(text: string): Promise<void>;
842
847
  /**
843
848
  * Check if the device is indeed a printer
844
849
  * @param device
package/dist/index.js CHANGED
@@ -330,12 +330,13 @@ function parsePNG(buffer2) {
330
330
  }
331
331
  const scanlineLength = width * bytesPerPixel;
332
332
  const data = new Uint8Array(width * height * outputChannels);
333
+ let prevUnfilteredScanline = Buffer.alloc(scanlineLength);
333
334
  for (let y = 0; y < height; y++) {
334
335
  const scanlineStart = y * (scanlineLength + 1);
335
336
  const filterType = decompressedData[scanlineStart];
336
337
  const scanline = decompressedData.subarray(scanlineStart + 1, scanlineStart + 1 + scanlineLength);
337
- const prevScanline = y > 0 ? decompressedData.subarray((y - 1) * (scanlineLength + 1) + 1, (y - 1) * (scanlineLength + 1) + 1 + scanlineLength) : Buffer.alloc(scanlineLength);
338
- const unfilteredScanline = applyPNGFilter(filterType, scanline, prevScanline, bytesPerPixel);
338
+ const unfilteredScanline = applyPNGFilter(filterType, scanline, prevUnfilteredScanline, bytesPerPixel);
339
+ prevUnfilteredScanline = unfilteredScanline;
339
340
  for (let x = 0; x < width; x++) {
340
341
  const outIdx = (y * width + x) * outputChannels;
341
342
  if (colorType === 0) {
@@ -829,7 +830,8 @@ var ImageProcessor_default = ImageProcessor;
829
830
  // src/helpers/ImageUtils.ts
830
831
  var BLACK_PIXEL = 0;
831
832
  var WHITE_PIXEL = 1;
832
- var DEFAULT_THRESHOLD = 200;
833
+ var DEFAULT_THRESHOLD = 240;
834
+ var DEFAULT_CROP_ALPHA_THRESHOLD = 16;
833
835
  var ImageUtils = class {
834
836
  /**
835
837
  * Get pixel information about an image
@@ -848,11 +850,11 @@ var ImageUtils = class {
848
850
  * input size as only downscaling is performed
849
851
  *
850
852
  * @param image Image to process
851
- * @param destinationWidth Width of the ouput bitmap
853
+ * @param destinationWidth Width of the output bitmap
852
854
  * @param destinationHeight Height of the output bitmap
853
855
  * @returns
854
856
  */
855
- static getBWBitmap(image2, destinationWidth, destinationHeight) {
857
+ static getBWBitmap(image2, destinationWidth, destinationHeight, threshold, lsbFirst = false) {
856
858
  return __async(this, null, function* () {
857
859
  const {
858
860
  data,
@@ -863,43 +865,103 @@ var ImageUtils = class {
863
865
  image2,
864
866
  destinationWidth != null && destinationHeight != null ? { width: destinationWidth, height: destinationHeight } : void 0
865
867
  );
866
- const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
868
+ let cropX0 = 0;
869
+ let cropY0 = 0;
870
+ let cropX1 = width - 1;
871
+ let cropY1 = height - 1;
872
+ if (bitsPerPixel > 3) {
873
+ let found = false;
874
+ let minX = width;
875
+ let minY = height;
876
+ let maxX = -1;
877
+ let maxY = -1;
878
+ for (let y = 0; y < height; y++) {
879
+ for (let x = 0; x < width; x++) {
880
+ const a = data[y * width * bitsPerPixel + x * bitsPerPixel + 3];
881
+ if (a >= DEFAULT_CROP_ALPHA_THRESHOLD) {
882
+ found = true;
883
+ if (x < minX) minX = x;
884
+ if (y < minY) minY = y;
885
+ if (x > maxX) maxX = x;
886
+ if (y > maxY) maxY = y;
887
+ }
888
+ }
889
+ }
890
+ if (found) {
891
+ cropX0 = minX;
892
+ cropY0 = minY;
893
+ cropX1 = maxX;
894
+ cropY1 = maxY;
895
+ }
896
+ }
897
+ const cropWidth = cropX1 - cropX0 + 1;
898
+ const cropHeight = cropY1 - cropY0 + 1;
899
+ const dim = getSizePreserveAspect(cropWidth, cropHeight, destinationWidth, destinationHeight);
867
900
  const dWidth = dim.width;
868
901
  const dHeight = dim.height;
869
902
  const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
870
903
  const dividableDWidth = dWidth + differenceToDividable;
871
- const bitmapData = new Uint8Array(dividableDWidth * dHeight);
904
+ const luminances = new Uint8Array(dividableDWidth * dHeight);
872
905
  let destinationIndex = 0;
873
906
  for (let h = 0; h < dHeight; h++) {
874
- const originalHeight = Math.round(h * (height - 1) / (dHeight - 1));
907
+ const srcY0 = cropY0 + Math.floor(h * cropHeight / dHeight);
908
+ const srcY1 = Math.max(srcY0, cropY0 + Math.floor((h + 1) * cropHeight / dHeight) - 1);
875
909
  for (let w = 0; w < dWidth; w++) {
876
- const originalWidth = Math.round(w * (width - 1) / (dWidth - 1));
877
- const baseIndex = originalHeight * width * bitsPerPixel + originalWidth * bitsPerPixel;
878
- const r = data[baseIndex];
879
- const g = data[baseIndex + 1];
880
- const b = data[baseIndex + 2];
881
- const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255;
882
- const alpha = a / 255;
883
- const rC = r * alpha + 255 * (1 - alpha);
884
- const gC = g * alpha + 255 * (1 - alpha);
885
- const bC = b * alpha + 255 * (1 - alpha);
886
- const luminance = 0.299 * rC + 0.587 * gC + 0.114 * bC;
887
- if (luminance > DEFAULT_THRESHOLD) {
888
- bitmapData[destinationIndex] = WHITE_PIXEL;
889
- } else {
890
- bitmapData[destinationIndex] = BLACK_PIXEL;
910
+ const srcX0 = cropX0 + Math.floor(w * cropWidth / dWidth);
911
+ const srcX1 = Math.max(srcX0, cropX0 + Math.floor((w + 1) * cropWidth / dWidth) - 1);
912
+ let lumSum = 0;
913
+ let count = 0;
914
+ let opaqueCount = 0;
915
+ let opaqueLumSum = 0;
916
+ let opaqueWeightSum = 0;
917
+ let minOpaqueLum = 255;
918
+ for (let sy = srcY0; sy <= srcY1; sy++) {
919
+ for (let sx = srcX0; sx <= srcX1; sx++) {
920
+ const baseIndex = sy * width * bitsPerPixel + sx * bitsPerPixel;
921
+ const r = data[baseIndex];
922
+ const g = data[baseIndex + 1];
923
+ const b = data[baseIndex + 2];
924
+ const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255;
925
+ const alpha = a / 255;
926
+ const rC = r * alpha + 255 * (1 - alpha);
927
+ const gC = g * alpha + 255 * (1 - alpha);
928
+ const bC = b * alpha + 255 * (1 - alpha);
929
+ lumSum += 0.299 * rC + 0.587 * gC + 0.114 * bC;
930
+ count += 1;
931
+ if (a > 0) {
932
+ opaqueCount += 1;
933
+ const lum = 0.299 * r + 0.587 * g + 0.114 * b;
934
+ opaqueLumSum += lum * alpha;
935
+ opaqueWeightSum += alpha;
936
+ if (lum < minOpaqueLum) minOpaqueLum = lum;
937
+ }
938
+ }
891
939
  }
940
+ const avgLum = count > 0 ? lumSum / count : 255;
941
+ const avgOpaqueLum = opaqueWeightSum > 0 ? opaqueLumSum / opaqueWeightSum : 255;
942
+ const opaqueRatio = count > 0 ? opaqueCount / count : 0;
943
+ const luminance = opaqueCount === 0 ? 255 : opaqueRatio < 0.25 ? minOpaqueLum : avgOpaqueLum;
944
+ luminances[destinationIndex] = Math.max(0, Math.min(255, Math.round(luminance)));
892
945
  destinationIndex += 1;
893
946
  }
894
947
  for (let i = 0; i < differenceToDividable; i++) {
895
- bitmapData[destinationIndex] = WHITE_PIXEL;
948
+ luminances[destinationIndex] = 255;
896
949
  destinationIndex += 1;
897
950
  }
898
951
  }
952
+ const thresholdValue = threshold != null ? threshold : this.otsuThreshold(luminances, dWidth, dividableDWidth, dHeight);
953
+ const bitmapData = new Uint8Array(dividableDWidth * dHeight);
954
+ for (let h = 0; h < dHeight; h++) {
955
+ const rowOffset = h * dividableDWidth;
956
+ for (let w = 0; w < dividableDWidth; w++) {
957
+ const idx = rowOffset + w;
958
+ bitmapData[idx] = luminances[idx] > thresholdValue ? WHITE_PIXEL : BLACK_PIXEL;
959
+ }
960
+ }
899
961
  const byteArrays = this.chunk(bitmapData, 8);
900
962
  const widthInBytes = dividableDWidth / 8;
901
- const bytes = byteArrays.map(this.bitsToByte);
902
- const finalBytes = new Uint8Array(bytes);
963
+ const bytes2 = byteArrays.map((b) => this.bitsToByte(b, lsbFirst));
964
+ const finalBytes = new Uint8Array(bytes2);
903
965
  return {
904
966
  width: widthInBytes,
905
967
  height: dHeight,
@@ -907,6 +969,40 @@ var ImageUtils = class {
907
969
  };
908
970
  });
909
971
  }
972
+ static otsuThreshold(luminances, contentWidth, rowWidth, height) {
973
+ const hist = new Uint32Array(256);
974
+ let total = 0;
975
+ for (let y = 0; y < height; y++) {
976
+ const rowOffset = y * rowWidth;
977
+ for (let x = 0; x < contentWidth; x++) {
978
+ hist[luminances[rowOffset + x]] += 1;
979
+ total += 1;
980
+ }
981
+ }
982
+ if (total === 0) return DEFAULT_THRESHOLD;
983
+ let sum = 0;
984
+ for (let t = 0; t < 256; t++) sum += t * hist[t];
985
+ let sumB = 0;
986
+ let wB = 0;
987
+ let wF = 0;
988
+ let maxBetween = -1;
989
+ let threshold = DEFAULT_THRESHOLD;
990
+ for (let t = 0; t < 256; t++) {
991
+ wB += hist[t];
992
+ if (wB === 0) continue;
993
+ wF = total - wB;
994
+ if (wF === 0) break;
995
+ sumB += t * hist[t];
996
+ const mB = sumB / wB;
997
+ const mF = (sum - sumB) / wF;
998
+ const between = wB * wF * (mB - mF) * (mB - mF);
999
+ if (between > maxBetween) {
1000
+ maxBetween = between;
1001
+ threshold = t;
1002
+ }
1003
+ }
1004
+ return threshold;
1005
+ }
910
1006
  /**
911
1007
  * Splits an array into chunks.
912
1008
  * @param originalArray
@@ -926,13 +1022,95 @@ var ImageUtils = class {
926
1022
  * @param bits
927
1023
  * @returns
928
1024
  */
929
- static bitsToByte(bits) {
1025
+ static bitsToByte(bits, lsbFirst) {
930
1026
  let byteValue = 0;
1027
+ if (lsbFirst) {
1028
+ for (let i = 0; i < bits.length; i++) {
1029
+ byteValue |= (bits[i] & 1) << i;
1030
+ }
1031
+ return byteValue;
1032
+ }
931
1033
  for (let i = 0; i < bits.length; i++) {
932
- byteValue = byteValue << 1 | bits[i];
1034
+ byteValue = byteValue << 1 | bits[i] & 1;
933
1035
  }
934
1036
  return byteValue;
935
1037
  }
1038
+ static dilateBWBitmap(bitmap2, iterations = 1) {
1039
+ let current = bitmap2;
1040
+ for (let i = 0; i < iterations; i++) {
1041
+ current = this.dilateOnce(current);
1042
+ }
1043
+ return current;
1044
+ }
1045
+ static bwBitmapToPBM(bitmap2, widthDots2) {
1046
+ var _a;
1047
+ const widthBytes = bitmap2.width;
1048
+ const height = bitmap2.height;
1049
+ const widthBits = widthDots2 != null ? widthDots2 : widthBytes * 8;
1050
+ const header = `P4
1051
+ ${widthBits} ${height}
1052
+ `;
1053
+ const headerBytes = new TextEncoder().encode(header);
1054
+ const rowBytes = Math.ceil(widthBits / 8);
1055
+ const out = new Uint8Array(headerBytes.length + rowBytes * height);
1056
+ out.set(headerBytes, 0);
1057
+ const src = bitmap2.bytes;
1058
+ let offset = headerBytes.length;
1059
+ for (let y = 0; y < height; y++) {
1060
+ const rowStart = y * widthBytes;
1061
+ for (let xb = 0; xb < rowBytes; xb++) {
1062
+ const b = (_a = src[rowStart + xb]) != null ? _a : 255;
1063
+ out[offset++] = ~b & 255;
1064
+ }
1065
+ const extraBits = rowBytes * 8 - widthBits;
1066
+ if (extraBits > 0) {
1067
+ const mask = 255 << extraBits;
1068
+ out[offset - 1] = out[offset - 1] & mask;
1069
+ }
1070
+ }
1071
+ return out;
1072
+ }
1073
+ static saveBWBitmapAsPBM(bitmap, filePath, widthDots) {
1074
+ return __async(this, null, function* () {
1075
+ if (typeof window !== "undefined") {
1076
+ throw new Error("pbm-export-not-supported-in-browser");
1077
+ }
1078
+ const fs = yield eval("require")("fs");
1079
+ const bytes = this.bwBitmapToPBM(bitmap, widthDots);
1080
+ fs.writeFileSync(filePath, bytes);
1081
+ });
1082
+ }
1083
+ static dilateOnce(bitmap2) {
1084
+ const widthBytes = bitmap2.width;
1085
+ const widthBits = widthBytes * 8;
1086
+ const height = bitmap2.height;
1087
+ const src = bitmap2.bytes;
1088
+ const dst = new Uint8Array(src.length);
1089
+ const getBit = (x, y) => {
1090
+ if (x < 0 || y < 0 || x >= widthBits || y >= height) return 1;
1091
+ const byteIndex = y * widthBytes + (x >> 3);
1092
+ const bitIndex = 7 - (x & 7);
1093
+ return src[byteIndex] >> bitIndex & 1;
1094
+ };
1095
+ const setBit = (x, y, value) => {
1096
+ if (x < 0 || y < 0 || x >= widthBits || y >= height) return;
1097
+ const byteIndex = y * widthBytes + (x >> 3);
1098
+ const mask = 1 << 7 - (x & 7);
1099
+ if (value === 1) dst[byteIndex] |= mask;
1100
+ else dst[byteIndex] &= ~mask & 255;
1101
+ };
1102
+ for (let y = 0; y < height; y++) {
1103
+ for (let x = 0; x < widthBits; x++) {
1104
+ 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;
1105
+ setBit(x, y, isBlack ? 0 : 1);
1106
+ }
1107
+ }
1108
+ return {
1109
+ width: widthBytes,
1110
+ height,
1111
+ bytes: dst
1112
+ };
1113
+ }
936
1114
  };
937
1115
 
938
1116
  // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
@@ -944,9 +1122,9 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
944
1122
  * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by
945
1123
  * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values
946
1124
  */
947
- constructor(bitmap, x, y, mode) {
1125
+ constructor(bitmap2, x, y, mode) {
948
1126
  super(x, y);
949
- this.bitmap = bitmap;
1127
+ this.bitmap = bitmap2;
950
1128
  this.mode = mode != null ? mode : "overwrite";
951
1129
  }
952
1130
  get commandString() {
@@ -987,8 +1165,8 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
987
1165
  */
988
1166
  static forImageUrl(image2, x, y, imageWidth, imageHeight, mode) {
989
1167
  return __async(this, null, function* () {
990
- const bitmap = yield ImageUtils.getBWBitmap(image2, imageWidth, imageHeight);
991
- return new _TSPLBitmapCommand(bitmap, x, y, mode);
1168
+ const bitmap2 = yield ImageUtils.getBWBitmap(image2, imageWidth, imageHeight);
1169
+ return new _TSPLBitmapCommand(bitmap2, x, y, mode);
992
1170
  });
993
1171
  }
994
1172
  };
@@ -1373,6 +1551,16 @@ var Printer = class {
1373
1551
  yield command.writeTo(this.device);
1374
1552
  });
1375
1553
  }
1554
+ /**
1555
+ * Writes a raw string to the printer
1556
+ * @param text String to send to the printer
1557
+ */
1558
+ writeRawString(text) {
1559
+ return __async(this, null, function* () {
1560
+ if (!this.device.opened) yield this.device.openAndConfigure();
1561
+ yield this.device.writeString(text);
1562
+ });
1563
+ }
1376
1564
  /**
1377
1565
  * Check if the device is indeed a printer
1378
1566
  * @param device
@@ -1397,9 +1585,9 @@ var StringUtils = class {
1397
1585
  * @param bytes Bytes to decode
1398
1586
  * @returns A string
1399
1587
  */
1400
- toString(bytes) {
1588
+ toString(bytes2) {
1401
1589
  let decoder = new TextDecoder();
1402
- return decoder.decode(bytes);
1590
+ return decoder.decode(bytes2);
1403
1591
  }
1404
1592
  };
1405
1593
  var isWhitespace = (text) => text.trim() === "";
@@ -1472,6 +1660,10 @@ var UsbDevice = class {
1472
1660
  var _a;
1473
1661
  return (_a = this.endpoints.find((e) => e.direction == "out")) == null ? void 0 : _a.endpointNumber;
1474
1662
  }
1663
+ get outEndpointPacketSize() {
1664
+ var _a;
1665
+ return (_a = this.endpoints.find((e) => e.direction == "out")) == null ? void 0 : _a.packetSize;
1666
+ }
1475
1667
  /**
1476
1668
  * Endpoint for reading
1477
1669
  */
@@ -1520,8 +1712,8 @@ var UsbDevice = class {
1520
1712
  */
1521
1713
  writeString(text) {
1522
1714
  return __async(this, null, function* () {
1523
- const bytes = stringHelper.toUTF8Array(text);
1524
- yield this.writeData(bytes);
1715
+ const bytes2 = stringHelper.toUTF8Array(text);
1716
+ yield this.writeData(bytes2);
1525
1717
  });
1526
1718
  }
1527
1719
  /**
@@ -1549,8 +1741,8 @@ var UsbDevice = class {
1549
1741
  */
1550
1742
  readString(length) {
1551
1743
  return __async(this, null, function* () {
1552
- const bytes = yield this.readData(length);
1553
- if (bytes) return stringHelper.toString(bytes);
1744
+ const bytes2 = yield this.readData(length);
1745
+ if (bytes2) return stringHelper.toString(bytes2);
1554
1746
  return void 0;
1555
1747
  });
1556
1748
  }
@@ -1661,8 +1853,8 @@ var NetworkDevice = class {
1661
1853
  }
1662
1854
  writeString(text) {
1663
1855
  return __async(this, null, function* () {
1664
- const bytes = stringHelper2.toUTF8Array(text);
1665
- yield this.writeData(bytes);
1856
+ const bytes2 = stringHelper2.toUTF8Array(text);
1857
+ yield this.writeData(bytes2);
1666
1858
  });
1667
1859
  }
1668
1860
  readData(length) {
@@ -1706,8 +1898,8 @@ var NetworkDevice = class {
1706
1898
  }
1707
1899
  readString(length) {
1708
1900
  return __async(this, null, function* () {
1709
- const bytes = yield this.readData(length);
1710
- if (bytes) return stringHelper2.toString(bytes);
1901
+ const bytes2 = yield this.readData(length);
1902
+ if (bytes2) return stringHelper2.toString(bytes2);
1711
1903
  return void 0;
1712
1904
  });
1713
1905
  }
@@ -2355,7 +2547,7 @@ var BOLD_WEIGTH = 700;
2355
2547
  var BOLD_TAG = "b";
2356
2548
  var ITALIC_TAG = "i";
2357
2549
  var UNDERLINE_TAG = "u";
2358
- var STRIKE_TAG = "s";
2550
+ var STRIKE_TAG = ["s", "del", "strike"];
2359
2551
  var Text = class extends LabelField {
2360
2552
  constructor(content, x, y, formatted = true) {
2361
2553
  super();
@@ -2447,7 +2639,7 @@ var Text = class extends LabelField {
2447
2639
  let baseFeatures = [...features];
2448
2640
  if (tag == UNDERLINE_TAG) {
2449
2641
  baseFeatures.push("underline");
2450
- } else if (tag == STRIKE_TAG) {
2642
+ } else if (STRIKE_TAG.includes(tag)) {
2451
2643
  baseFeatures.push("strike");
2452
2644
  } else if (tag == BOLD_TAG) {
2453
2645
  baseFont.weight = BOLD_WEIGTH;
@@ -2672,8 +2864,8 @@ var Image2 = class _Image extends LabelField {
2672
2864
  */
2673
2865
  static create(image2, x, y, width, height) {
2674
2866
  return __async(this, null, function* () {
2675
- const bitmap = yield ImageUtils.getBWBitmap(image2, width, height);
2676
- return new _Image(x, y, bitmap);
2867
+ const bitmap2 = yield ImageUtils.getBWBitmap(image2, width, height);
2868
+ return new _Image(x, y, bitmap2);
2677
2869
  });
2678
2870
  }
2679
2871
  };