diff --git a/binding.gyp b/binding.gyp index a2a400ed..fbd03fa5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -15,10 +15,11 @@ '_ALLOW_KEYWORD_MACROS' ], 'sources': [ - 'src/libvips/cplusplus/VError.cpp', 'src/libvips/cplusplus/VConnection.cpp', + 'src/libvips/cplusplus/VError.cpp', + 'src/libvips/cplusplus/VImage.cpp', 'src/libvips/cplusplus/VInterpolate.cpp', - 'src/libvips/cplusplus/VImage.cpp' + 'src/libvips/cplusplus/VRegion.cpp' ], 'include_dirs': [ '<(sharp_vendor_dir)/include', diff --git a/package.json b/package.json index 2ec4deba..8d592236 100644 --- a/package.json +++ b/package.json @@ -140,9 +140,9 @@ "devDependencies": { "async": "^3.2.4", "cc": "^3.0.1", - "decompress-zip": "^0.3.3", "documentation": "^13.2.5", "exif-reader": "^1.0.3", + "extract-zip": "^2.0.1", "icc": "^2.0.0", "license-checker": "^25.0.1", "mocha": "^10.0.0", @@ -154,19 +154,19 @@ }, "license": "Apache-2.0", "config": { - "libvips": "8.12.2", + "libvips": "8.13.0-rc1", "integrity": { - "darwin-arm64v8": "sha512-p46s/bbJAjkOXzPISZt9HUpG9GWjwQkYnLLRLKzsBJHLtB3X6C6Y/zXI5Hd0DOojcFkks9a0kTN+uDQ/XJY19g==", - "darwin-x64": "sha512-6vOHVZnvXwe6EXRsy29jdkUzBE6ElNpXUwd+m8vV7qy32AnXu7B9YemHsZ44vWviIwPZeXF6Nhd9EFLM0wWohw==", - "linux-arm64v8": "sha512-XwZdS63yhqLtbFtx/0eoLF/Agf5qtTrI11FMnMRpuBJWd4jHB60RAH+uzYUgoChCmKIS+AeXYMLm4d8Ns2QX8w==", - "linux-armv6": "sha512-Rh0Q0kqwPG2MjXWOkPCuPEyiUKFgKJYWLgS835D4MrXgdKr8Tft/eVrc2iGIxt2re30VpDiZ1h0Rby1aCZt2zw==", - "linux-armv7": "sha512-heTS/MsmRvu4JljINxP+vDiS9ZZfuGhr3IStb5F7Gc0/QLRhllYAg4rcO8L1eTK9sIIzG5ARvI19+YUZe7WbzA==", - "linux-x64": "sha512-SSWAwBFi0hx8V/h/v82tTFGKWTFv9FiCK3Timz5OExuI+sX1Ngrd0PVQaWXOThGNdel/fcD3Bz9YjSt4feBR1g==", - "linuxmusl-arm64v8": "sha512-Rhks+5C7p7aO6AucLT1uvzo8ohlqcqCUPgZmN+LZjsPWob/Iix3MfiDYtv/+gTvdeEfXxbCU6/YuPBwHQ7/crA==", - "linuxmusl-x64": "sha512-IOyjSQqpWVntqOUpCHVWuQwACwmmjdi15H8Pc+Ma1JkhPogTfVsFQWyL7DuOTD3Yr23EuYGzovUX00duOtfy/g==", - "win32-arm64v8": "sha512-A+Qe8Ipewtvw9ldvF6nWed2J8kphzrUE04nFeKCtNx6pfGQ/MAlCKMjt/U8VgUKNjB01zJDUW9XE0+FhGZ/UpQ==", - "win32-ia32": "sha512-cMrAvwFdDeAVnLJt0IPMPRKaIFhyXYGTprsM0DND9VUHE8F7dJMR44tS5YkXsGh1QNDtjKT6YuxAVUglmiXtpA==", - "win32-x64": "sha512-vLFIfw6aW2zABa8jpgzWDhljnE6glktrddErVyazAIoHl6BFFe/Da+LK1DbXvIYHz7fyOoKhSfCJHCiJG1Vg6w==" + "darwin-arm64v8": "sha512-tczrNbjU/+bUhTHilUNd2OL9DgwPvUX3L6LUTQHmLZlatxT5ztj6of1erNXYhgt4lLhruKcKkYYQyRicBoKsRA==", + "darwin-x64": "sha512-eonsBwyPEHxFL++bCG+rEUokSOaCbImSJ5VA//Qkv34QAO+vZWzj9RMf/ETvT3pHzrx56Wm3SwpGgJ/BIeyKgg==", + "linux-arm64v8": "sha512-/hLYMwmWG3wKyUeDvNZCMJL3mZ+/8mj+VfVbo2DsNsI6MxBnZ4aXg3qMJ17FcEa2sPDHhkVqaJl5DnXGn87gGQ==", + "linux-armv6": "sha512-25Ml2+J+KWj7yKnZVcrxZmZHFIwzbW6d/kACT7duz48NmGWDD0jnu/nroAETYiMqS1W5fHlPRiwG82/d/PeIpg==", + "linux-armv7": "sha512-7u6RS3IFptQMGRMujyvz1kh8YFPBRdEu9T1zJKYl0/cZkxeNNiljW4PenOQ6cxoPlXivUDpEOoifo4B6a3B4/A==", + "linux-x64": "sha512-v6/vcp+71p4NtoEpWUghgboVzavwX8FVa1NXBDVYMx/up4AmQEjEzOicSiLxXc97Ydhk6FJz8Qkrfp05AN0SfQ==", + "linuxmusl-arm64v8": "sha512-8DNTwBbAna/R0/ksmaO/2TKZxjdkgSppTjmM9xIAZO7tbknuDCqi0YyJiiCP5Nh5yGtpf+PcQdSu/ca21ICwAQ==", + "linuxmusl-x64": "sha512-3B12ehfury7m39sZ1lyTxzcf3hPAcCC/+4l16C0Mkoc6FGKPV/CJFtoCzNjUEsEJR5rMKOFBfsgZOoNk0KEzSQ==", + "win32-arm64v8": "sha512-45gnLXiq4EtJNnhhgSY8Kgr5L0ed637Kn2SCW7jhQu9qZS3riLSM5Kk+6L1Kqc+cyNnsFbtWWBWCZp01Tg9HSw==", + "win32-ia32": "sha512-LEodsYlTo0gkrfpHFNr9IwSMI7MTBBy/vry0MazcUAIPkiPhx3CCNbPZL7pd7vuHZ4CP5XNsArTb0RaHpMrc+w==", + "win32-x64": "sha512-5usGDnN1pmFoqfEuHmdvKF/35NbQLlnal5T2bMWDx9kvLIOy7WSahvSGAeDg9cXjHv9SONX/qdpKuJ55c6aD4g==" }, "runtime": "napi", "target": 5 diff --git a/src/common.cc b/src/common.cc index 751e41d7..307549b3 100644 --- a/src/common.cc +++ b/src/common.cc @@ -366,32 +366,33 @@ namespace sharp { } } } else { - if (descriptor->createChannels > 0) { + int const channels = descriptor->createChannels; + if (channels > 0) { // Create new image if (descriptor->createNoiseType == "gaussian") { - int const channels = descriptor->createChannels; - image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight); std::vector bands = {}; bands.reserve(channels); for (int _band = 0; _band < channels; _band++) { - bands.push_back(image.gaussnoise( - descriptor->createWidth, - descriptor->createHeight, - VImage::option()->set("mean", descriptor->createNoiseMean)->set("sigma", descriptor->createNoiseSigma))); + bands.push_back(VImage::gaussnoise(descriptor->createWidth, descriptor->createHeight, VImage::option() + ->set("mean", descriptor->createNoiseMean) + ->set("sigma", descriptor->createNoiseSigma))); } - image = image.bandjoin(bands); + image = VImage::bandjoin(bands).copy(VImage::option()->set("interpretation", + channels < 3 ? VIPS_INTERPRETATION_B_W: VIPS_INTERPRETATION_sRGB)); } else { std::vector background = { descriptor->createBackground[0], descriptor->createBackground[1], descriptor->createBackground[2] }; - if (descriptor->createChannels == 4) { + if (channels == 4) { background.push_back(descriptor->createBackground[3]); } - image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight).new_from_image(background); + image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight) + .copy(VImage::option()->set("interpretation", + channels < 3 ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_sRGB)) + .new_from_image(background); } - image.get_image()->Type = image.guess_interpretation(); image = image.cast(VIPS_FORMAT_UCHAR); imageType = ImageType::RAW; } else { diff --git a/src/libvips/cplusplus/VConnection.cpp b/src/libvips/cplusplus/VConnection.cpp index adea2e17..55451415 100644 --- a/src/libvips/cplusplus/VConnection.cpp +++ b/src/libvips/cplusplus/VConnection.cpp @@ -31,7 +31,6 @@ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ -#include #include diff --git a/src/libvips/cplusplus/VError.cpp b/src/libvips/cplusplus/VError.cpp index a3d82188..3be49068 100644 --- a/src/libvips/cplusplus/VError.cpp +++ b/src/libvips/cplusplus/VError.cpp @@ -30,7 +30,6 @@ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ -#include #include diff --git a/src/libvips/cplusplus/VImage.cpp b/src/libvips/cplusplus/VImage.cpp index 5a08d80f..72c3fa9d 100644 --- a/src/libvips/cplusplus/VImage.cpp +++ b/src/libvips/cplusplus/VImage.cpp @@ -38,7 +38,6 @@ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ -#include #include @@ -733,7 +732,7 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size, set( "in", *this )-> set( "target", target ) ); - g_object_get( target.get_target(), "blob", &blob, NULL ); + g_object_get( target.get_target(), "blob", &blob, (void *) NULL ); } else if( (operation_name = vips_foreign_find_save_buffer( filename )) ) { call_option_string( operation_name, option_string, @@ -778,6 +777,32 @@ VImage::write_to_target( const char *suffix, VTarget target, set( "target", target ) ); } +VRegion +VImage::region() const +{ + return VRegion::new_from_image( *this ); +} + +VRegion +VImage::region( VipsRect *rect ) const +{ + VRegion region = VRegion::new_from_image( *this ); + + region.prepare( rect ); + + return region; +} + +VRegion +VImage::region( int left, int top, int width, int height ) const +{ + VRegion region = VRegion::new_from_image( *this ); + + region.prepare( left, top, width, height ); + + return region; +} + #include "vips-operators.cpp" std::vector diff --git a/src/libvips/cplusplus/VInterpolate.cpp b/src/libvips/cplusplus/VInterpolate.cpp index 303a9b8b..ed1e2bd9 100644 --- a/src/libvips/cplusplus/VInterpolate.cpp +++ b/src/libvips/cplusplus/VInterpolate.cpp @@ -31,7 +31,6 @@ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ -#include #include diff --git a/src/libvips/cplusplus/VRegion.cpp b/src/libvips/cplusplus/VRegion.cpp new file mode 100644 index 00000000..4a042821 --- /dev/null +++ b/src/libvips/cplusplus/VRegion.cpp @@ -0,0 +1,27 @@ +// Object part of VRegion class + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ + +#include + +#include + +VIPS_NAMESPACE_START + +VRegion +VRegion::new_from_image( VImage image ) +{ + VipsRegion *region; + + if( !(region = vips_region_new( image.get_image() )) ) { + throw VError(); + } + + VRegion out( region ); + + return( out ); +} + +VIPS_NAMESPACE_END diff --git a/src/libvips/cplusplus/vips-operators.cpp b/src/libvips/cplusplus/vips-operators.cpp index 38b858b3..9360bd89 100644 --- a/src/libvips/cplusplus/vips-operators.cpp +++ b/src/libvips/cplusplus/vips-operators.cpp @@ -1,5 +1,4 @@ // bodies for vips operations -// Mon Nov 1 03:31:09 PM CET 2021 // this file is generated automatically, do not edit! VImage VImage::CMC2LCh( VOption *options ) const @@ -943,6 +942,14 @@ VipsBlob *VImage::dzsave_buffer( VOption *options ) const return( buffer ); } +void VImage::dzsave_target( VTarget target, VOption *options ) const +{ + call( "dzsave_target", + (options ? options : VImage::option())-> + set( "in", *this )-> + set( "target", target ) ); +} + VImage VImage::embed( int x, int y, int width, int height, VOption *options ) const { VImage out; @@ -3521,6 +3528,14 @@ VipsBlob *VImage::tiffsave_buffer( VOption *options ) const return( buffer ); } +void VImage::tiffsave_target( VTarget target, VOption *options ) const +{ + call( "tiffsave_target", + (options ? options : VImage::option())-> + set( "in", *this )-> + set( "target", target ) ); +} + VImage VImage::tilecache( VOption *options ) const { VImage out; diff --git a/src/pipeline.cc b/src/pipeline.cc index 65f994b0..23806cde 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -668,7 +668,7 @@ class PipelineWorker : public Napi::AsyncWorker { xs.push_back(left); ys.push_back(top); } - image = image.composite(images, modes, VImage::option()->set("x", xs)->set("y", ys)); + image = VImage::composite(images, modes, VImage::option()->set("x", xs)->set("y", ys)); } // Reverse premultiplication after all transformations: diff --git a/src/sharp.cc b/src/sharp.cc index f76a5cb0..53853743 100644 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -22,7 +22,6 @@ #include "stats.h" static void* sharp_vips_init(void*) { - g_setenv("VIPS_MIN_STACK_SIZE", "2m", FALSE); vips_init("sharp"); return nullptr; } diff --git a/test/fixtures/expected/embed-lab-into-rgba.png b/test/fixtures/expected/embed-lab-into-rgba.png index 23c5d9ae..6e48a721 100644 Binary files a/test/fixtures/expected/embed-lab-into-rgba.png and b/test/fixtures/expected/embed-lab-into-rgba.png differ diff --git a/test/fixtures/expected/flatten-orange.jpg b/test/fixtures/expected/flatten-orange.jpg index 18f49bb8..5f00a736 100644 Binary files a/test/fixtures/expected/flatten-orange.jpg and b/test/fixtures/expected/flatten-orange.jpg differ diff --git a/test/fixtures/expected/hilutite.jpg b/test/fixtures/expected/hilutite.jpg index 6ae6a71c..d11facb2 100644 Binary files a/test/fixtures/expected/hilutite.jpg and b/test/fixtures/expected/hilutite.jpg differ diff --git a/test/unit/alpha.js b/test/unit/alpha.js index 4b9f618f..c39c1d64 100644 --- a/test/unit/alpha.js +++ b/test/unit/alpha.js @@ -23,6 +23,7 @@ describe('Alpha transparency', function () { .flatten({ background: { r: 255, g: 102, b: 0 } }) + .jpeg({ chromaSubsampling: '4:4:4' }) .toBuffer(function (err, data, info) { if (err) throw err; assert.strictEqual(400, info.width); @@ -35,6 +36,7 @@ describe('Alpha transparency', function () { sharp(fixtures.inputPngWithTransparency) .resize(400, 300) .flatten({ background: '#ff6600' }) + .jpeg({ chromaSubsampling: '4:4:4' }) .toBuffer(function (err, data, info) { if (err) throw err; assert.strictEqual(400, info.width); diff --git a/test/unit/avif.js b/test/unit/avif.js index b2def445..1714460e 100644 --- a/test/unit/avif.js +++ b/test/unit/avif.js @@ -27,7 +27,9 @@ describe('AVIF', () => { format: 'jpeg', hasAlpha: false, hasProfile: false, - height: 14, + // 32 / (2048 / 858) = 13.40625 + // Math.round(13.40625) = 13 + height: 13, isProgressive: false, space: 'srgb', width: 32 @@ -70,7 +72,11 @@ describe('AVIF', () => { format: 'heif', hasAlpha: false, hasProfile: false, - height: 14, + // FIXME(kleisauke): https://github.com/strukturag/libheif/issues/365 + // $ vips black x.avif 32 13 + // $ vipsheader x.avif + // x.avif: 32x12 uchar, 3 bands, srgb, heifload + height: 12, isProgressive: false, pagePrimary: 0, pages: 1, diff --git a/test/unit/beforeEach.js b/test/unit/beforeEach.js index f2b82e51..932cb8d7 100644 --- a/test/unit/beforeEach.js +++ b/test/unit/beforeEach.js @@ -5,11 +5,9 @@ const sharp = require('../../'); const libcFamily = detectLibc.familySync(); const usingCache = libcFamily !== detectLibc.MUSL; -const usingSimd = !process.env.G_DEBUG; -const concurrency = - libcFamily === detectLibc.MUSL || process.arch === 'arm' - ? 1 - : undefined; +const usingSimd = !(process.env.G_DEBUG || process.env.VIPS_NOVECTOR); +const concurrency = process.env.VIPS_CONCURRENCY || + (libcFamily === detectLibc.MUSL || process.arch === 'arm' ? 1 : undefined); beforeEach(function () { sharp.cache(usingCache); diff --git a/test/unit/metadata.js b/test/unit/metadata.js index 30ee777c..df5f1d61 100644 --- a/test/unit/metadata.js +++ b/test/unit/metadata.js @@ -343,7 +343,7 @@ describe('Image metadata', function () { assert.strictEqual(depth, 'uchar'); assert.strictEqual(isProgressive, false); assert.strictEqual(pages, 10); - assert.strictEqual(loop, 2); + assert.strictEqual(loop, 3); assert.deepStrictEqual(delay, [...Array(9).fill(3000), 15000]); assert.strictEqual(hasProfile, false); assert.strictEqual(hasAlpha, true); diff --git a/test/unit/tile.js b/test/unit/tile.js index b5ff7da2..9b09a527 100644 --- a/test/unit/tile.js +++ b/test/unit/tile.js @@ -6,7 +6,7 @@ const assert = require('assert'); const eachLimit = require('async/eachLimit'); const rimraf = require('rimraf'); -const DecompressZip = require('decompress-zip'); +const extractZip = require('extract-zip'); const sharp = require('../../'); const fixtures = require('../fixtures'); @@ -14,7 +14,8 @@ const fixtures = require('../fixtures'); // Verifies all tiles in a given dz output directory are <= size const assertDeepZoomTiles = function (directory, expectedSize, expectedLevels, done) { // Get levels - const levels = fs.readdirSync(directory); + const dirents = fs.readdirSync(directory, { withFileTypes: true }); + const levels = dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name); assert.strictEqual(expectedLevels, levels.length); // Get tiles const tiles = []; @@ -67,8 +68,10 @@ const assertZoomifyTiles = function (directory, expectedTileSize, expectedLevels }; const assertGoogleTiles = function (directory, expectedTileSize, expectedLevels, done) { - const levels = fs.readdirSync(directory); - assert.strictEqual(expectedLevels, levels.length - 1); // subtract one to account for default blank tile + // Get levels + const dirents = fs.readdirSync(directory, { withFileTypes: true }); + const levels = dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name); + assert.strictEqual(expectedLevels, levels.length); fs.stat(path.join(directory, 'blank.png'), function (err, stat) { if (err) throw err; @@ -94,7 +97,8 @@ const assertGoogleTiles = function (directory, expectedTileSize, expectedLevels, // Verifies tiles at specified level in a given output directory are > size+overlap const assertTileOverlap = function (directory, tileSize, done) { // Get sorted levels - const levels = fs.readdirSync(directory).sort((a, b) => a - b); + const dirents = fs.readdirSync(directory, { withFileTypes: true }); + const levels = dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name).sort((a, b) => a - b); // Select the highest tile level const highestLevel = levels[levels.length - 1]; // Get sorted tiles from greatest level @@ -908,14 +912,10 @@ describe('Tile', function () { if (err) throw err; assert.strictEqual(true, stat.isFile()); assert.strictEqual(true, stat.size > 0); - new DecompressZip(container) - .on('extract', function () { + extractZip(container, { dir: path.dirname(extractTo) }) + .then(() => { assertDeepZoomTiles(directory, 256, 13, done); - }) - .on('error', function (err) { - throw err; - }) - .extract({ path: path.dirname(extractTo) }); + }); }); }); }); @@ -942,14 +942,10 @@ describe('Tile', function () { if (err) throw err; assert.strictEqual(true, stat.isFile()); assert.strictEqual(true, stat.size > 0); - new DecompressZip(container) - .on('extract', function () { + extractZip(container, { dir: path.dirname(extractTo) }) + .then(() => { assertDeepZoomTiles(directory, 256, 13, done); - }) - .on('error', function (err) { - throw err; - }) - .extract({ path: path.dirname(extractTo) }); + }); }); }); }); diff --git a/test/unit/util.js b/test/unit/util.js index 0965280a..23ba2b59 100644 --- a/test/unit/util.js +++ b/test/unit/util.js @@ -140,7 +140,6 @@ describe('Utilities', function () { assert.strictEqual('object', typeof sharp.vendor); assert.strictEqual('string', typeof sharp.vendor.current); assert.strictEqual(true, Array.isArray(sharp.vendor.installed)); - assert.strictEqual(true, sharp.vendor.installed.length > 0); }); }); });