sharp 0.30.7 → 0.31.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/README.md +1 -1
- package/binding.gyp +4 -3
- package/lib/composite.js +14 -0
- package/lib/constructor.js +41 -4
- package/lib/input.js +92 -0
- package/lib/operation.js +57 -12
- package/lib/output.js +87 -23
- package/lib/resize.js +89 -12
- package/lib/utility.js +4 -0
- package/package.json +23 -21
- package/src/common.cc +90 -43
- package/src/common.h +32 -14
- package/src/libvips/cplusplus/VConnection.cpp +0 -1
- package/src/libvips/cplusplus/VError.cpp +0 -1
- package/src/libvips/cplusplus/VImage.cpp +27 -2
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -1
- package/src/libvips/cplusplus/VRegion.cpp +27 -0
- package/src/libvips/cplusplus/vips-operators.cpp +16 -1
- package/src/operations.cc +69 -25
- package/src/operations.h +7 -2
- package/src/pipeline.cc +156 -160
- package/src/pipeline.h +18 -5
- package/src/sharp.cc +0 -1
- package/src/utilities.cc +13 -2
package/lib/resize.js
CHANGED
|
@@ -92,6 +92,13 @@ function isRotationExpected (options) {
|
|
|
92
92
|
return (options.angle % 360) !== 0 || options.useExifOrientation === true || options.rotationAngle !== 0;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
function isResizeExpected (options) {
|
|
99
|
+
return options.width !== -1 || options.height !== -1;
|
|
100
|
+
}
|
|
101
|
+
|
|
95
102
|
/**
|
|
96
103
|
* Resize image to `width`, `height` or `width x height`.
|
|
97
104
|
*
|
|
@@ -123,6 +130,9 @@ function isRotationExpected (options) {
|
|
|
123
130
|
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
|
124
131
|
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
|
125
132
|
*
|
|
133
|
+
* Only one resize can occur per pipeline.
|
|
134
|
+
* Previous calls to `resize` in the same pipeline will be ignored.
|
|
135
|
+
*
|
|
126
136
|
* @example
|
|
127
137
|
* sharp(input)
|
|
128
138
|
* .resize({ width: 100 })
|
|
@@ -220,6 +230,9 @@ function isRotationExpected (options) {
|
|
|
220
230
|
* @throws {Error} Invalid parameters
|
|
221
231
|
*/
|
|
222
232
|
function resize (width, height, options) {
|
|
233
|
+
if (isResizeExpected(this.options)) {
|
|
234
|
+
this.options.debuglog('ignoring previous resize options');
|
|
235
|
+
}
|
|
223
236
|
if (is.defined(width)) {
|
|
224
237
|
if (is.object(width) && !is.defined(options)) {
|
|
225
238
|
options = width;
|
|
@@ -300,6 +313,9 @@ function resize (width, height, options) {
|
|
|
300
313
|
this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
|
|
301
314
|
}
|
|
302
315
|
}
|
|
316
|
+
if (isRotationExpected(this.options) && isResizeExpected(this.options)) {
|
|
317
|
+
this.options.rotateBeforePreExtract = true;
|
|
318
|
+
}
|
|
303
319
|
return this;
|
|
304
320
|
}
|
|
305
321
|
|
|
@@ -412,7 +428,10 @@ function extend (extend) {
|
|
|
412
428
|
* @throws {Error} Invalid parameters
|
|
413
429
|
*/
|
|
414
430
|
function extract (options) {
|
|
415
|
-
const suffix = this.options
|
|
431
|
+
const suffix = isResizeExpected(this.options) || isRotationExpected(this.options) ? 'Post' : 'Pre';
|
|
432
|
+
if (this.options[`width${suffix}`] !== -1) {
|
|
433
|
+
this.options.debuglog('ignoring previous extract options');
|
|
434
|
+
}
|
|
416
435
|
['left', 'top', 'width', 'height'].forEach(function (name) {
|
|
417
436
|
const value = options[name];
|
|
418
437
|
if (is.integer(value) && value >= 0) {
|
|
@@ -422,32 +441,90 @@ function extract (options) {
|
|
|
422
441
|
}
|
|
423
442
|
}, this);
|
|
424
443
|
// Ensure existing rotation occurs before pre-resize extraction
|
|
425
|
-
if (
|
|
426
|
-
this.options.
|
|
444
|
+
if (isRotationExpected(this.options) && !isResizeExpected(this.options)) {
|
|
445
|
+
if (this.options.widthPre === -1 || this.options.widthPost === -1) {
|
|
446
|
+
this.options.rotateBeforePreExtract = true;
|
|
447
|
+
}
|
|
427
448
|
}
|
|
428
449
|
return this;
|
|
429
450
|
}
|
|
430
451
|
|
|
431
452
|
/**
|
|
432
|
-
* Trim
|
|
433
|
-
*
|
|
453
|
+
* Trim pixels from all edges that contain values similar to the given background colour, which defaults to that of the top-left pixel.
|
|
454
|
+
*
|
|
455
|
+
* Images with an alpha channel will use the combined bounding box of alpha and non-alpha channels.
|
|
456
|
+
*
|
|
457
|
+
* If the result of this operation would trim an image to nothing then no change is made.
|
|
434
458
|
*
|
|
435
459
|
* The `info` response Object, obtained from callback of `.toFile()` or `.toBuffer()`,
|
|
436
460
|
* will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
|
437
461
|
*
|
|
438
|
-
* @
|
|
462
|
+
* @example
|
|
463
|
+
* // Trim pixels with a colour similar to that of the top-left pixel.
|
|
464
|
+
* sharp(input)
|
|
465
|
+
* .trim()
|
|
466
|
+
* .toFile(output, function(err, info) {
|
|
467
|
+
* ...
|
|
468
|
+
* });
|
|
469
|
+
* @example
|
|
470
|
+
* // Trim pixels with the exact same colour as that of the top-left pixel.
|
|
471
|
+
* sharp(input)
|
|
472
|
+
* .trim(0)
|
|
473
|
+
* .toFile(output, function(err, info) {
|
|
474
|
+
* ...
|
|
475
|
+
* });
|
|
476
|
+
* @example
|
|
477
|
+
* // Trim only pixels with a similar colour to red.
|
|
478
|
+
* sharp(input)
|
|
479
|
+
* .trim("#FF0000")
|
|
480
|
+
* .toFile(output, function(err, info) {
|
|
481
|
+
* ...
|
|
482
|
+
* });
|
|
483
|
+
* @example
|
|
484
|
+
* // Trim all "yellow-ish" pixels, being more lenient with the higher threshold.
|
|
485
|
+
* sharp(input)
|
|
486
|
+
* .trim({
|
|
487
|
+
* background: "yellow",
|
|
488
|
+
* threshold: 42,
|
|
489
|
+
* })
|
|
490
|
+
* .toFile(output, function(err, info) {
|
|
491
|
+
* ...
|
|
492
|
+
* });
|
|
493
|
+
*
|
|
494
|
+
* @param {string|number|Object} trim - the specific background colour to trim, the threshold for doing so or an Object with both.
|
|
495
|
+
* @param {string|Object} [trim.background='top-left pixel'] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel.
|
|
496
|
+
* @param {number} [trim.threshold=10] - the allowed difference from the above colour, a positive number.
|
|
439
497
|
* @returns {Sharp}
|
|
440
498
|
* @throws {Error} Invalid parameters
|
|
441
499
|
*/
|
|
442
|
-
function trim (
|
|
443
|
-
if (!is.defined(
|
|
500
|
+
function trim (trim) {
|
|
501
|
+
if (!is.defined(trim)) {
|
|
502
|
+
this.options.trimThreshold = 10;
|
|
503
|
+
} else if (is.string(trim)) {
|
|
504
|
+
this._setBackgroundColourOption('trimBackground', trim);
|
|
444
505
|
this.options.trimThreshold = 10;
|
|
445
|
-
} else if (is.number(
|
|
446
|
-
|
|
506
|
+
} else if (is.number(trim)) {
|
|
507
|
+
if (trim >= 0) {
|
|
508
|
+
this.options.trimThreshold = trim;
|
|
509
|
+
} else {
|
|
510
|
+
throw is.invalidParameterError('threshold', 'positive number', trim);
|
|
511
|
+
}
|
|
512
|
+
} else if (is.object(trim)) {
|
|
513
|
+
this._setBackgroundColourOption('trimBackground', trim.background);
|
|
514
|
+
|
|
515
|
+
if (!is.defined(trim.threshold)) {
|
|
516
|
+
this.options.trimThreshold = 10;
|
|
517
|
+
} else if (is.number(trim.threshold)) {
|
|
518
|
+
if (trim.threshold >= 0) {
|
|
519
|
+
this.options.trimThreshold = trim.threshold;
|
|
520
|
+
} else {
|
|
521
|
+
throw is.invalidParameterError('threshold', 'positive number', trim);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
447
524
|
} else {
|
|
448
|
-
throw is.invalidParameterError('
|
|
525
|
+
throw is.invalidParameterError('trim', 'string, number or object', trim);
|
|
449
526
|
}
|
|
450
|
-
if (
|
|
527
|
+
if (isRotationExpected(this.options)) {
|
|
451
528
|
this.options.rotateBeforePreExtract = true;
|
|
452
529
|
}
|
|
453
530
|
return this;
|
package/lib/utility.js
CHANGED
|
@@ -17,6 +17,10 @@ const sharp = require('./sharp');
|
|
|
17
17
|
* @returns {Object}
|
|
18
18
|
*/
|
|
19
19
|
const format = sharp.format();
|
|
20
|
+
format.heif.output.alias = ['avif', 'heic'];
|
|
21
|
+
format.jpeg.output.alias = ['jpe', 'jpg'];
|
|
22
|
+
format.tiff.output.alias = ['tif'];
|
|
23
|
+
format.jp2k.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* An Object containing the available interpolators and their proper values
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "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.
|
|
4
|
+
"version": "0.31.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -83,7 +83,9 @@
|
|
|
83
83
|
"Chris Banks <christopher.bradley.banks@gmail.com>",
|
|
84
84
|
"Ompal Singh <ompal.hitm09@gmail.com>",
|
|
85
85
|
"Brodan <christopher.hranj@gmail.com",
|
|
86
|
-
"Ankur Parihar <ankur.github@gmail.com>"
|
|
86
|
+
"Ankur Parihar <ankur.github@gmail.com>",
|
|
87
|
+
"Brahim Ait elhaj <brahima@gmail.com>",
|
|
88
|
+
"Mart Jansink <m.jansink@gmail.com>"
|
|
87
89
|
],
|
|
88
90
|
"scripts": {
|
|
89
91
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
@@ -140,46 +142,46 @@
|
|
|
140
142
|
"devDependencies": {
|
|
141
143
|
"async": "^3.2.4",
|
|
142
144
|
"cc": "^3.0.1",
|
|
143
|
-
"
|
|
144
|
-
"documentation": "^13.2.5",
|
|
145
|
+
"documentation": "^14.0.0",
|
|
145
146
|
"exif-reader": "^1.0.3",
|
|
147
|
+
"extract-zip": "^2.0.1",
|
|
146
148
|
"icc": "^2.0.0",
|
|
147
149
|
"license-checker": "^25.0.1",
|
|
148
150
|
"mocha": "^10.0.0",
|
|
149
|
-
"mock-fs": "^5.1.
|
|
151
|
+
"mock-fs": "^5.1.4",
|
|
150
152
|
"nyc": "^15.1.0",
|
|
151
|
-
"prebuild": "^11.0.
|
|
153
|
+
"prebuild": "^11.0.4",
|
|
152
154
|
"rimraf": "^3.0.2",
|
|
153
155
|
"semistandard": "^16.0.1"
|
|
154
156
|
},
|
|
155
157
|
"license": "Apache-2.0",
|
|
156
158
|
"config": {
|
|
157
|
-
"libvips": "8.
|
|
159
|
+
"libvips": "8.13.1",
|
|
158
160
|
"integrity": {
|
|
159
|
-
"darwin-arm64v8": "sha512-
|
|
160
|
-
"darwin-x64": "sha512-
|
|
161
|
-
"linux-arm64v8": "sha512-
|
|
162
|
-
"linux-armv6": "sha512-
|
|
163
|
-
"linux-armv7": "sha512-
|
|
164
|
-
"linux-x64": "sha512-
|
|
165
|
-
"linuxmusl-arm64v8": "sha512-
|
|
166
|
-
"linuxmusl-x64": "sha512-
|
|
167
|
-
"win32-arm64v8": "sha512-
|
|
168
|
-
"win32-ia32": "sha512-
|
|
169
|
-
"win32-x64": "sha512-
|
|
161
|
+
"darwin-arm64v8": "sha512-JdpGTx67RDbvRkg3ljFvTzqoq+oBXmMdDFEp0expDYXmP5HLH+GCkikmsROlGltgfKE2KqL/qwpxTEhIwMK/3A==",
|
|
162
|
+
"darwin-x64": "sha512-0Oh4/hEDnzV+X8MiiyUQ4G/Zh/MHw9rKstfuX0P1czgaxS2hX8Pxdbzdk1oqwTOEYVEGO/hMm9ItCVZ3RVPPaA==",
|
|
163
|
+
"linux-arm64v8": "sha512-9pSlPzEojt6ue5vXfASNMhQO1YS1p4i4Wydu+bzOfMtIPSBRXbu/+y8WELbbo03Ts7pftm9KtrMHitCVdy5EXw==",
|
|
164
|
+
"linux-armv6": "sha512-sv2FqS/ggpQly7h5/+nh8txQDulolE5ptaE90PO7iwfTont8N42pudeqootWKsuf0fRmkW4M92184VfVVYCvGw==",
|
|
165
|
+
"linux-armv7": "sha512-LmQIB8FDfasK6BsFhnE7ZI3LMlxh/rF5tZRNQ/uoTbF2xrtWQqqgiZgCifJByiEM+1tR7RxwNdnjxZhWvM9WmQ==",
|
|
166
|
+
"linux-x64": "sha512-JBRf8WBnlVw/K1jpSvmeZpnGZGjeqhG2NDEiQV/hUze3zgDGwDza4oiworaQExQmKcDrc2LJKF14Nsz1qQSNJw==",
|
|
167
|
+
"linuxmusl-arm64v8": "sha512-yzUQO5isDwsRpEUxbMXBeWp0sKhWghebrSK46SUF5mvB/kq6hZ7JbRuJ2aZjE84K/HUTyuCc0kE+M3m8naOs+g==",
|
|
168
|
+
"linuxmusl-x64": "sha512-H3Vz1QaaZ6X5iEbfPST7TPFwDO01tI8dk1osLm6l4a17BWCaOMaBQlqxgTgYrtd09JJ9CvGoq5fo5j5TPxUc4Q==",
|
|
169
|
+
"win32-arm64v8": "sha512-b5Ver+uwOJhdOGqvZVM+qF2KLKcowcac/wKK5Fg0czqlSMqP/KxDF2kxw2eKXUJNgfqe4eDH1QG/yTg2pQSetQ==",
|
|
170
|
+
"win32-ia32": "sha512-h/SJ/Yfn0ce9H70vt1wS8rZ4PfHnguCCTsOGik7e6O/e2AlBQOM0mKsPIB9jSOquoCP8rP0qF6AOPOjXKnCk+w==",
|
|
171
|
+
"win32-x64": "sha512-p9qpdWdhZooPteib92Kk+qF1vvzcScxvOwdIP8muhgo/A8uDI4/mqXCpEbMBw6vjETKlS3qo2JUbVF6+0/lyWQ=="
|
|
170
172
|
},
|
|
171
173
|
"runtime": "napi",
|
|
172
|
-
"target":
|
|
174
|
+
"target": 7
|
|
173
175
|
},
|
|
174
176
|
"engines": {
|
|
175
|
-
"node": ">=
|
|
177
|
+
"node": ">=14.15.0"
|
|
176
178
|
},
|
|
177
179
|
"funding": {
|
|
178
180
|
"url": "https://opencollective.com/libvips"
|
|
179
181
|
},
|
|
180
182
|
"binary": {
|
|
181
183
|
"napi_versions": [
|
|
182
|
-
|
|
184
|
+
7
|
|
183
185
|
]
|
|
184
186
|
},
|
|
185
187
|
"semistandard": {
|
package/src/common.cc
CHANGED
|
@@ -88,18 +88,14 @@ namespace sharp {
|
|
|
88
88
|
descriptor->buffer = buffer.Data();
|
|
89
89
|
descriptor->isBuffer = TRUE;
|
|
90
90
|
}
|
|
91
|
-
descriptor->failOn =
|
|
92
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_FAIL_ON,
|
|
93
|
-
AttrAsStr(input, "failOn").data()));
|
|
91
|
+
descriptor->failOn = AttrAsEnum<VipsFailOn>(input, "failOn", VIPS_TYPE_FAIL_ON);
|
|
94
92
|
// Density for vector-based input
|
|
95
93
|
if (HasAttr(input, "density")) {
|
|
96
94
|
descriptor->density = AttrAsDouble(input, "density");
|
|
97
95
|
}
|
|
98
96
|
// Raw pixel input
|
|
99
97
|
if (HasAttr(input, "rawChannels")) {
|
|
100
|
-
descriptor->rawDepth =
|
|
101
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_BAND_FORMAT,
|
|
102
|
-
AttrAsStr(input, "rawDepth").data()));
|
|
98
|
+
descriptor->rawDepth = AttrAsEnum<VipsBandFormat>(input, "rawDepth", VIPS_TYPE_BAND_FORMAT);
|
|
103
99
|
descriptor->rawChannels = AttrAsUint32(input, "rawChannels");
|
|
104
100
|
descriptor->rawWidth = AttrAsUint32(input, "rawWidth");
|
|
105
101
|
descriptor->rawHeight = AttrAsUint32(input, "rawHeight");
|
|
@@ -133,11 +129,42 @@ namespace sharp {
|
|
|
133
129
|
descriptor->createBackground = AttrAsVectorOfDouble(input, "createBackground");
|
|
134
130
|
}
|
|
135
131
|
}
|
|
132
|
+
// Create new image with text
|
|
133
|
+
if (HasAttr(input, "textValue")) {
|
|
134
|
+
descriptor->textValue = AttrAsStr(input, "textValue");
|
|
135
|
+
if (HasAttr(input, "textFont")) {
|
|
136
|
+
descriptor->textFont = AttrAsStr(input, "textFont");
|
|
137
|
+
}
|
|
138
|
+
if (HasAttr(input, "textFontfile")) {
|
|
139
|
+
descriptor->textFontfile = AttrAsStr(input, "textFontfile");
|
|
140
|
+
}
|
|
141
|
+
if (HasAttr(input, "textWidth")) {
|
|
142
|
+
descriptor->textWidth = AttrAsUint32(input, "textWidth");
|
|
143
|
+
}
|
|
144
|
+
if (HasAttr(input, "textHeight")) {
|
|
145
|
+
descriptor->textHeight = AttrAsUint32(input, "textHeight");
|
|
146
|
+
}
|
|
147
|
+
if (HasAttr(input, "textAlign")) {
|
|
148
|
+
descriptor->textAlign = AttrAsEnum<VipsAlign>(input, "textAlign", VIPS_TYPE_ALIGN);
|
|
149
|
+
}
|
|
150
|
+
if (HasAttr(input, "textJustify")) {
|
|
151
|
+
descriptor->textJustify = AttrAsBool(input, "textJustify");
|
|
152
|
+
}
|
|
153
|
+
if (HasAttr(input, "textDpi")) {
|
|
154
|
+
descriptor->textDpi = AttrAsUint32(input, "textDpi");
|
|
155
|
+
}
|
|
156
|
+
if (HasAttr(input, "textRgba")) {
|
|
157
|
+
descriptor->textRgba = AttrAsBool(input, "textRgba");
|
|
158
|
+
}
|
|
159
|
+
if (HasAttr(input, "textSpacing")) {
|
|
160
|
+
descriptor->textSpacing = AttrAsUint32(input, "textSpacing");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
136
163
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
137
164
|
descriptor->limitInputPixels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputPixels"));
|
|
138
165
|
// Allow switch from random to sequential access
|
|
139
166
|
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
|
140
|
-
// Remove safety features and allow unlimited
|
|
167
|
+
// Remove safety features and allow unlimited input
|
|
141
168
|
descriptor->unlimited = AttrAsBool(input, "unlimited");
|
|
142
169
|
return descriptor;
|
|
143
170
|
}
|
|
@@ -250,9 +277,9 @@ namespace sharp {
|
|
|
250
277
|
{ "VipsForeignLoadMagickBuffer", ImageType::MAGICK },
|
|
251
278
|
{ "VipsForeignLoadMagick7File", ImageType::MAGICK },
|
|
252
279
|
{ "VipsForeignLoadMagick7Buffer", ImageType::MAGICK },
|
|
253
|
-
{ "
|
|
280
|
+
{ "VipsForeignLoadOpenslideFile", ImageType::OPENSLIDE },
|
|
254
281
|
{ "VipsForeignLoadPpmFile", ImageType::PPM },
|
|
255
|
-
{ "
|
|
282
|
+
{ "VipsForeignLoadFitsFile", ImageType::FITS },
|
|
256
283
|
{ "VipsForeignLoadOpenexr", ImageType::EXR },
|
|
257
284
|
{ "VipsForeignLoadVips", ImageType::VIPS },
|
|
258
285
|
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
|
|
@@ -307,6 +334,17 @@ namespace sharp {
|
|
|
307
334
|
imageType == ImageType::PDF;
|
|
308
335
|
}
|
|
309
336
|
|
|
337
|
+
/*
|
|
338
|
+
Does this image type support removal of safety limits?
|
|
339
|
+
*/
|
|
340
|
+
bool ImageTypeSupportsUnlimited(ImageType imageType) {
|
|
341
|
+
return
|
|
342
|
+
imageType == ImageType::JPEG ||
|
|
343
|
+
imageType == ImageType::PNG ||
|
|
344
|
+
imageType == ImageType::SVG ||
|
|
345
|
+
imageType == ImageType::HEIF;
|
|
346
|
+
}
|
|
347
|
+
|
|
310
348
|
/*
|
|
311
349
|
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
|
312
350
|
*/
|
|
@@ -335,7 +373,7 @@ namespace sharp {
|
|
|
335
373
|
vips::VOption *option = VImage::option()
|
|
336
374
|
->set("access", descriptor->access)
|
|
337
375
|
->set("fail_on", descriptor->failOn);
|
|
338
|
-
if (descriptor->unlimited && (imageType
|
|
376
|
+
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
|
339
377
|
option->set("unlimited", TRUE);
|
|
340
378
|
}
|
|
341
379
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -366,34 +404,63 @@ namespace sharp {
|
|
|
366
404
|
}
|
|
367
405
|
}
|
|
368
406
|
} else {
|
|
369
|
-
|
|
407
|
+
int const channels = descriptor->createChannels;
|
|
408
|
+
if (channels > 0) {
|
|
370
409
|
// Create new image
|
|
371
410
|
if (descriptor->createNoiseType == "gaussian") {
|
|
372
|
-
int const channels = descriptor->createChannels;
|
|
373
|
-
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight);
|
|
374
411
|
std::vector<VImage> bands = {};
|
|
375
412
|
bands.reserve(channels);
|
|
376
413
|
for (int _band = 0; _band < channels; _band++) {
|
|
377
|
-
bands.push_back(
|
|
378
|
-
descriptor->
|
|
379
|
-
descriptor->
|
|
380
|
-
VImage::option()->set("mean", descriptor->createNoiseMean)->set("sigma", descriptor->createNoiseSigma)));
|
|
414
|
+
bands.push_back(VImage::gaussnoise(descriptor->createWidth, descriptor->createHeight, VImage::option()
|
|
415
|
+
->set("mean", descriptor->createNoiseMean)
|
|
416
|
+
->set("sigma", descriptor->createNoiseSigma)));
|
|
381
417
|
}
|
|
382
|
-
image =
|
|
418
|
+
image = VImage::bandjoin(bands).copy(VImage::option()->set("interpretation",
|
|
419
|
+
channels < 3 ? VIPS_INTERPRETATION_B_W: VIPS_INTERPRETATION_sRGB));
|
|
383
420
|
} else {
|
|
384
421
|
std::vector<double> background = {
|
|
385
422
|
descriptor->createBackground[0],
|
|
386
423
|
descriptor->createBackground[1],
|
|
387
424
|
descriptor->createBackground[2]
|
|
388
425
|
};
|
|
389
|
-
if (
|
|
426
|
+
if (channels == 4) {
|
|
390
427
|
background.push_back(descriptor->createBackground[3]);
|
|
391
428
|
}
|
|
392
|
-
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight)
|
|
429
|
+
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight)
|
|
430
|
+
.copy(VImage::option()->set("interpretation",
|
|
431
|
+
channels < 3 ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_sRGB))
|
|
432
|
+
.new_from_image(background);
|
|
393
433
|
}
|
|
394
|
-
image.get_image()->Type = image.guess_interpretation();
|
|
395
434
|
image = image.cast(VIPS_FORMAT_UCHAR);
|
|
396
435
|
imageType = ImageType::RAW;
|
|
436
|
+
} else if (descriptor->textValue.length() > 0) {
|
|
437
|
+
// Create a new image with text
|
|
438
|
+
vips::VOption *textOptions = VImage::option()
|
|
439
|
+
->set("align", descriptor->textAlign)
|
|
440
|
+
->set("justify", descriptor->textJustify)
|
|
441
|
+
->set("rgba", descriptor->textRgba)
|
|
442
|
+
->set("spacing", descriptor->textSpacing)
|
|
443
|
+
->set("autofit_dpi", &descriptor->textAutofitDpi);
|
|
444
|
+
if (descriptor->textWidth > 0) {
|
|
445
|
+
textOptions->set("width", descriptor->textWidth);
|
|
446
|
+
}
|
|
447
|
+
// Ignore dpi if height is set
|
|
448
|
+
if (descriptor->textWidth > 0 && descriptor->textHeight > 0) {
|
|
449
|
+
textOptions->set("height", descriptor->textHeight);
|
|
450
|
+
} else if (descriptor->textDpi > 0) {
|
|
451
|
+
textOptions->set("dpi", descriptor->textDpi);
|
|
452
|
+
}
|
|
453
|
+
if (descriptor->textFont.length() > 0) {
|
|
454
|
+
textOptions->set("font", const_cast<char*>(descriptor->textFont.data()));
|
|
455
|
+
}
|
|
456
|
+
if (descriptor->textFontfile.length() > 0) {
|
|
457
|
+
textOptions->set("fontfile", const_cast<char*>(descriptor->textFontfile.data()));
|
|
458
|
+
}
|
|
459
|
+
image = VImage::text(const_cast<char *>(descriptor->textValue.data()), textOptions);
|
|
460
|
+
if (!descriptor->textRgba) {
|
|
461
|
+
image = image.copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_B_W));
|
|
462
|
+
}
|
|
463
|
+
imageType = ImageType::RAW;
|
|
397
464
|
} else {
|
|
398
465
|
// From filesystem
|
|
399
466
|
imageType = DetermineImageType(descriptor->file.data());
|
|
@@ -409,7 +476,7 @@ namespace sharp {
|
|
|
409
476
|
vips::VOption *option = VImage::option()
|
|
410
477
|
->set("access", descriptor->access)
|
|
411
478
|
->set("fail_on", descriptor->failOn);
|
|
412
|
-
if (descriptor->unlimited && (imageType
|
|
479
|
+
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
|
413
480
|
option->set("unlimited", TRUE);
|
|
414
481
|
}
|
|
415
482
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -637,7 +704,6 @@ namespace sharp {
|
|
|
637
704
|
Event listener for progress updates, used to detect timeout
|
|
638
705
|
*/
|
|
639
706
|
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
|
640
|
-
// printf("VipsProgressCallBack progress=%d run=%d timeout=%d\n", progress->percent, progress->run, *timeout);
|
|
641
707
|
if (*timeout > 0 && progress->run >= *timeout) {
|
|
642
708
|
vips_image_set_kill(im, TRUE);
|
|
643
709
|
vips_error("timeout", "%d%% complete", progress->percent);
|
|
@@ -794,22 +860,6 @@ namespace sharp {
|
|
|
794
860
|
return Is16Bit(interpretation) ? 65535.0 : 255.0;
|
|
795
861
|
}
|
|
796
862
|
|
|
797
|
-
/*
|
|
798
|
-
Get boolean operation type from string
|
|
799
|
-
*/
|
|
800
|
-
VipsOperationBoolean GetBooleanOperation(std::string const opStr) {
|
|
801
|
-
return static_cast<VipsOperationBoolean>(
|
|
802
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_OPERATION_BOOLEAN, opStr.data()));
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
/*
|
|
806
|
-
Get interpretation type from string
|
|
807
|
-
*/
|
|
808
|
-
VipsInterpretation GetInterpretation(std::string const typeStr) {
|
|
809
|
-
return static_cast<VipsInterpretation>(
|
|
810
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_INTERPRETATION, typeStr.data()));
|
|
811
|
-
}
|
|
812
|
-
|
|
813
863
|
/*
|
|
814
864
|
Convert RGBA value to another colourspace
|
|
815
865
|
*/
|
|
@@ -890,7 +940,7 @@ namespace sharp {
|
|
|
890
940
|
|
|
891
941
|
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
892
942
|
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
|
|
893
|
-
if (swap) {
|
|
943
|
+
if (swap && canvas != Canvas::IGNORE_ASPECT) {
|
|
894
944
|
// Swap input width and height when requested.
|
|
895
945
|
std::swap(width, height);
|
|
896
946
|
}
|
|
@@ -921,9 +971,6 @@ namespace sharp {
|
|
|
921
971
|
}
|
|
922
972
|
break;
|
|
923
973
|
case Canvas::IGNORE_ASPECT:
|
|
924
|
-
if (swap) {
|
|
925
|
-
std::swap(hshrink, vshrink);
|
|
926
|
-
}
|
|
927
974
|
break;
|
|
928
975
|
}
|
|
929
976
|
} else if (targetWidth > 0) {
|
package/src/common.h
CHANGED
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
// Verify platform and compiler compatibility
|
|
26
26
|
|
|
27
27
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
28
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
29
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
30
|
-
#error "libvips version 8.
|
|
28
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 13) || \
|
|
29
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION < 1)
|
|
30
|
+
#error "libvips version 8.13.1+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
31
31
|
#endif
|
|
32
32
|
|
|
33
33
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
|
@@ -71,6 +71,17 @@ namespace sharp {
|
|
|
71
71
|
std::string createNoiseType;
|
|
72
72
|
double createNoiseMean;
|
|
73
73
|
double createNoiseSigma;
|
|
74
|
+
std::string textValue;
|
|
75
|
+
std::string textFont;
|
|
76
|
+
std::string textFontfile;
|
|
77
|
+
int textWidth;
|
|
78
|
+
int textHeight;
|
|
79
|
+
VipsAlign textAlign;
|
|
80
|
+
bool textJustify;
|
|
81
|
+
int textDpi;
|
|
82
|
+
bool textRgba;
|
|
83
|
+
int textSpacing;
|
|
84
|
+
int textAutofitDpi;
|
|
74
85
|
|
|
75
86
|
InputDescriptor():
|
|
76
87
|
buffer(nullptr),
|
|
@@ -95,7 +106,15 @@ namespace sharp {
|
|
|
95
106
|
createHeight(0),
|
|
96
107
|
createBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
97
108
|
createNoiseMean(0.0),
|
|
98
|
-
createNoiseSigma(0.0)
|
|
109
|
+
createNoiseSigma(0.0),
|
|
110
|
+
textWidth(0),
|
|
111
|
+
textHeight(0),
|
|
112
|
+
textAlign(VIPS_ALIGN_LOW),
|
|
113
|
+
textJustify(FALSE),
|
|
114
|
+
textDpi(72),
|
|
115
|
+
textRgba(FALSE),
|
|
116
|
+
textSpacing(0),
|
|
117
|
+
textAutofitDpi(0) {}
|
|
99
118
|
};
|
|
100
119
|
|
|
101
120
|
// Convenience methods to access the attributes of a Napi::Object
|
|
@@ -110,6 +129,10 @@ namespace sharp {
|
|
|
110
129
|
bool AttrAsBool(Napi::Object obj, std::string attr);
|
|
111
130
|
std::vector<double> AttrAsVectorOfDouble(Napi::Object obj, std::string attr);
|
|
112
131
|
std::vector<int32_t> AttrAsInt32Vector(Napi::Object obj, std::string attr);
|
|
132
|
+
template <class T> T AttrAsEnum(Napi::Object obj, std::string attr, GType type) {
|
|
133
|
+
return static_cast<T>(
|
|
134
|
+
vips_enum_from_nick(nullptr, type, AttrAsStr(obj, attr).data()));
|
|
135
|
+
}
|
|
113
136
|
|
|
114
137
|
// Create an InputDescriptor instance from a Napi::Object describing an input image
|
|
115
138
|
InputDescriptor* CreateInputDescriptor(Napi::Object input);
|
|
@@ -183,6 +206,11 @@ namespace sharp {
|
|
|
183
206
|
*/
|
|
184
207
|
bool ImageTypeSupportsPage(ImageType imageType);
|
|
185
208
|
|
|
209
|
+
/*
|
|
210
|
+
Does this image type support removal of safety limits?
|
|
211
|
+
*/
|
|
212
|
+
bool ImageTypeSupportsUnlimited(ImageType imageType);
|
|
213
|
+
|
|
186
214
|
/*
|
|
187
215
|
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
|
188
216
|
*/
|
|
@@ -307,16 +335,6 @@ namespace sharp {
|
|
|
307
335
|
*/
|
|
308
336
|
double MaximumImageAlpha(VipsInterpretation const interpretation);
|
|
309
337
|
|
|
310
|
-
/*
|
|
311
|
-
Get boolean operation type from string
|
|
312
|
-
*/
|
|
313
|
-
VipsOperationBoolean GetBooleanOperation(std::string const opStr);
|
|
314
|
-
|
|
315
|
-
/*
|
|
316
|
-
Get interpretation type from string
|
|
317
|
-
*/
|
|
318
|
-
VipsInterpretation GetInterpretation(std::string const typeStr);
|
|
319
|
-
|
|
320
338
|
/*
|
|
321
339
|
Convert RGBA value to another colourspace
|
|
322
340
|
*/
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
#ifdef HAVE_CONFIG_H
|
|
39
39
|
#include <config.h>
|
|
40
40
|
#endif /*HAVE_CONFIG_H*/
|
|
41
|
-
#include <vips/intl.h>
|
|
42
41
|
|
|
43
42
|
#include <vips/vips8>
|
|
44
43
|
|
|
@@ -733,7 +732,7 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size,
|
|
|
733
732
|
set( "in", *this )->
|
|
734
733
|
set( "target", target ) );
|
|
735
734
|
|
|
736
|
-
g_object_get( target.get_target(), "blob", &blob, NULL );
|
|
735
|
+
g_object_get( target.get_target(), "blob", &blob, (void *) NULL );
|
|
737
736
|
}
|
|
738
737
|
else if( (operation_name = vips_foreign_find_save_buffer( filename )) ) {
|
|
739
738
|
call_option_string( operation_name, option_string,
|
|
@@ -778,6 +777,32 @@ VImage::write_to_target( const char *suffix, VTarget target,
|
|
|
778
777
|
set( "target", target ) );
|
|
779
778
|
}
|
|
780
779
|
|
|
780
|
+
VRegion
|
|
781
|
+
VImage::region() const
|
|
782
|
+
{
|
|
783
|
+
return VRegion::new_from_image( *this );
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
VRegion
|
|
787
|
+
VImage::region( VipsRect *rect ) const
|
|
788
|
+
{
|
|
789
|
+
VRegion region = VRegion::new_from_image( *this );
|
|
790
|
+
|
|
791
|
+
region.prepare( rect );
|
|
792
|
+
|
|
793
|
+
return region;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
VRegion
|
|
797
|
+
VImage::region( int left, int top, int width, int height ) const
|
|
798
|
+
{
|
|
799
|
+
VRegion region = VRegion::new_from_image( *this );
|
|
800
|
+
|
|
801
|
+
region.prepare( left, top, width, height );
|
|
802
|
+
|
|
803
|
+
return region;
|
|
804
|
+
}
|
|
805
|
+
|
|
781
806
|
#include "vips-operators.cpp"
|
|
782
807
|
|
|
783
808
|
std::vector<VImage>
|