label-printer 0.5.4 → 0.6.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/dist/index.d.mts CHANGED
@@ -762,7 +762,7 @@ declare class Image extends LabelField {
762
762
  * @param height
763
763
  * @returns
764
764
  */
765
- static create(image: string, x: number, y: number, width?: number, height?: number): Promise<Image>;
765
+ static create(image: string | Blob, x: number, y: number, width?: number, height?: number): Promise<Image>;
766
766
  }
767
767
 
768
768
  declare class QRCode extends LabelField {
package/dist/index.d.ts CHANGED
@@ -762,7 +762,7 @@ declare class Image extends LabelField {
762
762
  * @param height
763
763
  * @returns
764
764
  */
765
- static create(image: string, x: number, y: number, width?: number, height?: number): Promise<Image>;
765
+ static create(image: string | Blob, x: number, y: number, width?: number, height?: number): Promise<Image>;
766
766
  }
767
767
 
768
768
  declare class QRCode extends LabelField {
package/dist/index.js CHANGED
@@ -22,9 +22,9 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __export = (target, all) => {
25
+ var __export = (target2, all) => {
26
26
  for (var name in all)
27
- __defProp(target, name, { get: all[name], enumerable: true });
27
+ __defProp(target2, name, { get: all[name], enumerable: true });
28
28
  };
29
29
  var __copyProps = (to, from, except, desc) => {
30
30
  if (from && typeof from === "object" || typeof from === "function") {
@@ -34,12 +34,12 @@ var __copyProps = (to, from, except, desc) => {
34
34
  }
35
35
  return to;
36
36
  };
37
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
37
+ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
38
  // If the importer is in node compatibility mode or this is not an ESM
39
39
  // file that has been converted to a CommonJS file using a Babel-
40
40
  // compatible transform (i.e. "__esModule" has not been set), then set
41
41
  // "default" to the CommonJS "module.exports" for node compatibility.
42
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target2, "default", { value: mod, enumerable: true }) : target2,
43
43
  mod
44
44
  ));
45
45
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
@@ -424,14 +424,15 @@ var ImageProcessor = class {
424
424
  /**
425
425
  * Get pixel information about an image
426
426
  * @param image Image to process (local file path, remote URL, data URL, or Blob)
427
+ * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.
427
428
  * @returns Promise with image data including width, height, pixel data, and bits per pixel
428
429
  */
429
- static getImageData(image2) {
430
+ static getImageData(image2, target2) {
430
431
  return __async(this, null, function* () {
431
432
  if (typeof window !== "undefined") {
432
- return this.getImageDataBrowser(image2);
433
+ return this.getImageDataBrowser(image2, target2);
433
434
  } else {
434
- return this.getImageDataNode(image2);
435
+ return this.getImageDataNode(image2, target2);
435
436
  }
436
437
  });
437
438
  }
@@ -439,74 +440,76 @@ var ImageProcessor = class {
439
440
  /**
440
441
  * Get pixel information about an image in browser environment
441
442
  * @param image Image to process
443
+ * @param target Optional target raster size.
442
444
  * @returns Promise with image data
443
445
  */
444
- static getImageDataBrowser(image2) {
446
+ static getImageDataBrowser(image2, target2) {
445
447
  return __async(this, null, function* () {
446
- return new Promise((resolve, reject) => {
447
- const img = new Image();
448
- img.crossOrigin = "anonymous";
449
- img.onload = () => {
450
- try {
451
- const canvas = document.createElement("canvas");
452
- const ctx = canvas.getContext("2d");
453
- if (!ctx) {
454
- reject(new Error("Could not get canvas context"));
455
- return;
456
- }
457
- canvas.width = img.width;
458
- canvas.height = img.height;
459
- ctx.drawImage(img, 0, 0);
460
- const imageData = ctx.getImageData(0, 0, img.width, img.height);
461
- resolve({
462
- data: new Uint8Array(imageData.data),
463
- width: img.width,
464
- height: img.height,
465
- bitsPerPixel: 4
466
- // RGBA
467
- });
468
- } catch (error) {
469
- reject(error);
470
- }
471
- };
472
- img.onerror = () => reject(new Error("Failed to load image"));
473
- if (typeof image2 === "string") {
474
- img.src = image2;
475
- } else {
476
- const url2 = URL.createObjectURL(image2);
477
- img.onload = () => {
478
- URL.revokeObjectURL(url2);
479
- resolve({
480
- data: new Uint8Array(0),
481
- // Will be set by the actual onload
482
- width: 0,
483
- height: 0,
484
- bitsPerPixel: 4
485
- });
486
- };
487
- img.src = url2;
448
+ var _a, _b;
449
+ const loadImage = (src2) => {
450
+ return new Promise((resolve, reject) => {
451
+ const img = new Image();
452
+ img.crossOrigin = "anonymous";
453
+ img.onload = () => resolve(img);
454
+ img.onerror = () => reject(new Error("Failed to load image"));
455
+ img.src = src2;
456
+ });
457
+ };
458
+ let src;
459
+ let revokeUrl;
460
+ if (typeof image2 === "string") {
461
+ src = this.normalizePotentialSVGSource(image2);
462
+ } else {
463
+ revokeUrl = URL.createObjectURL(image2);
464
+ src = revokeUrl;
465
+ }
466
+ try {
467
+ const img = yield loadImage(src);
468
+ const canvas = document.createElement("canvas");
469
+ const ctx = canvas.getContext("2d");
470
+ if (!ctx) {
471
+ throw new Error("Could not get canvas context");
488
472
  }
489
- });
473
+ const width = (_a = target2 == null ? void 0 : target2.width) != null ? _a : img.width;
474
+ const height = (_b = target2 == null ? void 0 : target2.height) != null ? _b : img.height;
475
+ canvas.width = width;
476
+ canvas.height = height;
477
+ ctx.drawImage(img, 0, 0, width, height);
478
+ const imageData2 = ctx.getImageData(0, 0, width, height);
479
+ return {
480
+ data: new Uint8Array(imageData2.data),
481
+ width,
482
+ height,
483
+ bitsPerPixel: 4
484
+ };
485
+ } finally {
486
+ if (revokeUrl) URL.revokeObjectURL(revokeUrl);
487
+ }
490
488
  });
491
489
  }
492
490
  /******** NODEJS ********/
493
491
  /**
494
492
  * Get pixel information about an image in Node.js environment
495
493
  * @param image Image to process
494
+ * @param target Optional target raster size.
496
495
  * @returns Promise with image data
497
496
  */
498
- static getImageDataNode(image2) {
497
+ static getImageDataNode(image2, _target) {
499
498
  return __async(this, null, function* () {
500
499
  console.log("Processing image in Node.js environment");
501
500
  if (image2 instanceof Blob) {
502
501
  throw new Error("Blob input not supported in Node.js environment. Use file path or data URL instead.");
503
502
  }
503
+ const trimmed = image2.trim();
504
+ if (trimmed.startsWith("<svg")) {
505
+ return this.rasterizeSVGNode(trimmed, _target);
506
+ }
504
507
  if (image2.startsWith("data:")) {
505
- return this.getImageFromData(image2);
508
+ return this.getImageFromData(image2, _target);
506
509
  } else if (image2.startsWith("http://") || image2.startsWith("https://")) {
507
- return this.getImageFromUrl(image2);
510
+ return this.getImageFromUrl(image2, _target);
508
511
  } else {
509
- return this.getImageFromFile(image2);
512
+ return this.getImageFromFile(image2, _target);
510
513
  }
511
514
  });
512
515
  }
@@ -515,7 +518,7 @@ var ImageProcessor = class {
515
518
  * @param dataURL Data URL string
516
519
  * @returns Promise with image data
517
520
  */
518
- static getImageFromData(dataURL) {
521
+ static getImageFromData(dataURL, target2) {
519
522
  return __async(this, null, function* () {
520
523
  var _a;
521
524
  const [header, data] = dataURL.split(",");
@@ -523,8 +526,13 @@ var ImageProcessor = class {
523
526
  if (!(mimeType == null ? void 0 : mimeType.startsWith("image/"))) {
524
527
  throw new Error("Invalid image data URL");
525
528
  }
526
- const buffer2 = Buffer.from(data, "base64");
527
529
  const extension = mimeType.split("/")[1].toLowerCase();
530
+ if (extension === "svg+xml" || mimeType === "image/svg+xml") {
531
+ const isBase64 = header.includes(";base64");
532
+ const svgText = isBase64 ? Buffer.from(data, "base64").toString("utf8") : decodeURIComponent(data);
533
+ return this.rasterizeSVGNode(svgText, target2);
534
+ }
535
+ const buffer2 = Buffer.from(data, "base64");
528
536
  return this.parse(buffer2, extension);
529
537
  });
530
538
  }
@@ -533,7 +541,7 @@ var ImageProcessor = class {
533
541
  * @param image
534
542
  * @returns
535
543
  */
536
- static getImageFromFile(image) {
544
+ static getImageFromFile(image, target) {
537
545
  return __async(this, null, function* () {
538
546
  const fs = yield eval("require")("fs");
539
547
  const path = yield eval("require")("path");
@@ -542,6 +550,10 @@ var ImageProcessor = class {
542
550
  }
543
551
  const buffer = fs.readFileSync(image);
544
552
  const ext = path.extname(image).toLowerCase();
553
+ if (ext === ".svg") {
554
+ const svgText = buffer.toString("utf8");
555
+ return this.rasterizeSVGNode(svgText, target);
556
+ }
545
557
  return this.parse(buffer, ext);
546
558
  });
547
559
  }
@@ -550,16 +562,16 @@ var ImageProcessor = class {
550
562
  * @param url Remote image URL
551
563
  * @returns Promise with image data
552
564
  */
553
- static getImageFromUrl(url2) {
565
+ static getImageFromUrl(url2, target2) {
554
566
  return __async(this, null, function* () {
555
567
  let fetch;
556
568
  try {
557
569
  fetch = globalThis.fetch;
558
570
  } catch (e) {
559
- return this.fetchWithHttps(url2);
571
+ return this.fetchWithHttps(url2, target2);
560
572
  }
561
573
  if (!fetch) {
562
- return this.fetchWithHttps(url2);
574
+ return this.fetchWithHttps(url2, target2);
563
575
  }
564
576
  const response = yield fetch(url2);
565
577
  if (!response.ok) {
@@ -569,6 +581,10 @@ var ImageProcessor = class {
569
581
  const buffer2 = Buffer.from(arrayBuffer);
570
582
  const contentType = response.headers.get("content-type");
571
583
  const imageType = this.getImageType(contentType || "", url2);
584
+ if (imageType === "svg") {
585
+ const svgText = buffer2.toString("utf8");
586
+ return this.rasterizeSVGNode(svgText, target2);
587
+ }
572
588
  return this.parse(buffer2, imageType);
573
589
  });
574
590
  }
@@ -577,7 +593,7 @@ var ImageProcessor = class {
577
593
  * @param url Remote image URL
578
594
  * @returns Promise with image data
579
595
  */
580
- static fetchWithHttps(url) {
596
+ static fetchWithHttps(url, target) {
581
597
  return __async(this, null, function* () {
582
598
  const https = yield eval("require")("https");
583
599
  const http = yield eval("require")("http");
@@ -597,8 +613,12 @@ var ImageProcessor = class {
597
613
  const buffer2 = Buffer.concat(chunks);
598
614
  const contentType = response.headers["content-type"] || "";
599
615
  const imageType = this.getImageType(contentType || "", url);
600
- const data = this.parse(buffer2, imageType);
601
- resolve(data);
616
+ if (imageType === "svg") {
617
+ const svgText = buffer2.toString("utf8");
618
+ resolve(this.rasterizeSVGNode(svgText, target));
619
+ return;
620
+ }
621
+ resolve(this.parse(buffer2, imageType));
602
622
  } catch (error) {
603
623
  reject(error);
604
624
  }
@@ -626,6 +646,8 @@ var ImageProcessor = class {
626
646
  return "png";
627
647
  } else if (contentType.includes("jpeg") || contentType.includes("jpg")) {
628
648
  return "jpeg";
649
+ } else if (contentType.includes("svg")) {
650
+ return "svg";
629
651
  }
630
652
  }
631
653
  const urlLower = url2.toLowerCase();
@@ -633,32 +655,57 @@ var ImageProcessor = class {
633
655
  return "png";
634
656
  } else if (urlLower.includes(".jpg") || urlLower.includes(".jpeg")) {
635
657
  return "jpeg";
658
+ } else if (urlLower.includes(".svg")) {
659
+ return "svg";
636
660
  }
637
661
  return "";
638
662
  }
639
663
  /**
640
- *
641
- * @param buffer
642
- * @param extension
643
- * @returns
644
- */
664
+ * Parse image data by extension
665
+ */
645
666
  static parse(buffer2, extension) {
646
- console.log(`Parsing image with extension: ${extension}`);
647
- if (extension === "png") {
667
+ const normalizedExtension = extension.startsWith(".") ? extension.slice(1) : extension;
668
+ console.log(`Parsing image with extension: ${normalizedExtension}`);
669
+ if (normalizedExtension === "png") {
648
670
  return parsePNG(buffer2);
649
- } else if (extension === "jpeg" || extension === "jpg") {
671
+ } else if (normalizedExtension === "jpeg" || normalizedExtension === "jpg") {
650
672
  return this.parseJPEG(buffer2);
673
+ } else if (normalizedExtension === "svg") {
674
+ throw new Error("svg-not-supported-in-node");
651
675
  } else {
652
- throw new Error(`Unsupported image format: ${extension}. Supported formats: PNG, JPEG`);
676
+ throw new Error(`Unsupported image format: ${normalizedExtension}. Supported formats: PNG, JPEG`);
653
677
  }
654
678
  }
655
- /**
656
- * JPEG parser that creates a meaningful placeholder image
657
- * Note: Full JPEG decoding requires complex DCT and Huffman decoding.
658
- * This creates a gradient pattern based on the image dimensions.
659
- * @param buffer JPEG file buffer
660
- * @returns Image data
661
- */
679
+ static rasterizeSVGNode(svg, target) {
680
+ let Resvg;
681
+ try {
682
+ Resvg = eval("require")("@resvg/resvg-js").Resvg;
683
+ } catch (_e) {
684
+ throw new Error("svg-rasterizer-missing");
685
+ }
686
+ const fitTo = target ? { mode: "width", value: target.width } : void 0;
687
+ const resvg = new Resvg(svg, {
688
+ fitTo
689
+ });
690
+ const pngData = resvg.render().asPng();
691
+ const pngBuffer = Buffer.from(pngData);
692
+ const imageData = parsePNG(pngBuffer);
693
+ if (target && (imageData.width !== target.width || imageData.height !== target.height)) {
694
+ return this.resize(imageData, target.width, target.height);
695
+ }
696
+ return imageData;
697
+ }
698
+ static normalizePotentialSVGSource(source) {
699
+ const trimmed = source.trim();
700
+ const isInlineSvg = trimmed.startsWith("<svg");
701
+ const isSvgDataUrl = trimmed.startsWith("data:image/svg+xml");
702
+ if (isInlineSvg) {
703
+ const encoded = encodeURIComponent(trimmed);
704
+ return `data:image/svg+xml;charset=utf-8,${encoded}`;
705
+ }
706
+ if (isSvgDataUrl) return source;
707
+ return source;
708
+ }
662
709
  static parseJPEG(buffer2) {
663
710
  if (buffer2[0] !== 255 || buffer2[1] !== 216) {
664
711
  throw new Error("Invalid JPEG file");
@@ -725,8 +772,8 @@ var ImageProcessor = class {
725
772
  * @param imageData Original image data
726
773
  * @returns Grayscale image data
727
774
  */
728
- static toGrayscale(imageData) {
729
- const { data, width, height } = imageData;
775
+ static toGrayscale(imageData2) {
776
+ const { data, width, height } = imageData2;
730
777
  const grayscaleData = new Uint8Array(data.length);
731
778
  for (let i = 0; i < data.length; i += 4) {
732
779
  const r = data[i];
@@ -743,7 +790,7 @@ var ImageProcessor = class {
743
790
  data: grayscaleData,
744
791
  width,
745
792
  height,
746
- bitsPerPixel: imageData.bitsPerPixel
793
+ bitsPerPixel: imageData2.bitsPerPixel
747
794
  };
748
795
  }
749
796
  /**
@@ -753,8 +800,8 @@ var ImageProcessor = class {
753
800
  * @param newHeight Target height
754
801
  * @returns Resized image data
755
802
  */
756
- static resize(imageData, newWidth, newHeight) {
757
- const { data, width, height, bitsPerPixel } = imageData;
803
+ static resize(imageData2, newWidth, newHeight) {
804
+ const { data, width, height, bitsPerPixel } = imageData2;
758
805
  const resizedData = new Uint8Array(newWidth * newHeight * bitsPerPixel);
759
806
  const xRatio = width / newWidth;
760
807
  const yRatio = height / newHeight;
@@ -782,15 +829,17 @@ var ImageProcessor_default = ImageProcessor;
782
829
  // src/helpers/ImageUtils.ts
783
830
  var BLACK_PIXEL = 0;
784
831
  var WHITE_PIXEL = 1;
832
+ var DEFAULT_THRESHOLD = 200;
785
833
  var ImageUtils = class {
786
834
  /**
787
835
  * Get pixel information about an image
788
836
  * @param image Image to process
837
+ * @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.
789
838
  * @returns
790
839
  */
791
- static getPixels(image2) {
840
+ static getPixels(image2, target2) {
792
841
  return __async(this, null, function* () {
793
- return yield ImageProcessor_default.getImageData(image2);
842
+ return yield ImageProcessor_default.getImageData(image2, target2);
794
843
  });
795
844
  }
796
845
  /**
@@ -810,7 +859,10 @@ var ImageUtils = class {
810
859
  width,
811
860
  height,
812
861
  bitsPerPixel
813
- } = yield this.getPixels(image2);
862
+ } = yield this.getPixels(
863
+ image2,
864
+ destinationWidth != null && destinationHeight != null ? { width: destinationWidth, height: destinationHeight } : void 0
865
+ );
814
866
  const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
815
867
  const dWidth = dim.width;
816
868
  const dHeight = dim.height;
@@ -826,16 +878,16 @@ var ImageUtils = class {
826
878
  const r = data[baseIndex];
827
879
  const g = data[baseIndex + 1];
828
880
  const b = data[baseIndex + 2];
829
- const a = data[baseIndex + 3];
830
- if (a > 128) {
831
- const avg = (r + g + b) / 3;
832
- if (avg > 128) {
833
- bitmapData[destinationIndex] = WHITE_PIXEL;
834
- } else {
835
- bitmapData[destinationIndex] = BLACK_PIXEL;
836
- }
837
- } else {
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) {
838
888
  bitmapData[destinationIndex] = WHITE_PIXEL;
889
+ } else {
890
+ bitmapData[destinationIndex] = BLACK_PIXEL;
839
891
  }
840
892
  destinationIndex += 1;
841
893
  }