@revizly/sharp 0.34.0-revizly8 → 0.34.1-revizly1

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
@@ -1,6 +1,6 @@
1
1
  # sharp
2
2
 
3
- <img src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
3
+ <img src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/public/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
4
4
 
5
5
  The typical use case for this high speed Node-API module
6
6
  is to convert large images in common formats to
package/lib/colour.js CHANGED
@@ -134,6 +134,26 @@ function toColorspace (colorspace) {
134
134
  return this.toColourspace(colorspace);
135
135
  }
136
136
 
137
+ /**
138
+ * Create a RGBA colour array from a given value.
139
+ * @private
140
+ * @param {string|Object} value
141
+ * @throws {Error} Invalid value
142
+ */
143
+ function _getBackgroundColourOption (value) {
144
+ if (is.object(value) || is.string(value)) {
145
+ const colour = color(value);
146
+ return [
147
+ colour.red(),
148
+ colour.green(),
149
+ colour.blue(),
150
+ Math.round(colour.alpha() * 255)
151
+ ];
152
+ } else {
153
+ throw is.invalidParameterError('background', 'object or string', value);
154
+ }
155
+ }
156
+
137
157
  /**
138
158
  * Update a colour attribute of the this.options Object.
139
159
  * @private
@@ -143,17 +163,7 @@ function toColorspace (colorspace) {
143
163
  */
144
164
  function _setBackgroundColourOption (key, value) {
145
165
  if (is.defined(value)) {
146
- if (is.object(value) || is.string(value)) {
147
- const colour = color(value);
148
- this.options[key] = [
149
- colour.red(),
150
- colour.green(),
151
- colour.blue(),
152
- Math.round(colour.alpha() * 255)
153
- ];
154
- } else {
155
- throw is.invalidParameterError('background', 'object or string', value);
156
- }
166
+ this.options[key] = _getBackgroundColourOption(value);
157
167
  }
158
168
  }
159
169
 
@@ -173,6 +183,7 @@ module.exports = function (Sharp) {
173
183
  toColourspace,
174
184
  toColorspace,
175
185
  // Private
186
+ _getBackgroundColourOption,
176
187
  _setBackgroundColourOption
177
188
  });
178
189
  // Class attributes
@@ -263,6 +263,8 @@ const Sharp = function (input, options) {
263
263
  trimBackground: [],
264
264
  trimThreshold: -1,
265
265
  trimLineArt: false,
266
+ dilateWidth: 0,
267
+ erodeWidth: 0,
266
268
  gamma: 0,
267
269
  gammaOut: 0,
268
270
  greyscale: false,
@@ -296,6 +298,8 @@ const Sharp = function (input, options) {
296
298
  withExif: {},
297
299
  withExifMerge: true,
298
300
  resolveWithObject: false,
301
+ loop: 1,
302
+ delay: [],
299
303
  // output format
300
304
  jpegQuality: 80,
301
305
  jpegProgressive: false,
package/lib/index.d.ts CHANGED
@@ -504,6 +504,22 @@ declare namespace sharp {
504
504
  */
505
505
  blur(sigma?: number | boolean | BlurOptions): Sharp;
506
506
 
507
+ /**
508
+ * Expand foreground objects using the dilate morphological operator.
509
+ * @param {Number} [width=1] dilation width in pixels.
510
+ * @throws {Error} Invalid parameters
511
+ * @returns A sharp instance that can be used to chain operations
512
+ */
513
+ dilate(width?: number): Sharp;
514
+
515
+ /**
516
+ * Shrink foreground objects using the erode morphological operator.
517
+ * @param {Number} [width=1] erosion width in pixels.
518
+ * @throws {Error} Invalid parameters
519
+ * @returns A sharp instance that can be used to chain operations
520
+ */
521
+ erode(width?: number): Sharp;
522
+
507
523
  /**
508
524
  * Merge alpha transparency channel, if any, with background.
509
525
  * @param flatten true to enable and false to disable (defaults to true)
@@ -955,7 +971,7 @@ declare namespace sharp {
955
971
  *
956
972
  * Using this option will remove the EXIF `Orientation` tag, if any.
957
973
  */
958
- autoOrient?: boolean;
974
+ autoOrient?: boolean | undefined;
959
975
  /**
960
976
  * When to abort processing of invalid pixel data, one of (in order of sensitivity):
961
977
  * 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. (optional, default 'warning')
@@ -1683,6 +1699,10 @@ declare namespace sharp {
1683
1699
  /** When using the attention crop strategy, the focal point of the cropped region */
1684
1700
  attentionX?: number | undefined;
1685
1701
  attentionY?: number | undefined;
1702
+ /** Number of pages/frames contained within the image, with support for TIFF, HEIF, PDF, animated GIF and animated WebP */
1703
+ pages?: number | undefined;
1704
+ /** Number of pixels high each page in a multi-page image will be. */
1705
+ pageHeight?: number | undefined;
1686
1706
  }
1687
1707
 
1688
1708
  interface AvailableFormatInfo {
package/lib/input.js CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  'use strict';
5
5
 
6
- const color = require('color');
7
6
  const is = require('./is');
8
7
  const sharp = require('./sharp');
9
8
 
@@ -249,7 +248,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
249
248
  }
250
249
  // PDF background colour
251
250
  if (is.defined(inputOptions.pdfBackground)) {
252
- this._setBackgroundColourOption('pdfBackground', inputOptions.pdfBackground);
251
+ inputDescriptor.pdfBackground = this._getBackgroundColourOption(inputOptions.pdfBackground);
253
252
  }
254
253
  // Create new image
255
254
  if (is.defined(inputOptions.create)) {
@@ -288,13 +287,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
288
287
  if (!is.inRange(inputOptions.create.channels, 3, 4)) {
289
288
  throw is.invalidParameterError('create.channels', 'number between 3 and 4', inputOptions.create.channels);
290
289
  }
291
- const background = color(inputOptions.create.background);
292
- inputDescriptor.createBackground = [
293
- background.red(),
294
- background.green(),
295
- background.blue(),
296
- Math.round(background.alpha() * 255)
297
- ];
290
+ inputDescriptor.createBackground = this._getBackgroundColourOption(inputOptions.create.background);
298
291
  } else {
299
292
  throw new Error('Expected valid noise or background to create a new input image');
300
293
  }
@@ -410,13 +403,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
410
403
  }
411
404
  }
412
405
  if (is.defined(inputOptions.join.background)) {
413
- const background = color(inputOptions.join.background);
414
- inputDescriptor.joinBackground = [
415
- background.red(),
416
- background.green(),
417
- background.blue(),
418
- Math.round(background.alpha() * 255)
419
- ];
406
+ inputDescriptor.joinBackground = this._getBackgroundColourOption(inputOptions.join.background);
420
407
  }
421
408
  if (is.defined(inputOptions.join.halign)) {
422
409
  if (is.string(inputOptions.join.halign) && is.string(this.constructor.align[inputOptions.join.halign])) {
package/lib/operation.js CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  'use strict';
5
5
 
6
- const color = require('color');
7
6
  const is = require('./is');
8
7
 
9
8
  /**
@@ -67,13 +66,7 @@ function rotate (angle, options) {
67
66
  } else if (is.number(angle)) {
68
67
  this.options.rotationAngle = angle;
69
68
  if (is.object(options) && options.background) {
70
- const backgroundColour = color(options.background);
71
- this.options.rotationBackground = [
72
- backgroundColour.red(),
73
- backgroundColour.green(),
74
- backgroundColour.blue(),
75
- Math.round(backgroundColour.alpha() * 255)
76
- ];
69
+ this._setBackgroundColourOption('rotationBackground', options.background);
77
70
  }
78
71
  } else {
79
72
  throw is.invalidParameterError('angle', 'numeric', angle);
@@ -443,6 +436,52 @@ function blur (options) {
443
436
  return this;
444
437
  }
445
438
 
439
+ /**
440
+ * Expand foreground objects using the dilate morphological operator.
441
+ *
442
+ * @example
443
+ * const output = await sharp(input)
444
+ * .dilate()
445
+ * .toBuffer();
446
+ *
447
+ * @param {Number} [width=1] dilation width in pixels.
448
+ * @returns {Sharp}
449
+ * @throws {Error} Invalid parameters
450
+ */
451
+ function dilate (width) {
452
+ if (!is.defined(width)) {
453
+ this.options.dilateWidth = 1;
454
+ } else if (is.integer(width) && width > 0) {
455
+ this.options.dilateWidth = width;
456
+ } else {
457
+ throw is.invalidParameterError('dilate', 'positive integer', dilate);
458
+ }
459
+ return this;
460
+ }
461
+
462
+ /**
463
+ * Shrink foreground objects using the erode morphological operator.
464
+ *
465
+ * @example
466
+ * const output = await sharp(input)
467
+ * .erode()
468
+ * .toBuffer();
469
+ *
470
+ * @param {Number} [width=1] erosion width in pixels.
471
+ * @returns {Sharp}
472
+ * @throws {Error} Invalid parameters
473
+ */
474
+ function erode (width) {
475
+ if (!is.defined(width)) {
476
+ this.options.erodeWidth = 1;
477
+ } else if (is.integer(width) && width > 0) {
478
+ this.options.erodeWidth = width;
479
+ } else {
480
+ throw is.invalidParameterError('erode', 'positive integer', erode);
481
+ }
482
+ return this;
483
+ }
484
+
446
485
  /**
447
486
  * Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
448
487
  *
@@ -958,6 +997,8 @@ module.exports = function (Sharp) {
958
997
  flop,
959
998
  affine,
960
999
  sharpen,
1000
+ erode,
1001
+ dilate,
961
1002
  median,
962
1003
  blur,
963
1004
  flatten,
package/lib/resize.js CHANGED
@@ -129,7 +129,7 @@ function isResizeExpected (options) {
129
129
  *
130
130
  * Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
131
131
  *
132
- * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.svg">
132
+ * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/public/api-resize-fit.svg">
133
133
  *
134
134
  * When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
135
135
  * - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
package/lib/sharp.js CHANGED
@@ -17,9 +17,9 @@ const paths = [
17
17
  '@revizly/sharp-wasm32/sharp.node'
18
18
  ];
19
19
 
20
- let sharp;
20
+ let path, sharp;
21
21
  const errors = [];
22
- for (const path of paths) {
22
+ for (path of paths) {
23
23
  try {
24
24
  sharp = require(path);
25
25
  break;
@@ -29,6 +29,14 @@ for (const path of paths) {
29
29
  }
30
30
  }
31
31
 
32
+ /* istanbul ignore next */
33
+ if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2()) {
34
+ const err = new Error('Prebuilt binaries for linux-x64 require v2 microarchitecture');
35
+ err.code = 'Unsupported CPU';
36
+ errors.push(err);
37
+ sharp = null;
38
+ }
39
+
32
40
  /* istanbul ignore next */
33
41
  if (sharp) {
34
42
  module.exports = sharp;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revizly/sharp",
3
3
  "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
4
- "version": "0.34.0-revizly8",
4
+ "version": "0.34.1-revizly1",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://sharp.pixelplumbing.com",
7
7
  "contributors": [
@@ -142,17 +142,17 @@
142
142
  "semver": "^7.7.1"
143
143
  },
144
144
  "optionalDependencies": {
145
- "@revizly/sharp-libvips-linux-arm64": "1.0.11",
146
- "@revizly/sharp-libvips-linux-x64": "1.0.11",
147
- "@revizly/sharp-linux-arm64": "0.34.0-revizly6",
148
- "@revizly/sharp-linux-x64": "0.34.0-revizly6"
145
+ "@revizly/sharp-libvips-linux-arm64": "1.0.12",
146
+ "@revizly/sharp-libvips-linux-x64": "1.0.12",
147
+ "@revizly/sharp-linux-arm64": "0.34.0-revizly8",
148
+ "@revizly/sharp-linux-x64": "0.34.0-revizly8"
149
149
  },
150
150
  "devDependencies": {
151
- "@emnapi/runtime": "^1.3.1",
151
+ "@emnapi/runtime": "^1.4.0",
152
152
  "@revizly/sharp-libvips-dev": "1.0.11",
153
153
  "@types/node": "*",
154
154
  "cc": "^3.0.1",
155
- "emnapi": "^1.3.1",
155
+ "emnapi": "^1.4.0",
156
156
  "exif-reader": "^2.0.2",
157
157
  "extract-zip": "^2.0.1",
158
158
  "icc": "^3.0.0",
package/src/binding.gyp CHANGED
@@ -19,7 +19,10 @@
19
19
  'type': 'shared_library',
20
20
  'defines': [
21
21
  '_VIPS_PUBLIC=__declspec(dllexport)',
22
- '_ALLOW_KEYWORD_MACROS'
22
+ '_ALLOW_KEYWORD_MACROS',
23
+ 'G_DISABLE_ASSERT',
24
+ 'G_DISABLE_CAST_CHECKS',
25
+ 'G_DISABLE_CHECKS'
23
26
  ],
24
27
  'sources': [
25
28
  '<(sharp_libvips_cplusplus_dir)/VConnection.cpp',
@@ -80,6 +83,9 @@
80
83
  }, {
81
84
  'target_name': 'sharp-<(platform_and_arch)',
82
85
  'defines': [
86
+ 'G_DISABLE_ASSERT',
87
+ 'G_DISABLE_CAST_CHECKS',
88
+ 'G_DISABLE_CHECKS',
83
89
  'NAPI_VERSION=9',
84
90
  'NODE_ADDON_API_DISABLE_DEPRECATED',
85
91
  'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS'
@@ -179,6 +185,7 @@
179
185
  '-Wl,-s',
180
186
  '-Wl,--disable-new-dtags',
181
187
  '-Wl,-z,nodelete',
188
+ '-Wl,-Bsymbolic-functions',
182
189
  '-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
183
190
  '-Wl,-rpath=\'$$ORIGIN/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/lib\'',
184
191
  '-Wl,-rpath=\'$$ORIGIN/../../node_modules/@revizly/sharp-libvips-<(platform_and_arch)/lib\'',
package/src/operations.cc CHANGED
@@ -472,4 +472,26 @@ namespace sharp {
472
472
  }
473
473
  }
474
474
 
475
+ /*
476
+ * Dilate an image
477
+ */
478
+ VImage Dilate(VImage image, int const width) {
479
+ int const maskWidth = 2 * width + 1;
480
+ VImage mask = VImage::new_matrix(maskWidth, maskWidth);
481
+ return image.morph(
482
+ mask,
483
+ VIPS_OPERATION_MORPHOLOGY_DILATE).invert();
484
+ }
485
+
486
+ /*
487
+ * Erode an image
488
+ */
489
+ VImage Erode(VImage image, int const width) {
490
+ int const maskWidth = 2 * width + 1;
491
+ VImage mask = VImage::new_matrix(maskWidth, maskWidth);
492
+ return image.morph(
493
+ mask,
494
+ VIPS_OPERATION_MORPHOLOGY_ERODE).invert();
495
+ }
496
+
475
497
  } // namespace sharp
package/src/operations.h CHANGED
@@ -120,6 +120,15 @@ namespace sharp {
120
120
  VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
121
121
  VipsExtend extendWith, std::vector<double> background, int nPages, int *pageHeight);
122
122
 
123
+ /*
124
+ * Dilate an image
125
+ */
126
+ VImage Dilate(VImage image, int const maskWidth);
127
+
128
+ /*
129
+ * Erode an image
130
+ */
131
+ VImage Erode(VImage image, int const maskWidth);
123
132
  } // namespace sharp
124
133
 
125
134
  #endif // SRC_OPERATIONS_H_
package/src/pipeline.cc CHANGED
@@ -609,6 +609,16 @@ class PipelineWorker : public Napi::AsyncWorker {
609
609
  image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
610
610
  }
611
611
 
612
+ // Dilate - must happen before blurring, due to the utility of dilating after thresholding
613
+ if (baton->dilateWidth != 0) {
614
+ image = sharp::Dilate(image, baton->dilateWidth);
615
+ }
616
+
617
+ // Erode - must happen before blurring, due to the utility of eroding after thresholding
618
+ if (baton->erodeWidth != 0) {
619
+ image = sharp::Erode(image, baton->erodeWidth);
620
+ }
621
+
612
622
  // Blur
613
623
  if (shouldBlur) {
614
624
  image = sharp::Blur(image, baton->blurSigma, baton->precision, baton->minAmpl);
@@ -1032,7 +1042,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1032
1042
  (baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
1033
1043
  // Write HEIF to buffer
1034
1044
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
1035
- image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
1045
+ image = sharp::RemoveAnimationProperties(image);
1036
1046
  VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
1037
1047
  ->set("keep", baton->keepMetadata)
1038
1048
  ->set("Q", baton->heifQuality)
@@ -1227,7 +1237,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1227
1237
  (willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
1228
1238
  // Write HEIF to file
1229
1239
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
1230
- image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
1240
+ image = sharp::RemoveAnimationProperties(image);
1231
1241
  image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1232
1242
  ->set("keep", baton->keepMetadata)
1233
1243
  ->set("Q", baton->heifQuality)
@@ -1621,6 +1631,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1621
1631
  baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
1622
1632
  baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
1623
1633
  baton->linearB = sharp::AttrAsVectorOfDouble(options, "linearB");
1634
+ baton->dilateWidth = sharp::AttrAsUint32(options, "dilateWidth");
1635
+ baton->erodeWidth = sharp::AttrAsUint32(options, "erodeWidth");
1624
1636
  baton->greyscale = sharp::AttrAsBool(options, "greyscale");
1625
1637
  baton->normalise = sharp::AttrAsBool(options, "normalise");
1626
1638
  baton->normaliseLower = sharp::AttrAsUint32(options, "normaliseLower");
@@ -1705,6 +1717,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1705
1717
  }
1706
1718
  baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
1707
1719
  baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
1720
+ baton->loop = sharp::AttrAsUint32(options, "loop");
1721
+ baton->delay = sharp::AttrAsInt32Vector(options, "delay");
1708
1722
  // Format-specific
1709
1723
  baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
1710
1724
  baton->jpegProgressive = sharp::AttrAsBool(options, "jpegProgressive");
@@ -1774,13 +1788,6 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1774
1788
  baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
1775
1789
  baton->jxlLossless = sharp::AttrAsBool(options, "jxlLossless");
1776
1790
  baton->rawDepth = sharp::AttrAsEnum<VipsBandFormat>(options, "rawDepth", VIPS_TYPE_BAND_FORMAT);
1777
- // Animated output properties
1778
- if (sharp::HasAttr(options, "loop")) {
1779
- baton->loop = sharp::AttrAsUint32(options, "loop");
1780
- }
1781
- if (sharp::HasAttr(options, "delay")) {
1782
- baton->delay = sharp::AttrAsInt32Vector(options, "delay");
1783
- }
1784
1791
  baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
1785
1792
  baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
1786
1793
  baton->tileAngle = sharp::AttrAsInt32(options, "tileAngle");
package/src/pipeline.h CHANGED
@@ -101,6 +101,8 @@ struct PipelineBaton {
101
101
  int trimOffsetTop;
102
102
  std::vector<double> linearA;
103
103
  std::vector<double> linearB;
104
+ int dilateWidth;
105
+ int erodeWidth;
104
106
  double gamma;
105
107
  double gammaOut;
106
108
  bool greyscale;
@@ -274,6 +276,8 @@ struct PipelineBaton {
274
276
  trimOffsetTop(0),
275
277
  linearA{},
276
278
  linearB{},
279
+ dilateWidth(0),
280
+ erodeWidth(0),
277
281
  gamma(0.0),
278
282
  greyscale(false),
279
283
  normalise(false),
@@ -380,7 +384,7 @@ struct PipelineBaton {
380
384
  ensureAlpha(-1.0),
381
385
  colourspacePipeline(VIPS_INTERPRETATION_LAST),
382
386
  colourspace(VIPS_INTERPRETATION_LAST),
383
- loop(-1),
387
+ loop(1),
384
388
  tileSize(256),
385
389
  tileOverlap(0),
386
390
  tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
package/src/sharp.cc CHANGED
@@ -33,6 +33,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
33
33
  exports.Set("block", Napi::Function::New(env, block));
34
34
  exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance));
35
35
  exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc));
36
+ exports.Set("_isUsingX64V2", Napi::Function::New(env, _isUsingX64V2));
36
37
  exports.Set("stats", Napi::Function::New(env, stats));
37
38
  return exports;
38
39
  }
package/src/utilities.cc CHANGED
@@ -267,3 +267,20 @@ Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info) {
267
267
  return Napi::Boolean::New(env, false);
268
268
  }
269
269
  #endif
270
+
271
+ #if defined(__GNUC__) && defined(__x86_64__)
272
+ // Are SSE 4.2 intrinsics available at runtime?
273
+ Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info) {
274
+ Napi::Env env = info.Env();
275
+ unsigned int eax, ebx, ecx, edx;
276
+ __asm__ __volatile__("cpuid"
277
+ : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
278
+ : "a"(1));
279
+ return Napi::Boolean::New(env, (ecx & 1U << 20) != 0);
280
+ }
281
+ #else
282
+ Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info) {
283
+ Napi::Env env = info.Env();
284
+ return Napi::Boolean::New(env, false);
285
+ }
286
+ #endif
package/src/utilities.h CHANGED
@@ -15,5 +15,6 @@ Napi::Value format(const Napi::CallbackInfo& info);
15
15
  void block(const Napi::CallbackInfo& info);
16
16
  Napi::Value _maxColourDistance(const Napi::CallbackInfo& info);
17
17
  Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info);
18
+ Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info);
18
19
 
19
20
  #endif // SRC_UTILITIES_H_