image-js 1.1.0 → 1.2.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 (74) hide show
  1. package/dist/image-js.esm.js +176 -48
  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 +144 -14
  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 +2 -2
  10. package/lib/draw/drawLineOnImage.d.ts.map +1 -1
  11. package/lib/draw/drawLineOnImage.js.map +1 -1
  12. package/lib/extra/draw/draw_text.d.ts +47 -0
  13. package/lib/extra/draw/draw_text.d.ts.map +1 -0
  14. package/lib/extra/draw/draw_text.js +108 -0
  15. package/lib/extra/draw/draw_text.js.map +1 -0
  16. package/lib/extra/draw/index.d.ts +3 -0
  17. package/lib/extra/draw/index.d.ts.map +1 -0
  18. package/lib/extra/draw/index.js +3 -0
  19. package/lib/extra/draw/index.js.map +1 -0
  20. package/lib/{ssim → extra/ssim}/compute_dssim.d.ts +2 -2
  21. package/lib/extra/ssim/compute_dssim.d.ts.map +1 -0
  22. package/lib/{ssim → extra/ssim}/compute_dssim.js +1 -1
  23. package/lib/extra/ssim/compute_dssim.js.map +1 -0
  24. package/lib/{ssim → extra/ssim}/compute_ssim.d.ts +1 -1
  25. package/lib/extra/ssim/compute_ssim.d.ts.map +1 -0
  26. package/lib/{ssim → extra/ssim}/compute_ssim.js +2 -2
  27. package/lib/extra/ssim/compute_ssim.js.map +1 -0
  28. package/lib/extra/ssim/index.d.ts +3 -0
  29. package/lib/extra/ssim/index.d.ts.map +1 -0
  30. package/lib/extra/ssim/index.js +3 -0
  31. package/lib/extra/ssim/index.js.map +1 -0
  32. package/lib/index_browser.d.ts +3 -0
  33. package/lib/index_browser.d.ts.map +1 -0
  34. package/lib/index_browser.js +5 -0
  35. package/lib/index_browser.js.map +1 -0
  36. package/lib/index_full.d.ts +4 -0
  37. package/lib/index_full.d.ts.map +1 -0
  38. package/lib/index_full.js +5 -0
  39. package/lib/index_full.js.map +1 -0
  40. package/lib/load/read.d.ts +1 -1
  41. package/lib/load/read.js +1 -1
  42. package/lib/save/write.d.ts +1 -1
  43. package/lib/save/write.js +1 -1
  44. package/lib/utils/cross_platform.d.ts +8 -0
  45. package/lib/utils/cross_platform.d.ts.map +1 -1
  46. package/lib/utils/cross_platform.js +34 -2
  47. package/lib/utils/cross_platform.js.map +1 -1
  48. package/lib/utils/setBlendedPixel.d.ts +1 -1
  49. package/lib/utils/setBlendedPixel.js +1 -1
  50. package/lib/utils/setBlendedVisiblePixel.d.ts +1 -1
  51. package/lib/utils/setBlendedVisiblePixel.js +1 -1
  52. package/package.json +17 -3
  53. package/src/draw/drawLineOnImage.ts +0 -1
  54. package/src/extra/draw/draw_text.ts +194 -0
  55. package/src/extra/draw/index.ts +2 -0
  56. package/src/{ssim → extra/ssim}/compute_dssim.ts +3 -3
  57. package/src/{ssim → extra/ssim}/compute_ssim.ts +3 -3
  58. package/src/extra/ssim/index.ts +2 -0
  59. package/src/index_browser.ts +4 -0
  60. package/src/index_full.ts +4 -0
  61. package/src/load/read.ts +1 -1
  62. package/src/save/write.ts +1 -1
  63. package/src/utils/cross_platform.ts +47 -4
  64. package/src/utils/setBlendedPixel.ts +1 -1
  65. package/src/utils/setBlendedVisiblePixel.ts +1 -1
  66. package/lib/ssim/compute_dssim.d.ts.map +0 -1
  67. package/lib/ssim/compute_dssim.js.map +0 -1
  68. package/lib/ssim/compute_ssim.d.ts.map +0 -1
  69. package/lib/ssim/compute_ssim.js.map +0 -1
  70. package/lib/ssim/index.d.ts +0 -3
  71. package/lib/ssim/index.d.ts.map +0 -1
  72. package/lib/ssim/index.js +0 -3
  73. package/lib/ssim/index.js.map +0 -1
  74. package/src/ssim/index.ts +0 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * image-js v1.1.0
2
+ * image-js v1.2.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) {
@@ -28679,7 +28680,7 @@ ${indent}columns: ${matrix.columns}
28679
28680
  * @returns - The `fs`, `path` and `url` Node.js modules.
28680
28681
  */
28681
28682
  function getNodeApiOrThrow(methodName) {
28682
- if (typeof process === 'undefined' || typeof process.getBuiltinModule !== 'function') {
28683
+ if (!isNode()) {
28683
28684
  throw new Error(`${methodName} is only implemented for Node.js`);
28684
28685
  }
28685
28686
  return {
@@ -28688,6 +28689,35 @@ ${indent}columns: ${matrix.columns}
28688
28689
  url: process.getBuiltinModule('node:url')
28689
28690
  };
28690
28691
  }
28692
+ let CanvasCtorBrowser;
28693
+ let CanvasCtorNode;
28694
+ /**
28695
+ * Returns a 2D canvas context for rendering on the browser or Node.js.
28696
+ * @param width - Width of the canvas.
28697
+ * @param height - Height of the canvas.
28698
+ * @returns The initialised canvas context.
28699
+ */
28700
+ function getCanvasContext(width, height) {
28701
+ if (isNode()) {
28702
+ CanvasCtorNode ??= getRequireFn()('skia-canvas').Canvas;
28703
+ return new CanvasCtorNode(width, height).getContext('2d');
28704
+ } else {
28705
+ CanvasCtorBrowser ??= globalThis.OffscreenCanvas;
28706
+ const context = new CanvasCtorBrowser(width, height).getContext('2d');
28707
+ if (!context) {
28708
+ throw new Error('Failed to create canvas context');
28709
+ }
28710
+ return context;
28711
+ }
28712
+ }
28713
+ function isNode() {
28714
+ return typeof process !== 'undefined' && typeof process.getBuiltinModule === 'function';
28715
+ }
28716
+ let requireFn;
28717
+ function getRequireFn() {
28718
+ 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)));
28719
+ return requireFn;
28720
+ }
28691
28721
 
28692
28722
  /**
28693
28723
  * Asynchronously write an image to the disk.
@@ -28714,7 +28744,7 @@ ${indent}columns: ${matrix.columns}
28714
28744
  await nodeApi.fs.promises.writeFile(path, toWrite);
28715
28745
  }
28716
28746
  /**
28717
- * Synchronous version of @see {@link write}.
28747
+ * Synchronous version of {@link write}.
28718
28748
  * This method is only implemented for Node.js.
28719
28749
  * @param path - Path where the image should be written.
28720
28750
  * @param image - Image to save.
@@ -31680,7 +31710,7 @@ ${indent}columns: ${matrix.columns}
31680
31710
  return decode(data);
31681
31711
  }
31682
31712
  /**
31683
- * Synchronous version of @see {@link read}.
31713
+ * Synchronous version of {@link read}.
31684
31714
  * This method is only implemented for Node.js.
31685
31715
  * @param path - The path to the image.
31686
31716
  * @returns Image instance.
@@ -32893,7 +32923,7 @@ ${indent}columns: ${matrix.columns}
32893
32923
 
32894
32924
  var priorityQueue = {exports: {}};
32895
32925
 
32896
- (function (module, exports) {
32926
+ (function (module, exports$1) {
32897
32927
  (function (f) {
32898
32928
  {
32899
32929
  module.exports = f();
@@ -32923,7 +32953,7 @@ ${indent}columns: ${matrix.columns}
32923
32953
  for (var o = 0; o < r.length; o++) s(r[o]);
32924
32954
  return s;
32925
32955
  }({
32926
- 1: [function (_dereq_, module, exports) {
32956
+ 1: [function (_dereq_, module, exports$1) {
32927
32957
  var AbstractPriorityQueue,
32928
32958
  ArrayStrategy,
32929
32959
  BHeapStrategy,
@@ -32968,7 +32998,7 @@ ${indent}columns: ${matrix.columns}
32968
32998
  "./PriorityQueue/BHeapStrategy": 4,
32969
32999
  "./PriorityQueue/BinaryHeapStrategy": 5
32970
33000
  }],
32971
- 2: [function (_dereq_, module, exports) {
33001
+ 2: [function (_dereq_, module, exports$1) {
32972
33002
  module.exports = function () {
32973
33003
  function AbstractPriorityQueue(options) {
32974
33004
  var ref;
@@ -33006,7 +33036,7 @@ ${indent}columns: ${matrix.columns}
33006
33036
  return AbstractPriorityQueue;
33007
33037
  }();
33008
33038
  }, {}],
33009
- 3: [function (_dereq_, module, exports) {
33039
+ 3: [function (_dereq_, module, exports$1) {
33010
33040
  var binarySearchForIndexReversed;
33011
33041
  binarySearchForIndexReversed = function (array, value, comparator) {
33012
33042
  var high, low, mid;
@@ -33049,7 +33079,7 @@ ${indent}columns: ${matrix.columns}
33049
33079
  return ArrayStrategy;
33050
33080
  }();
33051
33081
  }, {}],
33052
- 4: [function (_dereq_, module, exports) {
33082
+ 4: [function (_dereq_, module, exports$1) {
33053
33083
  module.exports = function () {
33054
33084
  function BHeapStrategy(options) {
33055
33085
  var arr, j, k, len, ref, ref1, shift, value;
@@ -33187,7 +33217,7 @@ ${indent}columns: ${matrix.columns}
33187
33217
  return BHeapStrategy;
33188
33218
  }();
33189
33219
  }, {}],
33190
- 5: [function (_dereq_, module, exports) {
33220
+ 5: [function (_dereq_, module, exports$1) {
33191
33221
  module.exports = function () {
33192
33222
  function BinaryHeapStrategy(options) {
33193
33223
  var ref;
@@ -33849,6 +33879,105 @@ ${indent}columns: ${matrix.columns}
33849
33879
  BINARY: ['Mask']
33850
33880
  };
33851
33881
 
33882
+ /**
33883
+ * Draws text on an image.
33884
+ * @param image - Image to write text on.
33885
+ * @param text - Text to write on the image.
33886
+ * @param options - Out Options
33887
+ * @returns Image with drawn text.
33888
+ */
33889
+ function drawText(image, text, options) {
33890
+ if (Array.isArray(text) && text.length === 0) {
33891
+ throw new Error('At least one text element must be provided');
33892
+ }
33893
+ const newImage = getOutputImage(image, options, {
33894
+ clone: true
33895
+ });
33896
+ const defaultFont = options?.font ?? '12px Helvetica';
33897
+ const defaultColor = options?.fontColor ?? [255, 255, 255, 255];
33898
+ const ctx = getCanvasContext(image.width, image.height);
33899
+ if (!Array.isArray(text)) {
33900
+ drawTextElement(image, ctx, text, defaultFont, defaultColor);
33901
+ } else {
33902
+ for (const label of text) {
33903
+ drawTextElement(image, ctx, label, defaultFont, defaultColor);
33904
+ }
33905
+ }
33906
+ layerCanvas(newImage.getRawImage().data, ctx.getImageData(0, 0, image.width, image.height).data, image.channels, image.bitDepth);
33907
+ return newImage;
33908
+ }
33909
+ function drawTextElement(image, ctx, text, defaultFont, defaultColor) {
33910
+ ctx.font = text.font ?? defaultFont;
33911
+ const fontColor = text.fontColor ?? defaultColor;
33912
+ validateValues(fontColor, image);
33913
+ const alpha = fontColor[3] ? fontColor[3] / 255 : 1;
33914
+ const normalizedColor = [fontColor[0] ?? 0, fontColor[1] ?? 0, fontColor[2] ?? 0, alpha];
33915
+ ctx.fillStyle = `rgba(${normalizedColor.join(',')})`;
33916
+ ctx.fillText(String(text.content), text.position.column, text.position.row);
33917
+ }
33918
+ /**
33919
+ * Draws labels on the image data from canvas.
33920
+ * @param imageData - Image data to draw text on.
33921
+ * @param canvasData - Canvas data to draw on the image.
33922
+ * @param numberOfChannels - Number of channels of the initial image.
33923
+ * @param bitDepth - Bit depth of the initial image.
33924
+ */
33925
+ function layerCanvas(imageData, canvasData, numberOfChannels, bitDepth) {
33926
+ const config = CHANNEL_CONFIGS[numberOfChannels] || CHANNEL_CONFIGS[1];
33927
+ const pixelCount = canvasData.length >>> 2;
33928
+ const bitShift = bitDepth - 8;
33929
+ let imageIndex = 0;
33930
+ let canvasIndex = 0;
33931
+ for (let pixel = 0; pixel < pixelCount; pixel++) {
33932
+ const canvasAlpha = canvasData[canvasIndex + 3] / 255;
33933
+ // Skip transparent canvas pixels completely
33934
+ if (canvasAlpha === 0) {
33935
+ imageIndex += numberOfChannels;
33936
+ canvasIndex += 4;
33937
+ continue;
33938
+ }
33939
+ const invAlpha = 1 - canvasAlpha;
33940
+ for (const channel of config.channelOffsets) {
33941
+ const targetIndex = imageIndex + channel;
33942
+ imageData[targetIndex] = Math.round(canvasData[canvasIndex + channel] * canvasAlpha + imageData[targetIndex] * invAlpha) << bitShift;
33943
+ }
33944
+ if (config.hasAlpha) {
33945
+ const alphaIndex = imageIndex + config.alphaOffset;
33946
+ const imageAlpha = (imageData[alphaIndex] >>> bitShift) / 255;
33947
+ const newAlpha = canvasAlpha + imageAlpha * (1 - canvasAlpha);
33948
+ imageData[alphaIndex] = Math.round(newAlpha * 255) << bitShift;
33949
+ }
33950
+ imageIndex += numberOfChannels;
33951
+ canvasIndex += 4;
33952
+ }
33953
+ }
33954
+ const CHANNEL_CONFIGS = {
33955
+ // GREY
33956
+ 1: {
33957
+ channelOffsets: [0],
33958
+ hasAlpha: false,
33959
+ alphaOffset: undefined
33960
+ },
33961
+ // GREYA
33962
+ 2: {
33963
+ channelOffsets: [0],
33964
+ hasAlpha: true,
33965
+ alphaOffset: 1
33966
+ },
33967
+ 3: {
33968
+ // RGB
33969
+ channelOffsets: [0, 1, 2],
33970
+ hasAlpha: false,
33971
+ alphaOffset: undefined
33972
+ },
33973
+ 4: {
33974
+ // RGBA
33975
+ channelOffsets: [0, 1, 2],
33976
+ hasAlpha: true,
33977
+ alphaOffset: 3
33978
+ }
33979
+ };
33980
+
33852
33981
  exports.BorderType = BorderType;
33853
33982
  exports.DerivativeFilter = DerivativeFilter;
33854
33983
  exports.GreyAlgorithm = GreyAlgorithm;
@@ -33919,6 +34048,7 @@ ${indent}columns: ${matrix.columns}
33919
34048
  exports.drawPolylineOnImage = drawPolylineOnImage;
33920
34049
  exports.drawPolylineOnMask = drawPolylineOnMask;
33921
34050
  exports.drawRectangle = drawRectangle;
34051
+ exports.drawText = drawText;
33922
34052
  exports.encode = encode;
33923
34053
  exports.encodeDataURL = encodeDataURL;
33924
34054
  exports.encodeJpeg = encodeJpeg;