@revizly/sharp 0.33.4-revizly6 → 0.33.5-revizly1
Sign up to get free protection for your applications and to get access to all the features.
- package/install/check.js +1 -1
- package/lib/constructor.js +2 -0
- package/lib/index.d.ts +20 -2
- package/lib/input.js +1 -0
- package/lib/libvips.js +2 -2
- package/lib/operation.js +44 -5
- package/lib/sharp.js +2 -4
- package/package.json +14 -12
- package/src/binding.gyp +1 -1
- package/src/common.h +2 -2
- package/src/metadata.cc +33 -0
- package/src/metadata.h +3 -0
- package/src/operations.cc +4 -2
- package/src/operations.h +1 -1
- package/src/pipeline.cc +4 -1
- package/src/pipeline.h +2 -0
package/install/check.js
CHANGED
package/lib/constructor.js
CHANGED
package/lib/index.d.ts
CHANGED
@@ -464,7 +464,7 @@ declare namespace sharp {
|
|
464
464
|
* @throws {Error} Invalid parameters
|
465
465
|
* @returns A sharp instance that can be used to chain operations
|
466
466
|
*/
|
467
|
-
blur(sigma?: number | boolean): Sharp;
|
467
|
+
blur(sigma?: number | boolean | BlurOptions): Sharp;
|
468
468
|
|
469
469
|
/**
|
470
470
|
* Merge alpha transparency channel, if any, with background.
|
@@ -1069,7 +1069,7 @@ declare namespace sharp {
|
|
1069
1069
|
/** Number of pixels per inch (DPI), if present */
|
1070
1070
|
density?: number | undefined;
|
1071
1071
|
/** String containing JPEG chroma subsampling, 4:2:0 or 4:4:4 for RGB, 4:2:0:4 or 4:4:4:4 for CMYK */
|
1072
|
-
chromaSubsampling
|
1072
|
+
chromaSubsampling?: string | undefined;
|
1073
1073
|
/** Boolean indicating whether the image is interlaced using a progressive scan */
|
1074
1074
|
isProgressive?: boolean | undefined;
|
1075
1075
|
/** Number of pages/frames contained within the image, with support for TIFF, HEIF, PDF, animated GIF and animated WebP */
|
@@ -1108,6 +1108,8 @@ declare namespace sharp {
|
|
1108
1108
|
resolutionUnit?: 'inch' | 'cm' | undefined;
|
1109
1109
|
/** String containing format for images loaded via *magick */
|
1110
1110
|
formatMagick?: string | undefined;
|
1111
|
+
/** Array of keyword/text pairs representing PNG text blocks, if present. */
|
1112
|
+
comments?: CommentsMetadata[] | undefined;
|
1111
1113
|
}
|
1112
1114
|
|
1113
1115
|
interface LevelMetadata {
|
@@ -1115,6 +1117,11 @@ declare namespace sharp {
|
|
1115
1117
|
height: number;
|
1116
1118
|
}
|
1117
1119
|
|
1120
|
+
interface CommentsMetadata {
|
1121
|
+
keyword: string;
|
1122
|
+
text: string;
|
1123
|
+
}
|
1124
|
+
|
1118
1125
|
interface Stats {
|
1119
1126
|
/** Array of channel statistics for each channel in the image. */
|
1120
1127
|
channels: ChannelStats[];
|
@@ -1335,6 +1342,17 @@ declare namespace sharp {
|
|
1335
1342
|
background?: Color | undefined;
|
1336
1343
|
}
|
1337
1344
|
|
1345
|
+
type Precision = 'integer' | 'float' | 'approximate';
|
1346
|
+
|
1347
|
+
interface BlurOptions {
|
1348
|
+
/** A value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2` */
|
1349
|
+
sigma: number;
|
1350
|
+
/** A value between 0.001 and 1. A smaller value will generate a larger, more accurate mask. */
|
1351
|
+
minAmplitude?: number;
|
1352
|
+
/** How accurate the operation should be, one of: integer, float, approximate. (optional, default "integer") */
|
1353
|
+
precision?: Precision | undefined;
|
1354
|
+
}
|
1355
|
+
|
1338
1356
|
interface FlattenOptions {
|
1339
1357
|
/** background colour, parsed by the color module, defaults to black. (optional, default {r:0,g:0,b:0}) */
|
1340
1358
|
background?: Color | undefined;
|
package/lib/input.js
CHANGED
@@ -450,6 +450,7 @@ function _isStreamInput () {
|
|
450
450
|
* - `xmp`: Buffer containing raw XMP data, if present
|
451
451
|
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
|
452
452
|
* - `formatMagick`: String containing format for images loaded via *magick
|
453
|
+
* - `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
|
453
454
|
*
|
454
455
|
* @example
|
455
456
|
* const metadata = await sharp(input).metadata();
|
package/lib/libvips.js
CHANGED
@@ -10,10 +10,10 @@ const semverGreaterThanOrEqualTo = require('semver/functions/gte');
|
|
10
10
|
const semverSatisfies = require('semver/functions/satisfies');
|
11
11
|
const detectLibc = require('detect-libc');
|
12
12
|
|
13
|
-
const { engines, optionalDependencies } = require('../package.json');
|
13
|
+
const { config, engines, optionalDependencies } = require('../package.json');
|
14
14
|
|
15
15
|
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || /* istanbul ignore next */
|
16
|
-
|
16
|
+
config.libvips;
|
17
17
|
const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
18
18
|
|
19
19
|
const prebuiltPlatforms = [
|
package/lib/operation.js
CHANGED
@@ -6,6 +6,17 @@
|
|
6
6
|
const color = require('color');
|
7
7
|
const is = require('./is');
|
8
8
|
|
9
|
+
/**
|
10
|
+
* How accurate an operation should be.
|
11
|
+
* @member
|
12
|
+
* @private
|
13
|
+
*/
|
14
|
+
const vipsPrecision = {
|
15
|
+
integer: 'integer',
|
16
|
+
float: 'float',
|
17
|
+
approximate: 'approximate'
|
18
|
+
};
|
19
|
+
|
9
20
|
/**
|
10
21
|
* Rotate the output image by either an explicit angle
|
11
22
|
* or auto-orient based on the EXIF `Orientation` tag.
|
@@ -367,23 +378,51 @@ function median (size) {
|
|
367
378
|
* .blur(5)
|
368
379
|
* .toBuffer();
|
369
380
|
*
|
370
|
-
* @param {number} [
|
381
|
+
* @param {Object|number|Boolean} [options]
|
382
|
+
* @param {number} [options.sigma] a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
|
383
|
+
* @param {string} [options.precision='integer'] How accurate the operation should be, one of: integer, float, approximate.
|
384
|
+
* @param {number} [options.minAmplitude=0.2] A value between 0.001 and 1. A smaller value will generate a larger, more accurate mask.
|
371
385
|
* @returns {Sharp}
|
372
386
|
* @throws {Error} Invalid parameters
|
373
387
|
*/
|
374
|
-
function blur (
|
375
|
-
|
388
|
+
function blur (options) {
|
389
|
+
let sigma;
|
390
|
+
if (is.number(options)) {
|
391
|
+
sigma = options;
|
392
|
+
} else if (is.plainObject(options)) {
|
393
|
+
if (!is.number(options.sigma)) {
|
394
|
+
throw is.invalidParameterError('options.sigma', 'number between 0.3 and 1000', sigma);
|
395
|
+
}
|
396
|
+
sigma = options.sigma;
|
397
|
+
if ('precision' in options) {
|
398
|
+
if (is.string(vipsPrecision[options.precision])) {
|
399
|
+
this.options.precision = vipsPrecision[options.precision];
|
400
|
+
} else {
|
401
|
+
throw is.invalidParameterError('precision', 'one of: integer, float, approximate', options.precision);
|
402
|
+
}
|
403
|
+
}
|
404
|
+
if ('minAmplitude' in options) {
|
405
|
+
if (is.number(options.minAmplitude) && is.inRange(options.minAmplitude, 0.001, 1)) {
|
406
|
+
this.options.minAmpl = options.minAmplitude;
|
407
|
+
} else {
|
408
|
+
throw is.invalidParameterError('minAmplitude', 'number between 0.001 and 1', options.minAmplitude);
|
409
|
+
}
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
if (!is.defined(options)) {
|
376
414
|
// No arguments: default to mild blur
|
377
415
|
this.options.blurSigma = -1;
|
378
|
-
} else if (is.bool(
|
416
|
+
} else if (is.bool(options)) {
|
379
417
|
// Boolean argument: apply mild blur?
|
380
|
-
this.options.blurSigma =
|
418
|
+
this.options.blurSigma = options ? -1 : 0;
|
381
419
|
} else if (is.number(sigma) && is.inRange(sigma, 0.3, 1000)) {
|
382
420
|
// Numeric argument: specific sigma
|
383
421
|
this.options.blurSigma = sigma;
|
384
422
|
} else {
|
385
423
|
throw is.invalidParameterError('sigma', 'number between 0.3 and 1000', sigma);
|
386
424
|
}
|
425
|
+
|
387
426
|
return this;
|
388
427
|
}
|
389
428
|
|
package/lib/sharp.js
CHANGED
@@ -57,7 +57,6 @@ if (sharp) {
|
|
57
57
|
help.push(
|
58
58
|
'- Ensure optional dependencies can be installed:',
|
59
59
|
' npm install --include=optional sharp',
|
60
|
-
' yarn add sharp --ignore-engines',
|
61
60
|
'- Ensure your package manager supports multi-platform installation:',
|
62
61
|
' See https://sharp.pixelplumbing.com/install#cross-platform',
|
63
62
|
'- Add platform-specific dependencies:',
|
@@ -73,10 +72,9 @@ if (sharp) {
|
|
73
72
|
}
|
74
73
|
if (isLinux && /(symbol not found|CXXABI_)/i.test(messages)) {
|
75
74
|
try {
|
76
|
-
const {
|
77
|
-
|
75
|
+
const { config } = require(`@revizly/sharp-libvips-${runtimePlatform}/package`);
|
78
76
|
const libcFound = `${familySync()} ${versionSync()}`;
|
79
|
-
const libcRequires = `${
|
77
|
+
const libcRequires = `${config.musl ? 'musl' : 'glibc'} ${config.musl || config.glibc}`;
|
80
78
|
help.push(
|
81
79
|
'- Update your OS:',
|
82
80
|
` Found ${libcFound}`,
|
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.33.
|
4
|
+
"version": "0.33.5-revizly1",
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
6
6
|
"homepage": "https://sharp.pixelplumbing.com",
|
7
7
|
"contributors": [
|
@@ -139,17 +139,17 @@
|
|
139
139
|
"dependencies": {
|
140
140
|
"color": "^4.2.3",
|
141
141
|
"detect-libc": "^2.0.3",
|
142
|
-
"semver": "^7.6.
|
142
|
+
"semver": "^7.6.3"
|
143
143
|
},
|
144
144
|
"optionalDependencies": {
|
145
|
-
"@revizly/sharp-libvips-linux-arm64": "1.0.
|
146
|
-
"@revizly/sharp-libvips-linux-x64": "1.0.
|
147
|
-
"@revizly/sharp-linux-arm64": "0.33.4-
|
148
|
-
"@revizly/sharp-linux-x64": "0.33.4-
|
145
|
+
"@revizly/sharp-libvips-linux-arm64": "1.0.8",
|
146
|
+
"@revizly/sharp-libvips-linux-x64": "1.0.8",
|
147
|
+
"@revizly/sharp-linux-arm64": "0.33.4-revizly6",
|
148
|
+
"@revizly/sharp-linux-x64": "0.33.4-revizly6"
|
149
149
|
},
|
150
150
|
"devDependencies": {
|
151
151
|
"@emnapi/runtime": "^1.2.0",
|
152
|
-
"@revizly/sharp-libvips-dev": "1.0.
|
152
|
+
"@revizly/sharp-libvips-dev": "1.0.8",
|
153
153
|
"@types/node": "*",
|
154
154
|
"async": "^3.2.5",
|
155
155
|
"cc": "^3.0.1",
|
@@ -157,10 +157,10 @@
|
|
157
157
|
"exif-reader": "^2.0.1",
|
158
158
|
"extract-zip": "^2.0.1",
|
159
159
|
"icc": "^3.0.0",
|
160
|
-
"jsdoc-to-markdown": "^8.0.
|
160
|
+
"jsdoc-to-markdown": "^8.0.3",
|
161
161
|
"license-checker": "^25.0.1",
|
162
|
-
"mocha": "^10.
|
163
|
-
"node-addon-api": "^8.
|
162
|
+
"mocha": "^10.7.3",
|
163
|
+
"node-addon-api": "^8.1.0",
|
164
164
|
"nyc": "^17.0.0",
|
165
165
|
"prebuild": "^13.0.1",
|
166
166
|
"semistandard": "^17.0.0",
|
@@ -169,8 +169,10 @@
|
|
169
169
|
},
|
170
170
|
"license": "Apache-2.0",
|
171
171
|
"engines": {
|
172
|
-
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
173
|
-
|
172
|
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
173
|
+
},
|
174
|
+
"config": {
|
175
|
+
"libvips": ">=8.15.3"
|
174
176
|
},
|
175
177
|
"funding": {
|
176
178
|
"url": "https://opencollective.com/libvips"
|
package/src/binding.gyp
CHANGED
@@ -192,7 +192,7 @@
|
|
192
192
|
'-Oz',
|
193
193
|
'-sALLOW_MEMORY_GROWTH',
|
194
194
|
'-sENVIRONMENT=node',
|
195
|
-
'-sEXPORTED_FUNCTIONS=["_vips_shutdown", "_uv_library_shutdown"]',
|
195
|
+
'-sEXPORTED_FUNCTIONS=["emnapiInit", "_vips_shutdown", "_uv_library_shutdown"]',
|
196
196
|
'-sNODERAWFS',
|
197
197
|
'-sTEXTDECODER=0',
|
198
198
|
'-sWASM_ASYNC_COMPILATION=0',
|
package/src/common.h
CHANGED
@@ -16,8 +16,8 @@
|
|
16
16
|
|
17
17
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
18
18
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 15) || \
|
19
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION <
|
20
|
-
#error "libvips version 8.15.
|
19
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 3)
|
20
|
+
#error "libvips version 8.15.3+ is required - please see https://sharp.pixelplumbing.com/install"
|
21
21
|
#endif
|
22
22
|
|
23
23
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
package/src/metadata.cc
CHANGED
@@ -10,6 +10,8 @@
|
|
10
10
|
#include "common.h"
|
11
11
|
#include "metadata.h"
|
12
12
|
|
13
|
+
static void* readPNGComment(VipsImage *image, const char *field, GValue *value, void *p);
|
14
|
+
|
13
15
|
class MetadataWorker : public Napi::AsyncWorker {
|
14
16
|
public:
|
15
17
|
MetadataWorker(Napi::Function callback, MetadataBaton *baton, Napi::Function debuglog) :
|
@@ -131,6 +133,8 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
131
133
|
memcpy(baton->tifftagPhotoshop, tifftagPhotoshop, tifftagPhotoshopLength);
|
132
134
|
baton->tifftagPhotoshopLength = tifftagPhotoshopLength;
|
133
135
|
}
|
136
|
+
// PNG comments
|
137
|
+
vips_image_map(image.get_image(), readPNGComment, &baton->comments);
|
134
138
|
}
|
135
139
|
|
136
140
|
// Clean up
|
@@ -246,6 +250,17 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
246
250
|
Napi::Buffer<char>::NewOrCopy(env, baton->tifftagPhotoshop,
|
247
251
|
baton->tifftagPhotoshopLength, sharp::FreeCallback));
|
248
252
|
}
|
253
|
+
if (baton->comments.size() > 0) {
|
254
|
+
int i = 0;
|
255
|
+
Napi::Array comments = Napi::Array::New(env, baton->comments.size());
|
256
|
+
for (auto &c : baton->comments) {
|
257
|
+
Napi::Object comment = Napi::Object::New(env);
|
258
|
+
comment.Set("keyword", c.first);
|
259
|
+
comment.Set("text", c.second);
|
260
|
+
comments.Set(i++, comment);
|
261
|
+
}
|
262
|
+
info.Set("comments", comments);
|
263
|
+
}
|
249
264
|
Callback().Call(Receiver().Value(), { env.Null(), info });
|
250
265
|
} else {
|
251
266
|
Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
@@ -285,3 +300,21 @@ Napi::Value metadata(const Napi::CallbackInfo& info) {
|
|
285
300
|
|
286
301
|
return info.Env().Undefined();
|
287
302
|
}
|
303
|
+
|
304
|
+
const char *PNG_COMMENT_START = "png-comment-";
|
305
|
+
const int PNG_COMMENT_START_LEN = strlen(PNG_COMMENT_START);
|
306
|
+
|
307
|
+
static void* readPNGComment(VipsImage *image, const char *field, GValue *value, void *p) {
|
308
|
+
MetadataComments *comments = static_cast<MetadataComments *>(p);
|
309
|
+
|
310
|
+
if (vips_isprefix(PNG_COMMENT_START, field)) {
|
311
|
+
const char *keyword = strchr(field + PNG_COMMENT_START_LEN, '-');
|
312
|
+
const char *str;
|
313
|
+
if (keyword != NULL && !vips_image_get_string(image, field, &str)) {
|
314
|
+
keyword++; // Skip the hyphen
|
315
|
+
comments->push_back(std::make_pair(keyword, str));
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
return NULL;
|
320
|
+
}
|
package/src/metadata.h
CHANGED
@@ -9,6 +9,8 @@
|
|
9
9
|
|
10
10
|
#include "./common.h"
|
11
11
|
|
12
|
+
typedef std::vector<std::pair<std::string, std::string>> MetadataComments;
|
13
|
+
|
12
14
|
struct MetadataBaton {
|
13
15
|
// Input
|
14
16
|
sharp::InputDescriptor *input;
|
@@ -47,6 +49,7 @@ struct MetadataBaton {
|
|
47
49
|
size_t xmpLength;
|
48
50
|
char *tifftagPhotoshop;
|
49
51
|
size_t tifftagPhotoshopLength;
|
52
|
+
MetadataComments comments;
|
50
53
|
std::string err;
|
51
54
|
|
52
55
|
MetadataBaton():
|
package/src/operations.cc
CHANGED
@@ -144,7 +144,7 @@ namespace sharp {
|
|
144
144
|
/*
|
145
145
|
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
146
146
|
*/
|
147
|
-
VImage Blur(VImage image, double const sigma) {
|
147
|
+
VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl) {
|
148
148
|
if (sigma == -1.0) {
|
149
149
|
// Fast, mild blur - averages neighbouring pixels
|
150
150
|
VImage blur = VImage::new_matrixv(3, 3,
|
@@ -155,7 +155,9 @@ namespace sharp {
|
|
155
155
|
return image.conv(blur);
|
156
156
|
} else {
|
157
157
|
// Slower, accurate Gaussian blur
|
158
|
-
return StaySequential(image).gaussblur(sigma)
|
158
|
+
return StaySequential(image).gaussblur(sigma, VImage::option()
|
159
|
+
->set("precision", precision)
|
160
|
+
->set("min_ampl", minAmpl));
|
159
161
|
}
|
160
162
|
}
|
161
163
|
|
package/src/operations.h
CHANGED
@@ -47,7 +47,7 @@ namespace sharp {
|
|
47
47
|
/*
|
48
48
|
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
49
49
|
*/
|
50
|
-
VImage Blur(VImage image, double const sigma);
|
50
|
+
VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl);
|
51
51
|
|
52
52
|
/*
|
53
53
|
* Convolution with a kernel.
|
package/src/pipeline.cc
CHANGED
@@ -325,6 +325,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
325
325
|
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {
|
326
326
|
// Cache input profile for use with output
|
327
327
|
inputProfile = sharp::GetProfile(image);
|
328
|
+
baton->input->ignoreIcc = true;
|
328
329
|
}
|
329
330
|
char const *processingProfile = image.interpretation() == VIPS_INTERPRETATION_RGB16 ? "p3" : "srgb";
|
330
331
|
if (
|
@@ -592,7 +593,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
592
593
|
|
593
594
|
// Blur
|
594
595
|
if (shouldBlur) {
|
595
|
-
image = sharp::Blur(image, baton->blurSigma);
|
596
|
+
image = sharp::Blur(image, baton->blurSigma, baton->precision, baton->minAmpl);
|
596
597
|
}
|
597
598
|
|
598
599
|
// Unflatten the image
|
@@ -1541,6 +1542,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
1541
1542
|
baton->negate = sharp::AttrAsBool(options, "negate");
|
1542
1543
|
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
1543
1544
|
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
1545
|
+
baton->precision = sharp::AttrAsEnum<VipsPrecision>(options, "precision", VIPS_TYPE_PRECISION);
|
1546
|
+
baton->minAmpl = sharp::AttrAsDouble(options, "minAmpl");
|
1544
1547
|
baton->brightness = sharp::AttrAsDouble(options, "brightness");
|
1545
1548
|
baton->saturation = sharp::AttrAsDouble(options, "saturation");
|
1546
1549
|
baton->hue = sharp::AttrAsInt32(options, "hue");
|