sharp 0.29.0 → 0.30.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 +2 -2
- package/binding.gyp +2 -0
- package/install/libvips.js +39 -8
- package/lib/constructor.js +20 -5
- package/lib/input.js +21 -4
- package/lib/libvips.js +16 -2
- package/lib/operation.js +31 -3
- package/lib/output.js +250 -73
- package/lib/platform.js +1 -1
- package/lib/resize.js +19 -0
- package/lib/sharp.js +11 -3
- package/lib/utility.js +22 -3
- package/package.json +30 -13
- package/src/common.cc +156 -29
- package/src/common.h +49 -7
- package/src/libvips/cplusplus/VImage.cpp +34 -16
- package/src/libvips/cplusplus/vips-operators.cpp +29 -1
- package/src/metadata.cc +6 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +98 -3
- package/src/operations.h +15 -2
- package/src/pipeline.cc +357 -268
- package/src/pipeline.h +31 -19
- package/src/sharp.cc +16 -0
- package/src/utilities.cc +1 -1
package/lib/utility.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
3
5
|
const events = require('events');
|
|
4
6
|
const detectLibc = require('detect-libc');
|
|
5
7
|
|
|
6
8
|
const is = require('./is');
|
|
9
|
+
const platformAndArch = require('./platform')();
|
|
7
10
|
const sharp = require('./sharp');
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -45,8 +48,23 @@ let versions = {
|
|
|
45
48
|
vips: sharp.libvipsVersion()
|
|
46
49
|
};
|
|
47
50
|
try {
|
|
48
|
-
versions = require(`../vendor/${versions.vips}/versions.json`);
|
|
49
|
-
} catch (
|
|
51
|
+
versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
|
|
52
|
+
} catch (_err) { /* ignore */ }
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* An Object containing the platform and architecture
|
|
56
|
+
* of the current and installed vendored binaries.
|
|
57
|
+
* @member
|
|
58
|
+
* @example
|
|
59
|
+
* console.log(sharp.vendor);
|
|
60
|
+
*/
|
|
61
|
+
const vendor = {
|
|
62
|
+
current: platformAndArch,
|
|
63
|
+
installed: []
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
vendor.installed = fs.readdirSync(path.join(__dirname, `../vendor/${versions.vips}`));
|
|
67
|
+
} catch (_err) { /* ignore */ }
|
|
50
68
|
|
|
51
69
|
/**
|
|
52
70
|
* Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
|
|
@@ -110,7 +128,7 @@ function concurrency (concurrency) {
|
|
|
110
128
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
|
111
129
|
}
|
|
112
130
|
/* istanbul ignore next */
|
|
113
|
-
if (detectLibc.
|
|
131
|
+
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
|
114
132
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
|
115
133
|
sharp.concurrency(1);
|
|
116
134
|
}
|
|
@@ -175,5 +193,6 @@ module.exports = function (Sharp) {
|
|
|
175
193
|
Sharp.format = format;
|
|
176
194
|
Sharp.interpolators = interpolators;
|
|
177
195
|
Sharp.versions = versions;
|
|
196
|
+
Sharp.vendor = vendor;
|
|
178
197
|
Sharp.queue = queue;
|
|
179
198
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sharp",
|
|
3
|
-
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
|
4
|
+
"version": "0.30.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -78,7 +78,10 @@
|
|
|
78
78
|
"Jacob Smith <jacob@frende.me>",
|
|
79
79
|
"Michael Nutt <michael@nutt.im>",
|
|
80
80
|
"Brad Parham <baparham@gmail.com>",
|
|
81
|
-
"Taneli Vatanen <taneli.vatanen@gmail.com>"
|
|
81
|
+
"Taneli Vatanen <taneli.vatanen@gmail.com>",
|
|
82
|
+
"Joris Dugué <zaruike10@gmail.com>",
|
|
83
|
+
"Chris Banks <christopher.bradley.banks@gmail.com>",
|
|
84
|
+
"Ompal Singh <ompal.hitm09@gmail.com>"
|
|
82
85
|
],
|
|
83
86
|
"scripts": {
|
|
84
87
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
@@ -112,6 +115,7 @@
|
|
|
112
115
|
"tiff",
|
|
113
116
|
"gif",
|
|
114
117
|
"svg",
|
|
118
|
+
"jp2",
|
|
115
119
|
"dzi",
|
|
116
120
|
"image",
|
|
117
121
|
"resize",
|
|
@@ -122,33 +126,46 @@
|
|
|
122
126
|
"vips"
|
|
123
127
|
],
|
|
124
128
|
"dependencies": {
|
|
125
|
-
"color": "^4.0
|
|
126
|
-
"detect-libc": "^
|
|
127
|
-
"node-addon-api": "^4.
|
|
128
|
-
"prebuild-install": "^
|
|
129
|
+
"color": "^4.2.0",
|
|
130
|
+
"detect-libc": "^2.0.0",
|
|
131
|
+
"node-addon-api": "^4.3.0",
|
|
132
|
+
"prebuild-install": "^7.0.1",
|
|
129
133
|
"semver": "^7.3.5",
|
|
130
|
-
"simple-get": "^
|
|
134
|
+
"simple-get": "^4.0.1",
|
|
131
135
|
"tar-fs": "^2.1.1",
|
|
132
136
|
"tunnel-agent": "^0.6.0"
|
|
133
137
|
},
|
|
134
138
|
"devDependencies": {
|
|
135
|
-
"async": "^3.2.
|
|
139
|
+
"async": "^3.2.3",
|
|
136
140
|
"cc": "^3.0.1",
|
|
137
141
|
"decompress-zip": "^0.3.3",
|
|
138
142
|
"documentation": "^13.2.5",
|
|
139
143
|
"exif-reader": "^1.0.3",
|
|
140
144
|
"icc": "^2.0.0",
|
|
141
145
|
"license-checker": "^25.0.1",
|
|
142
|
-
"mocha": "^9.0
|
|
143
|
-
"mock-fs": "^5.
|
|
146
|
+
"mocha": "^9.2.0",
|
|
147
|
+
"mock-fs": "^5.1.2",
|
|
144
148
|
"nyc": "^15.1.0",
|
|
145
|
-
"prebuild": "^
|
|
149
|
+
"prebuild": "^11.0.2",
|
|
146
150
|
"rimraf": "^3.0.2",
|
|
147
151
|
"semistandard": "^16.0.1"
|
|
148
152
|
},
|
|
149
153
|
"license": "Apache-2.0",
|
|
150
154
|
"config": {
|
|
151
|
-
"libvips": "8.
|
|
155
|
+
"libvips": "8.12.2",
|
|
156
|
+
"integrity": {
|
|
157
|
+
"darwin-arm64v8": "sha512-p46s/bbJAjkOXzPISZt9HUpG9GWjwQkYnLLRLKzsBJHLtB3X6C6Y/zXI5Hd0DOojcFkks9a0kTN+uDQ/XJY19g==",
|
|
158
|
+
"darwin-x64": "sha512-6vOHVZnvXwe6EXRsy29jdkUzBE6ElNpXUwd+m8vV7qy32AnXu7B9YemHsZ44vWviIwPZeXF6Nhd9EFLM0wWohw==",
|
|
159
|
+
"linux-arm64v8": "sha512-XwZdS63yhqLtbFtx/0eoLF/Agf5qtTrI11FMnMRpuBJWd4jHB60RAH+uzYUgoChCmKIS+AeXYMLm4d8Ns2QX8w==",
|
|
160
|
+
"linux-armv6": "sha512-Rh0Q0kqwPG2MjXWOkPCuPEyiUKFgKJYWLgS835D4MrXgdKr8Tft/eVrc2iGIxt2re30VpDiZ1h0Rby1aCZt2zw==",
|
|
161
|
+
"linux-armv7": "sha512-heTS/MsmRvu4JljINxP+vDiS9ZZfuGhr3IStb5F7Gc0/QLRhllYAg4rcO8L1eTK9sIIzG5ARvI19+YUZe7WbzA==",
|
|
162
|
+
"linux-x64": "sha512-SSWAwBFi0hx8V/h/v82tTFGKWTFv9FiCK3Timz5OExuI+sX1Ngrd0PVQaWXOThGNdel/fcD3Bz9YjSt4feBR1g==",
|
|
163
|
+
"linuxmusl-arm64v8": "sha512-Rhks+5C7p7aO6AucLT1uvzo8ohlqcqCUPgZmN+LZjsPWob/Iix3MfiDYtv/+gTvdeEfXxbCU6/YuPBwHQ7/crA==",
|
|
164
|
+
"linuxmusl-x64": "sha512-IOyjSQqpWVntqOUpCHVWuQwACwmmjdi15H8Pc+Ma1JkhPogTfVsFQWyL7DuOTD3Yr23EuYGzovUX00duOtfy/g==",
|
|
165
|
+
"win32-arm64v8": "sha512-A+Qe8Ipewtvw9ldvF6nWed2J8kphzrUE04nFeKCtNx6pfGQ/MAlCKMjt/U8VgUKNjB01zJDUW9XE0+FhGZ/UpQ==",
|
|
166
|
+
"win32-ia32": "sha512-cMrAvwFdDeAVnLJt0IPMPRKaIFhyXYGTprsM0DND9VUHE8F7dJMR44tS5YkXsGh1QNDtjKT6YuxAVUglmiXtpA==",
|
|
167
|
+
"win32-x64": "sha512-vLFIfw6aW2zABa8jpgzWDhljnE6glktrddErVyazAIoHl6BFFe/Da+LK1DbXvIYHz7fyOoKhSfCJHCiJG1Vg6w=="
|
|
168
|
+
},
|
|
152
169
|
"runtime": "napi",
|
|
153
170
|
"target": 5
|
|
154
171
|
},
|
package/src/common.cc
CHANGED
|
@@ -132,6 +132,8 @@ namespace sharp {
|
|
|
132
132
|
descriptor->limitInputPixels = AttrAsUint32(input, "limitInputPixels");
|
|
133
133
|
// Allow switch from random to sequential access
|
|
134
134
|
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
|
135
|
+
// Remove safety features and allow unlimited SVG/PNG input
|
|
136
|
+
descriptor->unlimited = AttrAsBool(input, "unlimited");
|
|
135
137
|
return descriptor;
|
|
136
138
|
}
|
|
137
139
|
|
|
@@ -157,6 +159,10 @@ namespace sharp {
|
|
|
157
159
|
bool IsGif(std::string const &str) {
|
|
158
160
|
return EndsWith(str, ".gif") || EndsWith(str, ".GIF");
|
|
159
161
|
}
|
|
162
|
+
bool IsJp2(std::string const &str) {
|
|
163
|
+
return EndsWith(str, ".jp2") || EndsWith(str, ".jpx") || EndsWith(str, ".j2k") || EndsWith(str, ".j2c")
|
|
164
|
+
|| EndsWith(str, ".JP2") || EndsWith(str, ".JPX") || EndsWith(str, ".J2K") || EndsWith(str, ".J2C");
|
|
165
|
+
}
|
|
160
166
|
bool IsTiff(std::string const &str) {
|
|
161
167
|
return EndsWith(str, ".tif") || EndsWith(str, ".tiff") || EndsWith(str, ".TIF") || EndsWith(str, ".TIFF");
|
|
162
168
|
}
|
|
@@ -190,6 +196,7 @@ namespace sharp {
|
|
|
190
196
|
case ImageType::WEBP: id = "webp"; break;
|
|
191
197
|
case ImageType::TIFF: id = "tiff"; break;
|
|
192
198
|
case ImageType::GIF: id = "gif"; break;
|
|
199
|
+
case ImageType::JP2: id = "jp2"; break;
|
|
193
200
|
case ImageType::SVG: id = "svg"; break;
|
|
194
201
|
case ImageType::HEIF: id = "heif"; break;
|
|
195
202
|
case ImageType::PDF: id = "pdf"; break;
|
|
@@ -226,6 +233,8 @@ namespace sharp {
|
|
|
226
233
|
{ "VipsForeignLoadGifBuffer", ImageType::GIF },
|
|
227
234
|
{ "VipsForeignLoadNsgifFile", ImageType::GIF },
|
|
228
235
|
{ "VipsForeignLoadNsgifBuffer", ImageType::GIF },
|
|
236
|
+
{ "VipsForeignLoadJp2kBuffer", ImageType::JP2 },
|
|
237
|
+
{ "VipsForeignLoadJp2kFile", ImageType::JP2 },
|
|
229
238
|
{ "VipsForeignLoadSvgFile", ImageType::SVG },
|
|
230
239
|
{ "VipsForeignLoadSvgBuffer", ImageType::SVG },
|
|
231
240
|
{ "VipsForeignLoadHeifFile", ImageType::HEIF },
|
|
@@ -234,6 +243,8 @@ namespace sharp {
|
|
|
234
243
|
{ "VipsForeignLoadPdfBuffer", ImageType::PDF },
|
|
235
244
|
{ "VipsForeignLoadMagickFile", ImageType::MAGICK },
|
|
236
245
|
{ "VipsForeignLoadMagickBuffer", ImageType::MAGICK },
|
|
246
|
+
{ "VipsForeignLoadMagick7File", ImageType::MAGICK },
|
|
247
|
+
{ "VipsForeignLoadMagick7Buffer", ImageType::MAGICK },
|
|
237
248
|
{ "VipsForeignLoadOpenslide", ImageType::OPENSLIDE },
|
|
238
249
|
{ "VipsForeignLoadPpmFile", ImageType::PPM },
|
|
239
250
|
{ "VipsForeignLoadFits", ImageType::FITS },
|
|
@@ -285,6 +296,7 @@ namespace sharp {
|
|
|
285
296
|
imageType == ImageType::WEBP ||
|
|
286
297
|
imageType == ImageType::MAGICK ||
|
|
287
298
|
imageType == ImageType::GIF ||
|
|
299
|
+
imageType == ImageType::JP2 ||
|
|
288
300
|
imageType == ImageType::TIFF ||
|
|
289
301
|
imageType == ImageType::HEIF ||
|
|
290
302
|
imageType == ImageType::PDF;
|
|
@@ -318,7 +330,7 @@ namespace sharp {
|
|
|
318
330
|
vips::VOption *option = VImage::option()
|
|
319
331
|
->set("access", descriptor->access)
|
|
320
332
|
->set("fail", descriptor->failOnError);
|
|
321
|
-
if (imageType == ImageType::SVG) {
|
|
333
|
+
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
|
322
334
|
option->set("unlimited", TRUE);
|
|
323
335
|
}
|
|
324
336
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -393,7 +405,7 @@ namespace sharp {
|
|
|
393
405
|
vips::VOption *option = VImage::option()
|
|
394
406
|
->set("access", descriptor->access)
|
|
395
407
|
->set("fail", descriptor->failOnError);
|
|
396
|
-
if (imageType == ImageType::SVG) {
|
|
408
|
+
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
|
397
409
|
option->set("unlimited", TRUE);
|
|
398
410
|
}
|
|
399
411
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -478,36 +490,41 @@ namespace sharp {
|
|
|
478
490
|
|
|
479
491
|
/*
|
|
480
492
|
Set animation properties if necessary.
|
|
481
|
-
Non-provided properties will be loaded from image.
|
|
482
493
|
*/
|
|
483
|
-
VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop) {
|
|
484
|
-
bool hasDelay = delay.
|
|
485
|
-
|
|
486
|
-
if (pageHeight == 0 && image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {
|
|
487
|
-
pageHeight = image.get_int(VIPS_META_PAGE_HEIGHT);
|
|
488
|
-
}
|
|
494
|
+
VImage SetAnimationProperties(VImage image, int nPages, int pageHeight, std::vector<int> delay, int loop) {
|
|
495
|
+
bool hasDelay = !delay.empty();
|
|
489
496
|
|
|
490
|
-
if
|
|
491
|
-
|
|
492
|
-
hasDelay = true;
|
|
493
|
-
}
|
|
497
|
+
// Avoid a copy if none of the animation properties are needed.
|
|
498
|
+
if (nPages == 1 && !hasDelay && loop == -1) return image;
|
|
494
499
|
|
|
495
|
-
if (
|
|
496
|
-
|
|
500
|
+
if (delay.size() == 1) {
|
|
501
|
+
// We have just one delay, repeat that value for all frames.
|
|
502
|
+
delay.insert(delay.end(), nPages - 1, delay[0]);
|
|
497
503
|
}
|
|
498
504
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
// It is necessary to create the copy as otherwise, pageHeight will be ignored!
|
|
505
|
+
// Attaching metadata, need to copy the image.
|
|
502
506
|
VImage copy = image.copy();
|
|
503
507
|
|
|
504
|
-
|
|
508
|
+
// Only set page-height if we have more than one page, or this could
|
|
509
|
+
// accidentally turn into an animated image later.
|
|
510
|
+
if (nPages > 1) copy.set(VIPS_META_PAGE_HEIGHT, pageHeight);
|
|
505
511
|
if (hasDelay) copy.set("delay", delay);
|
|
506
512
|
if (loop != -1) copy.set("loop", loop);
|
|
507
513
|
|
|
508
514
|
return copy;
|
|
509
515
|
}
|
|
510
516
|
|
|
517
|
+
/*
|
|
518
|
+
Remove animation properties from image.
|
|
519
|
+
*/
|
|
520
|
+
VImage RemoveAnimationProperties(VImage image) {
|
|
521
|
+
VImage copy = image.copy();
|
|
522
|
+
copy.remove(VIPS_META_PAGE_HEIGHT);
|
|
523
|
+
copy.remove("delay");
|
|
524
|
+
copy.remove("loop");
|
|
525
|
+
return copy;
|
|
526
|
+
}
|
|
527
|
+
|
|
511
528
|
/*
|
|
512
529
|
Does this image have a non-default density?
|
|
513
530
|
*/
|
|
@@ -533,6 +550,14 @@ namespace sharp {
|
|
|
533
550
|
return copy;
|
|
534
551
|
}
|
|
535
552
|
|
|
553
|
+
/*
|
|
554
|
+
Multi-page images can have a page height. Fetch it, and sanity check it.
|
|
555
|
+
If page-height is not set, it defaults to the image height
|
|
556
|
+
*/
|
|
557
|
+
int GetPageHeight(VImage image) {
|
|
558
|
+
return vips_image_get_page_height(image.get_image());
|
|
559
|
+
}
|
|
560
|
+
|
|
536
561
|
/*
|
|
537
562
|
Check the proposed format supports the current dimensions.
|
|
538
563
|
*/
|
|
@@ -589,6 +614,33 @@ namespace sharp {
|
|
|
589
614
|
return warning;
|
|
590
615
|
}
|
|
591
616
|
|
|
617
|
+
/*
|
|
618
|
+
Attach an event listener for progress updates, used to detect timeout
|
|
619
|
+
*/
|
|
620
|
+
void SetTimeout(VImage image, int const seconds) {
|
|
621
|
+
if (seconds > 0) {
|
|
622
|
+
VipsImage *im = image.get_image();
|
|
623
|
+
if (im->progress_signal == NULL) {
|
|
624
|
+
int *timeout = VIPS_NEW(im, int);
|
|
625
|
+
*timeout = seconds;
|
|
626
|
+
g_signal_connect(im, "eval", G_CALLBACK(VipsProgressCallBack), timeout);
|
|
627
|
+
vips_image_set_progress(im, TRUE);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/*
|
|
633
|
+
Event listener for progress updates, used to detect timeout
|
|
634
|
+
*/
|
|
635
|
+
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
|
636
|
+
// printf("VipsProgressCallBack progress=%d run=%d timeout=%d\n", progress->percent, progress->run, *timeout);
|
|
637
|
+
if (*timeout > 0 && progress->run >= *timeout) {
|
|
638
|
+
vips_image_set_kill(im, TRUE);
|
|
639
|
+
vips_error("timeout", "%d%% complete", progress->percent);
|
|
640
|
+
*timeout = 0;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
592
644
|
/*
|
|
593
645
|
Calculate the (left, top) coordinates of the output image
|
|
594
646
|
within the input image, applying the given gravity during an embed.
|
|
@@ -757,23 +809,27 @@ namespace sharp {
|
|
|
757
809
|
/*
|
|
758
810
|
Convert RGBA value to another colourspace
|
|
759
811
|
*/
|
|
760
|
-
std::vector<double> GetRgbaAsColourspace(std::vector<double> const rgba,
|
|
812
|
+
std::vector<double> GetRgbaAsColourspace(std::vector<double> const rgba,
|
|
813
|
+
VipsInterpretation const interpretation, bool premultiply) {
|
|
761
814
|
int const bands = static_cast<int>(rgba.size());
|
|
762
|
-
if (bands < 3
|
|
815
|
+
if (bands < 3) {
|
|
763
816
|
return rgba;
|
|
764
|
-
} else {
|
|
765
|
-
VImage pixel = VImage::new_matrix(1, 1);
|
|
766
|
-
pixel.set("bands", bands);
|
|
767
|
-
pixel = pixel.new_from_image(rgba);
|
|
768
|
-
pixel = pixel.colourspace(interpretation, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB));
|
|
769
|
-
return pixel(0, 0);
|
|
770
817
|
}
|
|
818
|
+
VImage pixel = VImage::new_matrix(1, 1);
|
|
819
|
+
pixel.set("bands", bands);
|
|
820
|
+
pixel = pixel
|
|
821
|
+
.new_from_image(rgba)
|
|
822
|
+
.colourspace(interpretation, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB));
|
|
823
|
+
if (premultiply) {
|
|
824
|
+
pixel = pixel.premultiply();
|
|
825
|
+
}
|
|
826
|
+
return pixel(0, 0);
|
|
771
827
|
}
|
|
772
828
|
|
|
773
829
|
/*
|
|
774
830
|
Apply the alpha channel to a given colour
|
|
775
831
|
*/
|
|
776
|
-
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour) {
|
|
832
|
+
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour, bool premultiply) {
|
|
777
833
|
// Scale up 8-bit values to match 16-bit input image
|
|
778
834
|
double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
779
835
|
// Create alphaColour colour
|
|
@@ -797,7 +853,7 @@ namespace sharp {
|
|
|
797
853
|
alphaColour.push_back(colour[3] * multiplier);
|
|
798
854
|
}
|
|
799
855
|
// Ensure alphaColour colour uses correct colourspace
|
|
800
|
-
alphaColour = sharp::GetRgbaAsColourspace(alphaColour, image.interpretation());
|
|
856
|
+
alphaColour = sharp::GetRgbaAsColourspace(alphaColour, image.interpretation(), premultiply);
|
|
801
857
|
// Add non-transparent alpha channel, if required
|
|
802
858
|
if (colour[3] < 255.0 && !HasAlpha(image)) {
|
|
803
859
|
image = image.bandjoin(
|
|
@@ -827,4 +883,75 @@ namespace sharp {
|
|
|
827
883
|
}
|
|
828
884
|
return image;
|
|
829
885
|
}
|
|
886
|
+
|
|
887
|
+
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
888
|
+
Canvas canvas, bool swap, bool withoutEnlargement) {
|
|
889
|
+
if (swap) {
|
|
890
|
+
// Swap input width and height when requested.
|
|
891
|
+
std::swap(width, height);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
double hshrink = 1.0;
|
|
895
|
+
double vshrink = 1.0;
|
|
896
|
+
|
|
897
|
+
if (targetWidth > 0 && targetHeight > 0) {
|
|
898
|
+
// Fixed width and height
|
|
899
|
+
hshrink = static_cast<double>(width) / targetWidth;
|
|
900
|
+
vshrink = static_cast<double>(height) / targetHeight;
|
|
901
|
+
|
|
902
|
+
switch (canvas) {
|
|
903
|
+
case Canvas::CROP:
|
|
904
|
+
case Canvas::MIN:
|
|
905
|
+
if (hshrink < vshrink) {
|
|
906
|
+
vshrink = hshrink;
|
|
907
|
+
} else {
|
|
908
|
+
hshrink = vshrink;
|
|
909
|
+
}
|
|
910
|
+
break;
|
|
911
|
+
case Canvas::EMBED:
|
|
912
|
+
case Canvas::MAX:
|
|
913
|
+
if (hshrink > vshrink) {
|
|
914
|
+
vshrink = hshrink;
|
|
915
|
+
} else {
|
|
916
|
+
hshrink = vshrink;
|
|
917
|
+
}
|
|
918
|
+
break;
|
|
919
|
+
case Canvas::IGNORE_ASPECT:
|
|
920
|
+
if (swap) {
|
|
921
|
+
std::swap(hshrink, vshrink);
|
|
922
|
+
}
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
} else if (targetWidth > 0) {
|
|
926
|
+
// Fixed width
|
|
927
|
+
hshrink = static_cast<double>(width) / targetWidth;
|
|
928
|
+
|
|
929
|
+
if (canvas != Canvas::IGNORE_ASPECT) {
|
|
930
|
+
// Auto height
|
|
931
|
+
vshrink = hshrink;
|
|
932
|
+
}
|
|
933
|
+
} else if (targetHeight > 0) {
|
|
934
|
+
// Fixed height
|
|
935
|
+
vshrink = static_cast<double>(height) / targetHeight;
|
|
936
|
+
|
|
937
|
+
if (canvas != Canvas::IGNORE_ASPECT) {
|
|
938
|
+
// Auto width
|
|
939
|
+
hshrink = vshrink;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// We should not enlarge (oversample) the output image,
|
|
944
|
+
// if withoutEnlargement is specified.
|
|
945
|
+
if (withoutEnlargement) {
|
|
946
|
+
hshrink = std::max(1.0, hshrink);
|
|
947
|
+
vshrink = std::max(1.0, vshrink);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// We don't want to shrink so much that we send an axis to 0
|
|
951
|
+
hshrink = std::min(hshrink, static_cast<double>(width));
|
|
952
|
+
vshrink = std::min(vshrink, static_cast<double>(height));
|
|
953
|
+
|
|
954
|
+
return std::make_pair(hshrink, vshrink);
|
|
955
|
+
}
|
|
956
|
+
|
|
830
957
|
} // namespace sharp
|
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 < 12) || \
|
|
29
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 12 && VIPS_MICRO_VERSION < 2)
|
|
30
|
+
#error "libvips version 8.12.2+ 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)))
|
|
@@ -50,6 +50,7 @@ namespace sharp {
|
|
|
50
50
|
char *buffer;
|
|
51
51
|
bool failOnError;
|
|
52
52
|
int limitInputPixels;
|
|
53
|
+
bool unlimited;
|
|
53
54
|
VipsAccess access;
|
|
54
55
|
size_t bufferLength;
|
|
55
56
|
bool isBuffer;
|
|
@@ -75,6 +76,7 @@ namespace sharp {
|
|
|
75
76
|
buffer(nullptr),
|
|
76
77
|
failOnError(TRUE),
|
|
77
78
|
limitInputPixels(0x3FFF * 0x3FFF),
|
|
79
|
+
unlimited(FALSE),
|
|
78
80
|
access(VIPS_ACCESS_RANDOM),
|
|
79
81
|
bufferLength(0),
|
|
80
82
|
isBuffer(FALSE),
|
|
@@ -116,6 +118,7 @@ namespace sharp {
|
|
|
116
118
|
JPEG,
|
|
117
119
|
PNG,
|
|
118
120
|
WEBP,
|
|
121
|
+
JP2,
|
|
119
122
|
TIFF,
|
|
120
123
|
GIF,
|
|
121
124
|
SVG,
|
|
@@ -132,6 +135,14 @@ namespace sharp {
|
|
|
132
135
|
MISSING
|
|
133
136
|
};
|
|
134
137
|
|
|
138
|
+
enum class Canvas {
|
|
139
|
+
CROP,
|
|
140
|
+
EMBED,
|
|
141
|
+
MAX,
|
|
142
|
+
MIN,
|
|
143
|
+
IGNORE_ASPECT
|
|
144
|
+
};
|
|
145
|
+
|
|
135
146
|
// How many tasks are in the queue?
|
|
136
147
|
extern volatile int counterQueue;
|
|
137
148
|
|
|
@@ -142,6 +153,7 @@ namespace sharp {
|
|
|
142
153
|
bool IsJpeg(std::string const &str);
|
|
143
154
|
bool IsPng(std::string const &str);
|
|
144
155
|
bool IsWebp(std::string const &str);
|
|
156
|
+
bool IsJp2(std::string const &str);
|
|
145
157
|
bool IsGif(std::string const &str);
|
|
146
158
|
bool IsTiff(std::string const &str);
|
|
147
159
|
bool IsHeic(std::string const &str);
|
|
@@ -204,9 +216,13 @@ namespace sharp {
|
|
|
204
216
|
|
|
205
217
|
/*
|
|
206
218
|
Set animation properties if necessary.
|
|
207
|
-
Non-provided properties will be loaded from image.
|
|
208
219
|
*/
|
|
209
|
-
VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop);
|
|
220
|
+
VImage SetAnimationProperties(VImage image, int nPages, int pageHeight, std::vector<int> delay, int loop);
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
Remove animation properties from image.
|
|
224
|
+
*/
|
|
225
|
+
VImage RemoveAnimationProperties(VImage image);
|
|
210
226
|
|
|
211
227
|
/*
|
|
212
228
|
Does this image have a non-default density?
|
|
@@ -223,6 +239,12 @@ namespace sharp {
|
|
|
223
239
|
*/
|
|
224
240
|
VImage SetDensity(VImage image, const double density);
|
|
225
241
|
|
|
242
|
+
/*
|
|
243
|
+
Multi-page images can have a page height. Fetch it, and sanity check it.
|
|
244
|
+
If page-height is not set, it defaults to the image height
|
|
245
|
+
*/
|
|
246
|
+
int GetPageHeight(VImage image);
|
|
247
|
+
|
|
226
248
|
/*
|
|
227
249
|
Check the proposed format supports the current dimensions.
|
|
228
250
|
*/
|
|
@@ -243,6 +265,16 @@ namespace sharp {
|
|
|
243
265
|
*/
|
|
244
266
|
std::string VipsWarningPop();
|
|
245
267
|
|
|
268
|
+
/*
|
|
269
|
+
Attach an event listener for progress updates, used to detect timeout
|
|
270
|
+
*/
|
|
271
|
+
void SetTimeout(VImage image, int const timeoutSeconds);
|
|
272
|
+
|
|
273
|
+
/*
|
|
274
|
+
Event listener for progress updates, used to detect timeout
|
|
275
|
+
*/
|
|
276
|
+
void VipsProgressCallBack(VipsImage *image, VipsProgress *progress, int *timeoutSeconds);
|
|
277
|
+
|
|
246
278
|
/*
|
|
247
279
|
Calculate the (left, top) coordinates of the output image
|
|
248
280
|
within the input image, applying the given gravity during an embed.
|
|
@@ -288,12 +320,13 @@ namespace sharp {
|
|
|
288
320
|
/*
|
|
289
321
|
Convert RGBA value to another colourspace
|
|
290
322
|
*/
|
|
291
|
-
std::vector<double> GetRgbaAsColourspace(std::vector<double> const rgba,
|
|
323
|
+
std::vector<double> GetRgbaAsColourspace(std::vector<double> const rgba,
|
|
324
|
+
VipsInterpretation const interpretation, bool premultiply);
|
|
292
325
|
|
|
293
326
|
/*
|
|
294
327
|
Apply the alpha channel to a given colour
|
|
295
328
|
*/
|
|
296
|
-
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour);
|
|
329
|
+
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour, bool premultiply);
|
|
297
330
|
|
|
298
331
|
/*
|
|
299
332
|
Removes alpha channel, if any.
|
|
@@ -305,6 +338,15 @@ namespace sharp {
|
|
|
305
338
|
*/
|
|
306
339
|
VImage EnsureAlpha(VImage image, double const value);
|
|
307
340
|
|
|
341
|
+
/*
|
|
342
|
+
Calculate the shrink factor, taking into account auto-rotate, the canvas
|
|
343
|
+
mode, and so on. The hshrink/vshrink are the amount to shrink the input
|
|
344
|
+
image axes by in order for the output axes (ie. after rotation) to match
|
|
345
|
+
the required thumbnail width/height and canvas mode.
|
|
346
|
+
*/
|
|
347
|
+
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
348
|
+
Canvas canvas, bool swap, bool withoutEnlargement);
|
|
349
|
+
|
|
308
350
|
} // namespace sharp
|
|
309
351
|
|
|
310
352
|
#endif // SRC_COMMON_H_
|