image-js 1.1.0 → 1.3.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.
Files changed (90) hide show
  1. package/dist/image-js.esm.js +268 -54
  2. package/dist/image-js.esm.js.map +1 -1
  3. package/dist/image-js.esm.min.js +2 -2
  4. package/dist/image-js.esm.min.js.map +1 -1
  5. package/dist/image-js.umd.js +236 -20
  6. package/dist/image-js.umd.js.map +1 -1
  7. package/dist/image-js.umd.min.js +2 -2
  8. package/dist/image-js.umd.min.js.map +1 -1
  9. package/dist-types/image-js.d.ts +26 -2
  10. package/lib/Image.d.ts +17 -1
  11. package/lib/Image.d.ts.map +1 -1
  12. package/lib/Image.js +38 -1
  13. package/lib/Image.js.map +1 -1
  14. package/lib/draw/drawLineOnImage.d.ts.map +1 -1
  15. package/lib/draw/drawLineOnImage.js.map +1 -1
  16. package/lib/extra/draw/draw_text.d.ts +47 -0
  17. package/lib/extra/draw/draw_text.d.ts.map +1 -0
  18. package/lib/extra/draw/draw_text.js +108 -0
  19. package/lib/extra/draw/draw_text.js.map +1 -0
  20. package/lib/extra/draw/index.d.ts +3 -0
  21. package/lib/extra/draw/index.d.ts.map +1 -0
  22. package/lib/extra/draw/index.js +3 -0
  23. package/lib/extra/draw/index.js.map +1 -0
  24. package/lib/{ssim → extra/ssim}/compute_dssim.d.ts +2 -2
  25. package/lib/extra/ssim/compute_dssim.d.ts.map +1 -0
  26. package/lib/{ssim → extra/ssim}/compute_dssim.js +1 -1
  27. package/lib/extra/ssim/compute_dssim.js.map +1 -0
  28. package/lib/{ssim → extra/ssim}/compute_ssim.d.ts +1 -1
  29. package/lib/extra/ssim/compute_ssim.d.ts.map +1 -0
  30. package/lib/{ssim → extra/ssim}/compute_ssim.js +2 -2
  31. package/lib/extra/ssim/compute_ssim.js.map +1 -0
  32. package/lib/extra/ssim/index.d.ts +3 -0
  33. package/lib/extra/ssim/index.d.ts.map +1 -0
  34. package/lib/extra/ssim/index.js +3 -0
  35. package/lib/extra/ssim/index.js.map +1 -0
  36. package/lib/index_browser.d.ts +3 -0
  37. package/lib/index_browser.d.ts.map +1 -0
  38. package/lib/index_browser.js +5 -0
  39. package/lib/index_browser.js.map +1 -0
  40. package/lib/index_full.d.ts +4 -0
  41. package/lib/index_full.d.ts.map +1 -0
  42. package/lib/index_full.js +5 -0
  43. package/lib/index_full.js.map +1 -0
  44. package/lib/load/decodePng.d.ts.map +1 -1
  45. package/lib/load/decodePng.js +16 -0
  46. package/lib/load/decodePng.js.map +1 -1
  47. package/lib/load/decodeTiff.d.ts.map +1 -1
  48. package/lib/load/decodeTiff.js +35 -0
  49. package/lib/load/decodeTiff.js.map +1 -1
  50. package/lib/load/load.types.d.ts +6 -0
  51. package/lib/load/load.types.d.ts.map +1 -1
  52. package/lib/load/read.d.ts +1 -1
  53. package/lib/load/read.js +1 -1
  54. package/lib/save/write.d.ts +1 -1
  55. package/lib/save/write.js +1 -1
  56. package/lib/utils/cross_platform.d.ts +8 -0
  57. package/lib/utils/cross_platform.d.ts.map +1 -1
  58. package/lib/utils/cross_platform.js +34 -2
  59. package/lib/utils/cross_platform.js.map +1 -1
  60. package/lib/utils/setBlendedPixel.d.ts +1 -1
  61. package/lib/utils/setBlendedPixel.js +1 -1
  62. package/lib/utils/setBlendedVisiblePixel.d.ts +1 -1
  63. package/lib/utils/setBlendedVisiblePixel.js +1 -1
  64. package/package.json +17 -3
  65. package/src/Image.ts +44 -4
  66. package/src/draw/drawLineOnImage.ts +0 -1
  67. package/src/extra/draw/draw_text.ts +194 -0
  68. package/src/extra/draw/index.ts +2 -0
  69. package/src/{ssim → extra/ssim}/compute_dssim.ts +3 -3
  70. package/src/{ssim → extra/ssim}/compute_ssim.ts +3 -3
  71. package/src/extra/ssim/index.ts +2 -0
  72. package/src/index_browser.ts +4 -0
  73. package/src/index_full.ts +4 -0
  74. package/src/load/decodePng.ts +18 -0
  75. package/src/load/decodeTiff.ts +38 -1
  76. package/src/load/load.types.ts +8 -0
  77. package/src/load/read.ts +1 -1
  78. package/src/save/write.ts +1 -1
  79. package/src/utils/cross_platform.ts +47 -4
  80. package/src/utils/setBlendedPixel.ts +1 -1
  81. package/src/utils/setBlendedVisiblePixel.ts +1 -1
  82. package/lib/ssim/compute_dssim.d.ts.map +0 -1
  83. package/lib/ssim/compute_dssim.js.map +0 -1
  84. package/lib/ssim/compute_ssim.d.ts.map +0 -1
  85. package/lib/ssim/compute_ssim.js.map +0 -1
  86. package/lib/ssim/index.d.ts +0 -3
  87. package/lib/ssim/index.d.ts.map +0 -1
  88. package/lib/ssim/index.js +0 -3
  89. package/lib/ssim/index.js.map +0 -1
  90. package/src/ssim/index.ts +0 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * image-js v1.1.0
2
+ * image-js v1.3.0
3
3
  * Image processing and manipulation in JavaScript
4
4
  * https://github.com/image-js/image-js#readme
5
5
  *
@@ -11,6 +11,7 @@
11
11
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.IJS = {}));
12
12
  })(this, (function (exports) { 'use strict';
13
13
 
14
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
14
15
  function getDefaultExportFromCjs (x) {
15
16
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
16
17
  }
@@ -6269,9 +6270,9 @@ ${indent}columns: ${matrix.columns}
6269
6270
  var index_umd$1 = {exports: {}};
6270
6271
 
6271
6272
  var index_umd = index_umd$1.exports;
6272
- (function (module, exports) {
6273
+ (function (module, exports$1) {
6273
6274
  (function (N, J) {
6274
- J(exports) ;
6275
+ J(exports$1) ;
6275
6276
  })(index_umd, function (N) {
6276
6277
 
6277
6278
  function J(f, a, o, t, e) {
@@ -8668,7 +8669,7 @@ ${indent}columns: ${matrix.columns}
8668
8669
  * @param image - The image with which to blend.
8669
8670
  * @param column - Column of the target pixel.
8670
8671
  * @param row - Row of the target pixel.
8671
- * @param color - Color with which to blend the image pixel. @default `'Opaque black'`.
8672
+ * @param color - Color with which to blend the image pixel. Default: `Opaque black`.
8672
8673
  */
8673
8674
  function setBlendedPixel(image, column, row, color) {
8674
8675
  color = color ?? getDefaultColor(image);
@@ -8698,7 +8699,7 @@ ${indent}columns: ${matrix.columns}
8698
8699
  * @param image - The image with which to blend.
8699
8700
  * @param column - Column of the target pixel.
8700
8701
  * @param row - Row of the target pixel.
8701
- * @param color - Color with which to blend the image pixel. @default `'Opaque black'`.
8702
+ * @param color - Color with which to blend the image pixel. Default: `Opaque black`.
8702
8703
  */
8703
8704
  function setBlendedVisiblePixel(image, column, row, color) {
8704
8705
  if (column >= 0 && column < image.width && row >= 0 && row < image.height) {
@@ -16817,6 +16818,10 @@ ${indent}columns: ${matrix.columns}
16817
16818
  * Origin of the image relative to a the parent image.
16818
16819
  */
16819
16820
  origin;
16821
+ /**
16822
+ * Original image resolution.
16823
+ */
16824
+ originalResolution;
16820
16825
  meta;
16821
16826
  /**
16822
16827
  * Typed array holding the image data.
@@ -16837,7 +16842,8 @@ ${indent}columns: ${matrix.columns}
16837
16842
  row: 0,
16838
16843
  column: 0
16839
16844
  },
16840
- meta
16845
+ meta,
16846
+ resolution
16841
16847
  } = options;
16842
16848
  if (width < 1 || !Number.isInteger(width)) {
16843
16849
  throw new RangeError(`width must be an integer and at least 1. Received ${width}`);
@@ -16852,6 +16858,7 @@ ${indent}columns: ${matrix.columns}
16852
16858
  this.colorModel = colorModel;
16853
16859
  this.origin = origin;
16854
16860
  this.meta = meta;
16861
+ this.originalResolution = resolution;
16855
16862
  const colorModelDef = colorModels[colorModel];
16856
16863
  this.components = colorModelDef.components;
16857
16864
  this.alpha = colorModelDef.alpha;
@@ -16872,6 +16879,38 @@ ${indent}columns: ${matrix.columns}
16872
16879
  this.data = data;
16873
16880
  }
16874
16881
  }
16882
+ /**
16883
+ * Returns normalized resolution in pixels per centimeter. If resolution unit is unknown, return null.
16884
+ * @returns Object with x and y resolutions in pixel/cm.
16885
+ */
16886
+ get normalizedResolution() {
16887
+ if (!this.originalResolution) {
16888
+ return undefined;
16889
+ }
16890
+ const centimetersPerInch = 2.54;
16891
+ const centimetersPerMeter = 100;
16892
+ switch (this.originalResolution.unit) {
16893
+ case 'inch':
16894
+ return {
16895
+ x: this.originalResolution.x / centimetersPerInch,
16896
+ y: this.originalResolution.y / centimetersPerInch
16897
+ };
16898
+ case 'centimeter':
16899
+ return {
16900
+ x: this.originalResolution.x,
16901
+ y: this.originalResolution.y
16902
+ };
16903
+ case 'meter':
16904
+ return {
16905
+ x: this.originalResolution.x / centimetersPerMeter,
16906
+ y: this.originalResolution.y / centimetersPerMeter
16907
+ };
16908
+ case 'unknown':
16909
+ return null;
16910
+ default:
16911
+ throw new Error('Unknown resolution unit.');
16912
+ }
16913
+ }
16875
16914
  /**
16876
16915
  * Create a new Image based on the properties of an existing one.
16877
16916
  * @param other - Reference image.
@@ -28679,7 +28718,7 @@ ${indent}columns: ${matrix.columns}
28679
28718
  * @returns - The `fs`, `path` and `url` Node.js modules.
28680
28719
  */
28681
28720
  function getNodeApiOrThrow(methodName) {
28682
- if (typeof process === 'undefined' || typeof process.getBuiltinModule !== 'function') {
28721
+ if (!isNode()) {
28683
28722
  throw new Error(`${methodName} is only implemented for Node.js`);
28684
28723
  }
28685
28724
  return {
@@ -28688,6 +28727,35 @@ ${indent}columns: ${matrix.columns}
28688
28727
  url: process.getBuiltinModule('node:url')
28689
28728
  };
28690
28729
  }
28730
+ let CanvasCtorBrowser;
28731
+ let CanvasCtorNode;
28732
+ /**
28733
+ * Returns a 2D canvas context for rendering on the browser or Node.js.
28734
+ * @param width - Width of the canvas.
28735
+ * @param height - Height of the canvas.
28736
+ * @returns The initialised canvas context.
28737
+ */
28738
+ function getCanvasContext(width, height) {
28739
+ if (isNode()) {
28740
+ CanvasCtorNode ??= getRequireFn()('skia-canvas').Canvas;
28741
+ return new CanvasCtorNode(width, height).getContext('2d');
28742
+ } else {
28743
+ CanvasCtorBrowser ??= globalThis.OffscreenCanvas;
28744
+ const context = new CanvasCtorBrowser(width, height).getContext('2d');
28745
+ if (!context) {
28746
+ throw new Error('Failed to create canvas context');
28747
+ }
28748
+ return context;
28749
+ }
28750
+ }
28751
+ function isNode() {
28752
+ return typeof process !== 'undefined' && typeof process.getBuiltinModule === 'function';
28753
+ }
28754
+ let requireFn;
28755
+ function getRequireFn() {
28756
+ requireFn ??= process.getBuiltinModule('node:module').createRequire((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('image-js.umd.js', document.baseURI).href)));
28757
+ return requireFn;
28758
+ }
28691
28759
 
28692
28760
  /**
28693
28761
  * Asynchronously write an image to the disk.
@@ -28714,7 +28782,7 @@ ${indent}columns: ${matrix.columns}
28714
28782
  await nodeApi.fs.promises.writeFile(path, toWrite);
28715
28783
  }
28716
28784
  /**
28717
- * Synchronous version of @see {@link write}.
28785
+ * Synchronous version of {@link write}.
28718
28786
  * This method is only implemented for Node.js.
28719
28787
  * @param path - Path where the image should be written.
28720
28788
  * @param image - Image to save.
@@ -31517,10 +31585,23 @@ ${indent}columns: ${matrix.columns}
31517
31585
  default:
31518
31586
  throw new RangeError(`invalid number of channels: ${png.channels}`);
31519
31587
  }
31588
+ let resolution;
31589
+ if (png.resolution) {
31590
+ resolution = png.resolution.unit === 1 ? /*If the resolution unit is meters*/{
31591
+ x: png.resolution.x,
31592
+ y: png.resolution.y,
31593
+ unit: 'meter'
31594
+ } : /*If resolution unit is unknown */{
31595
+ x: png.resolution.x,
31596
+ y: png.resolution.y,
31597
+ unit: 'unknown'
31598
+ };
31599
+ }
31520
31600
  return new Image(png.width, png.height, {
31521
31601
  colorModel,
31522
31602
  bitDepth,
31523
- data: png.data
31603
+ data: png.data,
31604
+ resolution
31524
31605
  });
31525
31606
  }
31526
31607
  /**
@@ -31590,6 +31671,7 @@ ${indent}columns: ${matrix.columns}
31590
31671
  if (ifd.data instanceof Float32Array || ifd.data instanceof Float64Array) {
31591
31672
  throw new Error('Float TIFF data is not supported.');
31592
31673
  }
31674
+ const resolution = getTiffResolution(ifd);
31593
31675
  if (ifd.type === 3) {
31594
31676
  const hasAlpha = ifd.samplesPerPixel === 2;
31595
31677
  const pixelLength = hasAlpha ? 4 : 3;
@@ -31617,7 +31699,8 @@ ${indent}columns: ${matrix.columns}
31617
31699
  data,
31618
31700
  colorModel: hasAlpha ? 'RGBA' : 'RGB',
31619
31701
  bitDepth: 16,
31620
- meta: getMetadata(ifd)
31702
+ meta: getMetadata(ifd),
31703
+ resolution
31621
31704
  });
31622
31705
  } else if (ifd.type === 1 || ifd.type === 0) {
31623
31706
  if (ifd.bitsPerSample !== 1) {
@@ -31625,14 +31708,16 @@ ${indent}columns: ${matrix.columns}
31625
31708
  data: ifd.data,
31626
31709
  bitDepth: ifd.bitsPerSample,
31627
31710
  colorModel: ifd.alpha ? 'GREYA' : 'GREY',
31628
- meta: getMetadata(ifd)
31711
+ meta: getMetadata(ifd),
31712
+ resolution
31629
31713
  });
31630
31714
  } else {
31631
31715
  return new Image(ifd.width, ifd.height, {
31632
31716
  data: ifd.data.map(pixel => pixel * 255),
31633
31717
  bitDepth: 8,
31634
31718
  colorModel: 'GREY',
31635
- meta: getMetadata(ifd)
31719
+ meta: getMetadata(ifd),
31720
+ resolution
31636
31721
  });
31637
31722
  }
31638
31723
  } else {
@@ -31640,10 +31725,41 @@ ${indent}columns: ${matrix.columns}
31640
31725
  data: ifd.data,
31641
31726
  bitDepth: ifd.bitsPerSample,
31642
31727
  colorModel: ifd.alpha ? 'RGBA' : 'RGB',
31643
- meta: getMetadata(ifd)
31728
+ meta: getMetadata(ifd),
31729
+ resolution
31644
31730
  });
31645
31731
  }
31646
31732
  }
31733
+ /**
31734
+ * Gets image resolution from its metadata and converts it into Pixels per meter, when it's possible. Also keeps original resolution values and units.
31735
+ * @param ifd - Tiff metadata.
31736
+ * @returns Resolution object.
31737
+ */
31738
+ function getTiffResolution(ifd) {
31739
+ if (!ifd.xResolution || !ifd.yResolution) {
31740
+ return undefined;
31741
+ }
31742
+ switch (ifd.resolutionUnit) {
31743
+ case 1:
31744
+ return {
31745
+ x: ifd.xResolution,
31746
+ y: ifd.yResolution,
31747
+ unit: 'unknown'
31748
+ };
31749
+ case 3:
31750
+ return {
31751
+ x: ifd.xResolution,
31752
+ y: ifd.yResolution,
31753
+ unit: 'centimeter'
31754
+ };
31755
+ default:
31756
+ return {
31757
+ x: ifd.xResolution,
31758
+ y: ifd.yResolution,
31759
+ unit: 'inch'
31760
+ };
31761
+ }
31762
+ }
31647
31763
 
31648
31764
  /**
31649
31765
  * Decode input data. Data format is automatically detected.
@@ -31680,7 +31796,7 @@ ${indent}columns: ${matrix.columns}
31680
31796
  return decode(data);
31681
31797
  }
31682
31798
  /**
31683
- * Synchronous version of @see {@link read}.
31799
+ * Synchronous version of {@link read}.
31684
31800
  * This method is only implemented for Node.js.
31685
31801
  * @param path - The path to the image.
31686
31802
  * @returns Image instance.
@@ -32893,7 +33009,7 @@ ${indent}columns: ${matrix.columns}
32893
33009
 
32894
33010
  var priorityQueue = {exports: {}};
32895
33011
 
32896
- (function (module, exports) {
33012
+ (function (module, exports$1) {
32897
33013
  (function (f) {
32898
33014
  {
32899
33015
  module.exports = f();
@@ -32923,7 +33039,7 @@ ${indent}columns: ${matrix.columns}
32923
33039
  for (var o = 0; o < r.length; o++) s(r[o]);
32924
33040
  return s;
32925
33041
  }({
32926
- 1: [function (_dereq_, module, exports) {
33042
+ 1: [function (_dereq_, module, exports$1) {
32927
33043
  var AbstractPriorityQueue,
32928
33044
  ArrayStrategy,
32929
33045
  BHeapStrategy,
@@ -32968,7 +33084,7 @@ ${indent}columns: ${matrix.columns}
32968
33084
  "./PriorityQueue/BHeapStrategy": 4,
32969
33085
  "./PriorityQueue/BinaryHeapStrategy": 5
32970
33086
  }],
32971
- 2: [function (_dereq_, module, exports) {
33087
+ 2: [function (_dereq_, module, exports$1) {
32972
33088
  module.exports = function () {
32973
33089
  function AbstractPriorityQueue(options) {
32974
33090
  var ref;
@@ -33006,7 +33122,7 @@ ${indent}columns: ${matrix.columns}
33006
33122
  return AbstractPriorityQueue;
33007
33123
  }();
33008
33124
  }, {}],
33009
- 3: [function (_dereq_, module, exports) {
33125
+ 3: [function (_dereq_, module, exports$1) {
33010
33126
  var binarySearchForIndexReversed;
33011
33127
  binarySearchForIndexReversed = function (array, value, comparator) {
33012
33128
  var high, low, mid;
@@ -33049,7 +33165,7 @@ ${indent}columns: ${matrix.columns}
33049
33165
  return ArrayStrategy;
33050
33166
  }();
33051
33167
  }, {}],
33052
- 4: [function (_dereq_, module, exports) {
33168
+ 4: [function (_dereq_, module, exports$1) {
33053
33169
  module.exports = function () {
33054
33170
  function BHeapStrategy(options) {
33055
33171
  var arr, j, k, len, ref, ref1, shift, value;
@@ -33187,7 +33303,7 @@ ${indent}columns: ${matrix.columns}
33187
33303
  return BHeapStrategy;
33188
33304
  }();
33189
33305
  }, {}],
33190
- 5: [function (_dereq_, module, exports) {
33306
+ 5: [function (_dereq_, module, exports$1) {
33191
33307
  module.exports = function () {
33192
33308
  function BinaryHeapStrategy(options) {
33193
33309
  var ref;
@@ -33849,6 +33965,105 @@ ${indent}columns: ${matrix.columns}
33849
33965
  BINARY: ['Mask']
33850
33966
  };
33851
33967
 
33968
+ /**
33969
+ * Draws text on an image.
33970
+ * @param image - Image to write text on.
33971
+ * @param text - Text to write on the image.
33972
+ * @param options - Out Options
33973
+ * @returns Image with drawn text.
33974
+ */
33975
+ function drawText(image, text, options) {
33976
+ if (Array.isArray(text) && text.length === 0) {
33977
+ throw new Error('At least one text element must be provided');
33978
+ }
33979
+ const newImage = getOutputImage(image, options, {
33980
+ clone: true
33981
+ });
33982
+ const defaultFont = options?.font ?? '12px Helvetica';
33983
+ const defaultColor = options?.fontColor ?? [255, 255, 255, 255];
33984
+ const ctx = getCanvasContext(image.width, image.height);
33985
+ if (!Array.isArray(text)) {
33986
+ drawTextElement(image, ctx, text, defaultFont, defaultColor);
33987
+ } else {
33988
+ for (const label of text) {
33989
+ drawTextElement(image, ctx, label, defaultFont, defaultColor);
33990
+ }
33991
+ }
33992
+ layerCanvas(newImage.getRawImage().data, ctx.getImageData(0, 0, image.width, image.height).data, image.channels, image.bitDepth);
33993
+ return newImage;
33994
+ }
33995
+ function drawTextElement(image, ctx, text, defaultFont, defaultColor) {
33996
+ ctx.font = text.font ?? defaultFont;
33997
+ const fontColor = text.fontColor ?? defaultColor;
33998
+ validateValues(fontColor, image);
33999
+ const alpha = fontColor[3] ? fontColor[3] / 255 : 1;
34000
+ const normalizedColor = [fontColor[0] ?? 0, fontColor[1] ?? 0, fontColor[2] ?? 0, alpha];
34001
+ ctx.fillStyle = `rgba(${normalizedColor.join(',')})`;
34002
+ ctx.fillText(String(text.content), text.position.column, text.position.row);
34003
+ }
34004
+ /**
34005
+ * Draws labels on the image data from canvas.
34006
+ * @param imageData - Image data to draw text on.
34007
+ * @param canvasData - Canvas data to draw on the image.
34008
+ * @param numberOfChannels - Number of channels of the initial image.
34009
+ * @param bitDepth - Bit depth of the initial image.
34010
+ */
34011
+ function layerCanvas(imageData, canvasData, numberOfChannels, bitDepth) {
34012
+ const config = CHANNEL_CONFIGS[numberOfChannels] || CHANNEL_CONFIGS[1];
34013
+ const pixelCount = canvasData.length >>> 2;
34014
+ const bitShift = bitDepth - 8;
34015
+ let imageIndex = 0;
34016
+ let canvasIndex = 0;
34017
+ for (let pixel = 0; pixel < pixelCount; pixel++) {
34018
+ const canvasAlpha = canvasData[canvasIndex + 3] / 255;
34019
+ // Skip transparent canvas pixels completely
34020
+ if (canvasAlpha === 0) {
34021
+ imageIndex += numberOfChannels;
34022
+ canvasIndex += 4;
34023
+ continue;
34024
+ }
34025
+ const invAlpha = 1 - canvasAlpha;
34026
+ for (const channel of config.channelOffsets) {
34027
+ const targetIndex = imageIndex + channel;
34028
+ imageData[targetIndex] = Math.round(canvasData[canvasIndex + channel] * canvasAlpha + imageData[targetIndex] * invAlpha) << bitShift;
34029
+ }
34030
+ if (config.hasAlpha) {
34031
+ const alphaIndex = imageIndex + config.alphaOffset;
34032
+ const imageAlpha = (imageData[alphaIndex] >>> bitShift) / 255;
34033
+ const newAlpha = canvasAlpha + imageAlpha * (1 - canvasAlpha);
34034
+ imageData[alphaIndex] = Math.round(newAlpha * 255) << bitShift;
34035
+ }
34036
+ imageIndex += numberOfChannels;
34037
+ canvasIndex += 4;
34038
+ }
34039
+ }
34040
+ const CHANNEL_CONFIGS = {
34041
+ // GREY
34042
+ 1: {
34043
+ channelOffsets: [0],
34044
+ hasAlpha: false,
34045
+ alphaOffset: undefined
34046
+ },
34047
+ // GREYA
34048
+ 2: {
34049
+ channelOffsets: [0],
34050
+ hasAlpha: true,
34051
+ alphaOffset: 1
34052
+ },
34053
+ 3: {
34054
+ // RGB
34055
+ channelOffsets: [0, 1, 2],
34056
+ hasAlpha: false,
34057
+ alphaOffset: undefined
34058
+ },
34059
+ 4: {
34060
+ // RGBA
34061
+ channelOffsets: [0, 1, 2],
34062
+ hasAlpha: true,
34063
+ alphaOffset: 3
34064
+ }
34065
+ };
34066
+
33852
34067
  exports.BorderType = BorderType;
33853
34068
  exports.DerivativeFilter = DerivativeFilter;
33854
34069
  exports.GreyAlgorithm = GreyAlgorithm;
@@ -33919,6 +34134,7 @@ ${indent}columns: ${matrix.columns}
33919
34134
  exports.drawPolylineOnImage = drawPolylineOnImage;
33920
34135
  exports.drawPolylineOnMask = drawPolylineOnMask;
33921
34136
  exports.drawRectangle = drawRectangle;
34137
+ exports.drawText = drawText;
33922
34138
  exports.encode = encode;
33923
34139
  exports.encodeDataURL = encodeDataURL;
33924
34140
  exports.encodeJpeg = encodeJpeg;