Support info.size on wide-char systems via upgrade to C++17 #3943

This commit is contained in:
Lovell Fuller 2024-11-04 18:16:29 +00:00
parent 7bdf419eb1
commit 06b08bf10f
8 changed files with 43 additions and 48 deletions

View File

@ -10,6 +10,9 @@ Requires libvips v8.16.0
* Expose WebP `smartDeblock` output option. * Expose WebP `smartDeblock` output option.
* Support `info.size` on wide-character systems via upgrade to C++17.
[#3943](https://github.com/lovell/sharp/issues/3943)
* Ensure `background` metadata can be parsed by `color` package. * Ensure `background` metadata can be parsed by `color` package.
[#4090](https://github.com/lovell/sharp/issues/4090) [#4090](https://github.com/lovell/sharp/issues/4090)

View File

@ -38,7 +38,7 @@ Ready-compiled sharp and libvips binaries are provided for use on the most commo
* macOS x64 (>= 10.15) * macOS x64 (>= 10.15)
* macOS ARM64 * macOS ARM64
* Linux ARM (glibc >= 2.28) * Linux ARM (glibc >= 2.31)
* Linux ARM64 (glibc >= 2.26, musl >= 1.2.2) * Linux ARM64 (glibc >= 2.26, musl >= 1.2.2)
* Linux ppc64 (glibc >= 2.31) * Linux ppc64 (glibc >= 2.31)
* Linux s390x (glibc >= 2.31) * Linux s390x (glibc >= 2.31)
@ -111,7 +111,7 @@ environment variables.
Building from source requires: Building from source requires:
* C++11 compiler * C++17 compiler
* [node-addon-api](https://www.npmjs.com/package/node-addon-api) version 7+ * [node-addon-api](https://www.npmjs.com/package/node-addon-api) version 7+
* [node-gyp](https://github.com/nodejs/node-gyp#installation) version 9+ and its dependencies * [node-gyp](https://github.com/nodejs/node-gyp#installation) version 9+ and its dependencies

View File

@ -15,7 +15,7 @@
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": { "optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.1.0-rc3" "@img/sharp-libvips-linux-arm": "1.1.0-rc3.1"
}, },
"files": [ "files": [
"lib" "lib"
@ -32,7 +32,7 @@
"node": "^18.17.0 || ^20.3.0 || >=21.0.0" "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
}, },
"config": { "config": {
"glibc": ">=2.28" "glibc": ">=2.31"
}, },
"os": [ "os": [
"linux" "linux"

View File

@ -146,7 +146,7 @@
"@img/sharp-darwin-x64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5",
"@img/sharp-libvips-darwin-arm64": "1.1.0-rc3", "@img/sharp-libvips-darwin-arm64": "1.1.0-rc3",
"@img/sharp-libvips-darwin-x64": "1.1.0-rc3", "@img/sharp-libvips-darwin-x64": "1.1.0-rc3",
"@img/sharp-libvips-linux-arm": "1.1.0-rc3", "@img/sharp-libvips-linux-arm": "1.1.0-rc3.1",
"@img/sharp-libvips-linux-arm64": "1.1.0-rc3", "@img/sharp-libvips-linux-arm64": "1.1.0-rc3",
"@img/sharp-libvips-linux-ppc64": "1.1.0-rc3", "@img/sharp-libvips-linux-ppc64": "1.1.0-rc3",
"@img/sharp-libvips-linux-s390x": "1.1.0-rc3", "@img/sharp-libvips-linux-s390x": "1.1.0-rc3",
@ -178,7 +178,7 @@
"jsdoc-to-markdown": "^9.0.5", "jsdoc-to-markdown": "^9.0.5",
"license-checker": "^25.0.1", "license-checker": "^25.0.1",
"mocha": "^10.8.2", "mocha": "^10.8.2",
"node-addon-api": "8.1.0", "node-addon-api": "^8.2.1",
"nyc": "^17.1.0", "nyc": "^17.1.0",
"prebuild": "^13.0.1", "prebuild": "^13.0.1",
"semistandard": "^17.0.0", "semistandard": "^17.0.0",

View File

@ -45,6 +45,9 @@
'Release': { 'Release': {
'msvs_settings': { 'msvs_settings': {
'VCCLCompilerTool': { 'VCCLCompilerTool': {
"AdditionalOptions": [
"/std:c++17"
],
'ExceptionHandling': 1, 'ExceptionHandling': 1,
'Optimization': 1, 'Optimization': 1,
'WholeProgramOptimization': 'true' 'WholeProgramOptimization': 'true'
@ -172,6 +175,7 @@
'-l:libvips-cpp.so.<(vips_version)' '-l:libvips-cpp.so.<(vips_version)'
], ],
'ldflags': [ 'ldflags': [
'-lstdc++fs',
'-Wl,-s', '-Wl,-s',
'-Wl,--disable-new-dtags', '-Wl,--disable-new-dtags',
'-Wl,-z,nodelete', '-Wl,-z,nodelete',
@ -207,13 +211,13 @@
}] }]
], ],
'cflags_cc': [ 'cflags_cc': [
'-std=c++0x', '-std=c++17',
'-fexceptions', '-fexceptions',
'-Wall', '-Wall',
'-Os' '-Os'
], ],
'xcode_settings': { 'xcode_settings': {
'CLANG_CXX_LANGUAGE_STANDARD': 'c++11', 'CLANG_CXX_LANGUAGE_STANDARD': 'c++17',
'MACOSX_DEPLOYMENT_TARGET': '10.15', 'MACOSX_DEPLOYMENT_TARGET': '10.15',
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'GCC_ENABLE_CPP_RTTI': 'YES', 'GCC_ENABLE_CPP_RTTI': 'YES',
@ -234,6 +238,9 @@
['OS == "win"', { ['OS == "win"', {
'msvs_settings': { 'msvs_settings': {
'VCCLCompilerTool': { 'VCCLCompilerTool': {
"AdditionalOptions": [
"/std:c++17"
],
'ExceptionHandling': 1, 'ExceptionHandling': 1,
'Optimization': 1, 'Optimization': 1,
'WholeProgramOptimization': 'true' 'WholeProgramOptimization': 'true'

View File

@ -20,13 +20,9 @@
#error "libvips version 8.16.0+ is required - please see https://sharp.pixelplumbing.com/install" #error "libvips version 8.16.0+ is required - please see https://sharp.pixelplumbing.com/install"
#endif #endif
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6))) #if defined(__has_include)
#error "GCC version 4.6+ is required for C++11 features - please see https://sharp.pixelplumbing.com/install" #if !__has_include(<filesystem>)
#endif #error "C++17 compiler required - please see https://sharp.pixelplumbing.com/install"
#if (defined(__clang__) && defined(__has_feature))
#if (!__has_feature(cxx_range_for))
#error "clang version 3.0+ is required for C++11 features - please see https://sharp.pixelplumbing.com/install"
#endif #endif
#endif #endif

View File

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <filesystem>
#include <map> #include <map>
#include <memory> #include <memory>
#include <numeric> #include <numeric>
@ -20,17 +21,6 @@
#include "operations.h" #include "operations.h"
#include "pipeline.h" #include "pipeline.h"
#ifdef _WIN32
#define STAT64_STRUCT __stat64
#define STAT64_FUNCTION _stat64
#elif defined(_LARGEFILE64_SOURCE)
#define STAT64_STRUCT stat64
#define STAT64_FUNCTION stat64
#else
#define STAT64_STRUCT stat
#define STAT64_FUNCTION stat
#endif
class PipelineWorker : public Napi::AsyncWorker { class PipelineWorker : public Napi::AsyncWorker {
public: public:
PipelineWorker(Napi::Function callback, PipelineBaton *baton, PipelineWorker(Napi::Function callback, PipelineBaton *baton,
@ -1306,9 +1296,11 @@ class PipelineWorker : public Napi::AsyncWorker {
Callback().Call(Receiver().Value(), { env.Null(), data, info }); Callback().Call(Receiver().Value(), { env.Null(), data, info });
} else { } else {
// Add file size to info // Add file size to info
struct STAT64_STRUCT st; if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) { try {
info.Set("size", static_cast<uint32_t>(st.st_size)); uint32_t const size = static_cast<uint32_t>(std::filesystem::file_size(baton->fileOut));
info.Set("size", size);
} catch (...) {}
} }
Callback().Call(Receiver().Value(), { env.Null(), info }); Callback().Call(Receiver().Value(), { env.Null(), info });
} }

View File

@ -483,7 +483,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
fs.stat(path.join(directory, 'ImageProperties.xml'), function (err, stat) { fs.stat(path.join(directory, 'ImageProperties.xml'), function (err, stat) {
if (err) throw err; if (err) throw err;
assert.strictEqual(true, stat.isFile()); assert.strictEqual(true, stat.isFile());
@ -509,7 +509,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertZoomifyTiles(directory, 256, 1, done); assertZoomifyTiles(directory, 256, 1, done);
}); });
}); });
@ -530,7 +530,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertZoomifyTiles(directory, 256, 5, done); assertZoomifyTiles(directory, 256, 5, done);
}); });
}); });
@ -551,7 +551,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertZoomifyTiles(directory, 256, 13, done); assertZoomifyTiles(directory, 256, 13, done);
}); });
}); });
@ -575,7 +575,7 @@ describe('Tile', function () {
assert.strictEqual(2048, info.width); assert.strictEqual(2048, info.width);
assert.strictEqual(1536, info.height); assert.strictEqual(1536, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertZoomifyTiles(directory, 256, 4, done); assertZoomifyTiles(directory, 256, 4, done);
}); });
}); });
@ -594,7 +594,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
fs.stat(path.join(directory, '0', '0', '0.jpg'), function (err, stat) { fs.stat(path.join(directory, '0', '0', '0.jpg'), function (err, stat) {
if (err) throw err; if (err) throw err;
assert.strictEqual(true, stat.isFile()); assert.strictEqual(true, stat.isFile());
@ -621,7 +621,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
const sample = path.join(directory, '0', '0', '0.jpg'); const sample = path.join(directory, '0', '0', '0.jpg');
sharp(sample).metadata(function (err, metadata) { sharp(sample).metadata(function (err, metadata) {
if (err) throw err; if (err) throw err;
@ -658,7 +658,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
const sample = path.join(directory, '0', '0', '0.png'); const sample = path.join(directory, '0', '0', '0.png');
sharp(sample).metadata(function (err, metadata) { sharp(sample).metadata(function (err, metadata) {
if (err) throw err; if (err) throw err;
@ -696,7 +696,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
const sample = path.join(directory, '0', '0', '0.webp'); const sample = path.join(directory, '0', '0', '0.webp');
sharp(sample).metadata(function (err, metadata) { sharp(sample).metadata(function (err, metadata) {
if (err) throw err; if (err) throw err;
@ -732,8 +732,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertGoogleTiles(directory, 256, 1, done); assertGoogleTiles(directory, 256, 1, done);
}); });
}); });
@ -754,8 +753,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertGoogleTiles(directory, 256, 5, done); assertGoogleTiles(directory, 256, 5, done);
}); });
}); });
@ -779,8 +777,7 @@ describe('Tile', function () {
assert.strictEqual(2809, info.width); assert.strictEqual(2809, info.width);
assert.strictEqual(2074, info.height); assert.strictEqual(2074, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
assertGoogleTiles(directory, 256, 5, done); assertGoogleTiles(directory, 256, 5, done);
}); });
}); });
@ -800,7 +797,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done); fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done);
}); });
}); });
@ -820,7 +817,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done); fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done);
}); });
}); });
@ -842,7 +839,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
const infoJson = require(path.join(directory, 'info.json')); const infoJson = require(path.join(directory, 'info.json'));
assert.strictEqual('http://iiif.io/api/image/2/context.json', infoJson['@context']); assert.strictEqual('http://iiif.io/api/image/2/context.json', infoJson['@context']);
assert.strictEqual(`${id}/${name}`, infoJson['@id']); assert.strictEqual(`${id}/${name}`, infoJson['@id']);
@ -872,7 +869,7 @@ describe('Tile', function () {
assert.strictEqual(2725, info.width); assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height); assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels); assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size); assert.strictEqual(undefined, info.size);
const infoJson = require(path.join(directory, 'info.json')); const infoJson = require(path.join(directory, 'info.json'));
assert.strictEqual('http://iiif.io/api/image/3/context.json', infoJson['@context']); assert.strictEqual('http://iiif.io/api/image/3/context.json', infoJson['@context']);
assert.strictEqual('ImageService3', infoJson.type); assert.strictEqual('ImageService3', infoJson.type);