Compare commits

...

20 Commits

Author SHA1 Message Date
Lovell Fuller
946976ba8f Prerelease 0.33.0-alpha.6 2023-10-09 10:46:16 +01:00
Lovell Fuller
29a83250a4 CI: Add smoke test for npm-published package
These tests will fail on their first run as a tag will exist but
the matching packages will not yet have been published.

The workflow can be manually re-run after publishing to npm.

Eventually, when there's some form of automated publishing, this
logic can become part of the post-publish checks.
2023-10-09 07:59:47 +01:00
Lovell Fuller
3f54ef7525 Remove extraneous rpath
The sharp.node shared library should now always end up being
nested either 3 subdirectories deep into the package root or exist
within same namespace of the node_modules tree.
2023-10-09 07:58:14 +01:00
Lovell Fuller
4dc2467f49 CI: simplify prebuild file copying 2023-10-08 23:07:02 +01:00
Lovell Fuller
f54ceb0973 CI: create prebuilds in src directory 2023-10-08 21:49:58 +01:00
Lovell Fuller
8d033ae341 Prerelease 0.33.0-alpha.5 2023-10-08 20:27:42 +01:00
Lovell Fuller
f7da2e5970 Building from source now requires node-addon-api in dependencies
If you want to build sharp from source against a globally-installed
libvips then you will now need to add both node-addon-api and
node-gyp to the dependencies section of your package.json file.

The binding.gyp file is "hidden" inside the src directory to
prevent various build and package manager tooling from assuming
that everyone is going to build from source every time.
2023-10-08 15:39:02 +01:00
Lovell Fuller
51e56f994c Package managers cannot handle nested optionalDependencies 2023-10-07 11:09:45 +01:00
Lovell Fuller
68ac12292c Prerelease 0.33.0-alpha.4 2023-10-06 15:02:19 +01:00
Lovell Fuller
a9aa7339ce Prerelease 0.33.0-alpha.3 2023-10-06 09:48:44 +01:00
Lovell Fuller
08108f5fad Use std::once for vips_init call 2023-10-06 09:44:57 +01:00
Lovell Fuller
58e3c4c70e Ensure all package files make use of commonjs explicit 2023-10-05 20:00:32 +01:00
Lovell Fuller
f8cf25ca56 Ensure correct interp of 16-bit raw input #3808 2023-10-05 14:05:36 +01:00
Lovell Fuller
ca95979ecc Prefix node builtins, skips cache lookup 2023-10-05 12:09:19 +01:00
Lovell Fuller
392f6afb5e Commit fcc7e84 but do it properly this time 2023-10-04 21:30:05 +01:00
Lovell Fuller
7c97aabaf8 Ensure win32 packages contain version/notice files 2023-10-04 21:12:16 +01:00
Lovell Fuller
fcc7e84bee Revert target names as these are used for DLLs 2023-10-04 20:46:25 +01:00
Lovell Fuller
226a9a13ef Packaging: prerelease version bump 2023-10-04 15:48:23 +01:00
Lovell Fuller
4d3c9ae3d1 Packaging: clear existing lib directories 2023-10-04 15:47:57 +01:00
Lovell Fuller
f31011d759 CI: increase linux-arm timeout 2023-10-04 15:47:35 +01:00
28 changed files with 258 additions and 123 deletions

View File

@@ -42,7 +42,7 @@ jobs:
sudo docker exec sharp sh -c "npm run clean" sudo docker exec sharp sh -c "npm run clean"
sudo docker exec sharp sh -c "npm install --ignore-scripts" sudo docker exec sharp sh -c "npm install --ignore-scripts"
sudo docker exec sharp sh -c "npm test" sudo docker exec sharp sh -c "npm test"
- run: "[[ -n $CIRCLE_TAG ]] && sudo docker exec --env prebuild_upload sharp sh -c \"npx prebuild --upload=$prebuild_upload\" || true" - run: "[[ -n $CIRCLE_TAG ]] && sudo docker exec --env prebuild_upload sharp sh -c \"cd src && ln -s ../package.json && npx prebuild --upload=$prebuild_upload\" || true"
linux-arm64-glibc-node-20: linux-arm64-glibc-node-20:
resource_class: arm.medium resource_class: arm.medium
machine: machine:
@@ -83,7 +83,7 @@ jobs:
sudo docker exec sharp sh -c "npm run clean" sudo docker exec sharp sh -c "npm run clean"
sudo docker exec sharp sh -c "npm install --ignore-scripts" sudo docker exec sharp sh -c "npm install --ignore-scripts"
sudo docker exec sharp sh -c "npm test" sudo docker exec sharp sh -c "npm test"
- run: "[[ -n $CIRCLE_TAG ]] && sudo docker exec --env prebuild_upload sharp sh -c \"npx prebuild --upload=$prebuild_upload\" || true" - run: "[[ -n $CIRCLE_TAG ]] && sudo docker exec --env prebuild_upload sharp sh -c \"cd src && ln -s ../package.json && npx prebuild --upload=$prebuild_upload\" || true"
linux-arm64-musl-node-20: linux-arm64-musl-node-20:
resource_class: arm.medium resource_class: arm.medium
machine: machine:

View File

@@ -114,7 +114,10 @@ jobs:
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/') if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
env: env:
prebuild_upload: ${{ secrets.GITHUB_TOKEN }} prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
run: npx prebuild run: |
node -e "require('fs').cpSync('package.json', 'src/package.json')"
cd src
npx prebuild
github-runner-qemu: github-runner-qemu:
permissions: permissions:
contents: write contents: write
@@ -141,8 +144,8 @@ jobs:
npm pkg set "optionalDependencies.@sharpen/sharp-linux-arm=file:./npm/linux-arm" npm pkg set "optionalDependencies.@sharpen/sharp-linux-arm=file:./npm/linux-arm"
npm run clean npm run clean
npm install --ignore-scripts npm install --ignore-scripts
npx mocha --no-config --spec=test/unit/io.js npx mocha --no-config --spec=test/unit/io.js --timeout=30000
[[ -n $prebuild_upload ]] && npx prebuild || true [[ -n $prebuild_upload ]] && cd src && ln -s ../package.json && npx prebuild || true
macstadium-runner: macstadium-runner:
permissions: permissions:
contents: write contents: write
@@ -187,4 +190,4 @@ jobs:
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/') if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
env: env:
prebuild_upload: ${{ secrets.GITHUB_TOKEN }} prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
run: npx prebuild run: cd src && ln -s ../package.json && npx prebuild

78
.github/workflows/npm.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
name: "npm release smoke test"
on:
push:
tags:
- "v**"
permissions: {}
jobs:
release-smoke-test:
name: "${{ github.ref }} ${{ matrix.name }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: linux-x64
os: ubuntu-22.04
- name: darwin-x64
os: macos-11
- name: win32-x64
os: windows-2019
steps:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: Install Bun
if: ${{ !contains(matrix.os, 'windows') }}
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Version
id: version
uses: actions/github-script@v6
with:
script: |
core.setOutput('semver', context.ref.replace('refs/tags/v',''))
- name: Create package.json
uses: DamianReeves/write-file-action@v1
with:
path: package.json
contents: |
{
"dependencies": {
"sharp": "${{ steps.version.outputs.semver }}"
}
}
- name: Create release.mjs
uses: DamianReeves/write-file-action@v1
with:
path: release.mjs
contents: |
import { createRequire } from 'node:module';
import { deepStrictEqual } from 'node:assert';
const require = createRequire(import.meta.url);
const sharp = require('sharp');
deepStrictEqual(['.jpg', '.jpeg', '.jpe'], sharp.format.jpeg.input.fileSuffix);
- name: Run with Node.js
run: |
npm install --ignore-scripts
node release.mjs
- name: Run with Deno
run: deno run --allow-read --allow-ffi release.mjs
- name: Run with Bun
if: ${{ !contains(matrix.os, 'windows') }}
run: |
bun install --ignore-scripts
bun release.mjs

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
build src/build
src/node_modules
node_modules node_modules
/coverage /coverage
npm/*/* npm/*/*

View File

@@ -8,11 +8,18 @@ Requires libvips v8.14.5
* Drop support for Node.js 14 and 16, now requires Node.js >= 18.17.0 * Drop support for Node.js 14 and 16, now requires Node.js >= 18.17.0
* Prebuilt binaries distributed via npm registry and installed via package manager.
* Building from source requires dependency on `node-addon-api`.
* Remove `sharp.vendor`. * Remove `sharp.vendor`.
* Make `compression` option of `heif` mandatory to help reduce HEIF vs HEIC confusion. * Make `compression` option of `heif` mandatory to help reduce HEIF vs HEIC confusion.
[#3740](https://github.com/lovell/sharp/issues/3740) [#3740](https://github.com/lovell/sharp/issues/3740)
* Ensure correct interpretation of 16-bit raw input.
[#3808](https://github.com/lovell/sharp/issues/3808)
## v0.32 - *flow* ## v0.32 - *flow*
Requires libvips v8.14.5 Requires libvips v8.14.5

View File

@@ -53,9 +53,15 @@ This module will be compiled from source at `npm install` time when:
Building from source requires: Building from source requires:
* C++11 compiler * C++11 compiler
* [node-addon-api](https://www.npmjs.com/package/node-addon-api)
* [node-gyp](https://github.com/nodejs/node-gyp#installation) and its dependencies * [node-gyp](https://github.com/nodejs/node-gyp#installation) and its dependencies
If `node-gyp` cannot be found, try adding it to `devDependencies`. There is an install-time check for these dependencies.
If `node-addon-api` or `node-gyp` cannot be found, try adding them via:
```sh
npm install --save node-addon-api node-gyp
```
For cross-compiling, the `--platform`, `--arch` and `--libc` npm flags For cross-compiling, the `--platform`, `--arch` and `--libc` npm flags
(or the `npm_config_platform`, `npm_config_arch` and `npm_config_libc` environment variables) (or the `npm_config_platform`, `npm_config_arch` and `npm_config_libc` environment variables)

View File

@@ -3,18 +3,27 @@
'use strict'; 'use strict';
const { useGlobalLibvips, globalLibvipsVersion, log, gypRebuild } = require('../lib/libvips'); const { useGlobalLibvips, globalLibvipsVersion, log, spawnRebuild } = require('../lib/libvips');
const buildFromSource = (msg) => { const buildFromSource = (msg) => {
log(msg); log(msg);
log('Attempting to build from source via node-gyp'); log('Attempting to build from source via node-gyp');
try { try {
require('node-gyp'); require('node-addon-api');
log('Found node-addon-api');
} catch (err) { } catch (err) {
log('You might need to install node-gyp'); log('Please add node-addon-api to your dependencies');
return;
}
try {
const gyp = require('node-gyp');
log(`Found node-gyp version ${gyp().version}`);
} catch (err) {
log('Please add node-gyp to your dependencies');
return;
} }
log('See https://sharp.pixelplumbing.com/install#building-from-source'); log('See https://sharp.pixelplumbing.com/install#building-from-source');
const status = gypRebuild(); const status = spawnRebuild();
if (status !== 0) { if (status !== 0) {
process.exit(status); process.exit(status);
} }

View File

@@ -3,8 +3,8 @@
'use strict'; 'use strict';
const util = require('util'); const util = require('node:util');
const stream = require('stream'); const stream = require('node:stream');
const is = require('./is'); const is = require('./is');
require('./sharp'); require('./sharp');

View File

@@ -3,7 +3,7 @@
'use strict'; 'use strict';
const spawnSync = require('child_process').spawnSync; const { spawnSync } = require('node:child_process');
const semverCoerce = require('semver/functions/coerce'); const semverCoerce = require('semver/functions/coerce');
const semverGreaterThanOrEqualTo = require('semver/functions/gte'); const semverGreaterThanOrEqualTo = require('semver/functions/gte');
const detectLibc = require('detect-libc'); const detectLibc = require('detect-libc');
@@ -80,8 +80,8 @@ const isRosetta = () => {
}; };
/* istanbul ignore next */ /* istanbul ignore next */
const gypRebuild = () => const spawnRebuild = () =>
spawnSync('node-gyp rebuild', { spawnSync('node-gyp rebuild --directory=src', {
...spawnSyncOptions, ...spawnSyncOptions,
stdio: 'inherit' stdio: 'inherit'
}).status; }).status;
@@ -146,7 +146,7 @@ module.exports = {
buildSharpLibvipsLibDir, buildSharpLibvipsLibDir,
runtimePlatformArch, runtimePlatformArch,
log, log,
gypRebuild, spawnRebuild,
globalLibvipsVersion, globalLibvipsVersion,
pkgConfigPath, pkgConfigPath,
useGlobalLibvips useGlobalLibvips

View File

@@ -3,7 +3,7 @@
'use strict'; 'use strict';
const path = require('path'); const path = require('node:path');
const is = require('./is'); const is = require('./is');
const sharp = require('./sharp'); const sharp = require('./sharp');

View File

@@ -9,11 +9,12 @@ const { familySync, versionSync } = require('detect-libc');
const { runtimePlatformArch, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips'); const { runtimePlatformArch, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
const runtimePlatform = runtimePlatformArch(); const runtimePlatform = runtimePlatformArch();
const [isLinux, isMacOs, isWindows] = ['linux', 'darwin', 'win32'].map(os => runtimePlatform.startsWith(os));
/* istanbul ignore next */ /* istanbul ignore next */
try { try {
// Check for local build // Check for local build
module.exports = require(`../build/Release/sharp-${runtimePlatform}.node`); module.exports = require(`../src/build/Release/sharp-${runtimePlatform}.node`);
} catch (errLocal) { } catch (errLocal) {
try { try {
// Check for runtime package // Check for runtime package
@@ -29,11 +30,15 @@ try {
help.push('Possible solutions:'); help.push('Possible solutions:');
// Common error messages // Common error messages
if (prebuiltPlatforms.includes(runtimePlatform)) { if (prebuiltPlatforms.includes(runtimePlatform)) {
help.push(`- Add an explicit dependency for the runtime platform: "npm install --force @sharpen/sharp-${runtimePlatform}"`); help.push('- Add explicit dependencies for the runtime platform:');
help.push(` npm install --force @sharpen/sharp-${runtimePlatform}`);
if (!isWindows) {
help.push(` npm install --force @sharpen/sharp-libvips-${runtimePlatform}`);
}
} else { } else {
help.push(`- The ${runtimePlatform} platform requires manual installation of libvips >= ${minimumLibvipsVersion}`); help.push(`- The ${runtimePlatform} platform requires manual installation of libvips >= ${minimumLibvipsVersion}`);
} }
if (runtimePlatform.startsWith('linux') && /symbol not found/i.test(errPackage)) { if (isLinux && /symbol not found/i.test(errPackage)) {
try { try {
const { engines } = require(`@sharpen/sharp-libvips-${runtimePlatform}/package`); const { engines } = require(`@sharpen/sharp-libvips-${runtimePlatform}/package`);
const libcFound = `${familySync()} ${versionSync()}`; const libcFound = `${familySync()} ${versionSync()}`;
@@ -41,16 +46,17 @@ try {
help.push(`- Update your OS: found ${libcFound}, requires ${libcRequires}`); help.push(`- Update your OS: found ${libcFound}, requires ${libcRequires}`);
} catch (errEngines) {} } catch (errEngines) {}
} }
if (runtimePlatform.startsWith('darwin') && /Incompatible library version/.test(errLocal.message)) { if (isMacOs && /Incompatible library version/.test(errLocal.message)) {
help.push('- Update Homebrew: "brew update && brew upgrade vips"'); help.push('- Update Homebrew:');
help.push(' brew update && brew upgrade vips');
} }
if (errPackage.code === 'ERR_DLOPEN_DISABLED') { if (errPackage.code === 'ERR_DLOPEN_DISABLED') {
help.push('- Run Node.js without using the --no-addons flag'); help.push('- Run Node.js without using the --no-addons flag');
} }
// Link to installation docs // Link to installation docs
if (runtimePlatform.startsWith('linux') && /Module did not self-register/.test(errLocal.message + errPackage.message)) { if (isLinux && /Module did not self-register/.test(errLocal.message + errPackage.message)) {
help.push('- Using worker threads on Linux? See https://sharp.pixelplumbing.com/install#worker-threads'); help.push('- Using worker threads on Linux? See https://sharp.pixelplumbing.com/install#worker-threads');
} else if (runtimePlatform.startsWith('win32') && /The specified procedure could not be found/.test(errPackage.message)) { } else if (isWindows && /The specified procedure could not be found/.test(errPackage.message)) {
help.push('- Using the canvas package on Windows? See https://sharp.pixelplumbing.com/install#canvas-and-windows'); help.push('- Using the canvas package on Windows? See https://sharp.pixelplumbing.com/install#canvas-and-windows');
} else { } else {
help.push('- Consult the installation documentation: https://sharp.pixelplumbing.com/install'); help.push('- Consult the installation documentation: https://sharp.pixelplumbing.com/install');

View File

@@ -3,7 +3,7 @@
'use strict'; 'use strict';
const events = require('events'); const events = require('node:events');
const detectLibc = require('detect-libc'); const detectLibc = require('detect-libc');
const is = require('./is'); const is = require('./is');

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-darwin-arm64", "name": "@sharpen/sharp-darwin-arm64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with macOS ARM64", "description": "Prebuilt sharp for use with macOS ARM64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-darwin-arm64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-darwin-arm64.node", "./sharp.node": "./lib/sharp-darwin-arm64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-darwin-x64", "name": "@sharpen/sharp-darwin-x64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with macOS x64", "description": "Prebuilt sharp for use with macOS x64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-darwin-x64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-darwin-x64.node", "./sharp.node": "./lib/sharp-darwin-x64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -5,7 +5,7 @@
// Populate contents of all packages with the current GitHub release // Populate contents of all packages with the current GitHub release
const { writeFile, copyFile } = require('node:fs/promises'); const { writeFile, copyFile, rm } = require('node:fs/promises');
const path = require('node:path'); const path = require('node:path');
const { Readable } = require('node:stream'); const { Readable } = require('node:stream');
const { pipeline } = require('node:stream/promises'); const { pipeline } = require('node:stream/promises');
@@ -46,10 +46,12 @@ workspaces.map(async platform => {
return; return;
} }
// Extract prebuild tarball // Extract prebuild tarball
const lib = path.join(dir, 'lib');
await rm(lib, { recursive: true });
await pipeline( await pipeline(
Readable.fromWeb(response.body), Readable.fromWeb(response.body),
createGunzip(), createGunzip(),
extract(path.join(dir, 'lib'), { map: mapTarballEntry }) extract(lib, { map: mapTarballEntry })
); );
// Generate README // Generate README
const { name, description } = require(`./${platform}/package.json`); const { name, description } = require(`./${platform}/package.json`);

View File

@@ -14,7 +14,7 @@ const platform = buildPlatformArch();
const dest = path.join(__dirname, platform); const dest = path.join(__dirname, platform);
// Use same config as prebuild to copy binary files // Use same config as prebuild to copy binary files
const release = path.join(__dirname, '..', 'build', 'Release'); const release = path.join(__dirname, '..', 'src', 'build', 'Release');
const prebuildrc = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '.prebuildrc'), 'utf8')); const prebuildrc = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '.prebuildrc'), 'utf8'));
const include = new RegExp(prebuildrc['include-regex'], 'i'); const include = new RegExp(prebuildrc['include-regex'], 'i');
fs.cpSync(release, path.join(dest, 'lib'), { fs.cpSync(release, path.join(dest, 'lib'), {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-linux-arm", "name": "@sharpen/sharp-linux-arm",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)", "description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-linux-arm": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-linux-arm.node", "./sharp.node": "./lib/sharp-linux-arm.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-linux-arm64", "name": "@sharpen/sharp-linux-arm64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Linux (glibc) ARM64", "description": "Prebuilt sharp for use with Linux (glibc) ARM64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-linux-arm64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-linux-arm64.node", "./sharp.node": "./lib/sharp-linux-arm64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-linux-x64", "name": "@sharpen/sharp-linux-x64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Linux (glibc) x64", "description": "Prebuilt sharp for use with Linux (glibc) x64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-linux-x64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-linux-x64.node", "./sharp.node": "./lib/sharp-linux-x64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-linuxmusl-arm64", "name": "@sharpen/sharp-linuxmusl-arm64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Linux (musl) ARM64", "description": "Prebuilt sharp for use with Linux (musl) ARM64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-linuxmusl-arm64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-linuxmusl-arm64.node", "./sharp.node": "./lib/sharp-linuxmusl-arm64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-linuxmusl-x64", "name": "@sharpen/sharp-linuxmusl-x64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Linux (musl) x64", "description": "Prebuilt sharp for use with Linux (musl) x64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,13 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-linuxmusl-x64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-linuxmusl-x64.node", "./sharp.node": "./lib/sharp-linuxmusl-x64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-win32-ia32", "name": "@sharpen/sharp-win32-ia32",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Windows x86 (32-bit)", "description": "Prebuilt sharp for use with Windows x86 (32-bit)",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,18 +13,19 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-win32-ia32": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib",
"versions.json",
"THIRD-PARTY-NOTICES.md"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-win32-ia32.node", "./sharp.node": "./lib/sharp-win32-ia32.node",
"./package": "./package.json" "./package": "./package.json",
"./versions": "./versions.json"
}, },
"engines": { "engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0", "node": "^18.17.0 || ^20.3.0 || >=21.0.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@sharpen/sharp-win32-x64", "name": "@sharpen/sharp-win32-x64",
"version": "0.0.1-alpha.1", "version": "0.0.1-alpha.6",
"description": "Prebuilt sharp for use with Windows x64", "description": "Prebuilt sharp for use with Windows x64",
"homepage": "https://sharp.pixelplumbing.com", "homepage": "https://sharp.pixelplumbing.com",
"repository": { "repository": {
@@ -13,15 +13,15 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"preferUnplugged": true, "preferUnplugged": true,
"optionalDependencies": {
"@sharpen/sharp-libvips-win32-x64": "0.0.1-alpha.1"
},
"files": [ "files": [
"lib" "lib",
"versions.json",
"THIRD-PARTY-NOTICES.md"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"type": "commonjs",
"exports": { "exports": {
"./sharp.node": "./lib/sharp-win32-x64.node", "./sharp.node": "./lib/sharp-win32-x64.node",
"./package": "./package.json" "./package": "./package.json"

View File

@@ -1,7 +1,7 @@
{ {
"name": "sharp", "name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images", "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
"version": "0.33.0-alpha.2", "version": "0.33.0-alpha.6",
"author": "Lovell Fuller <npm@lovell.info>", "author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp", "homepage": "https://github.com/lovell/sharp",
"contributors": [ "contributors": [
@@ -90,7 +90,7 @@
], ],
"scripts": { "scripts": {
"install": "node install/check", "install": "node install/check",
"clean": "rm -rf build/ .nyc_output/ coverage/ test/fixtures/output.*", "clean": "rm -rf src/build/ .nyc_output/ coverage/ test/fixtures/output.*",
"test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types", "test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types",
"test-lint": "semistandard && cpplint", "test-lint": "semistandard && cpplint",
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha", "test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha",
@@ -103,13 +103,13 @@
"docs-serve": "cd docs && npx serve", "docs-serve": "cd docs && npx serve",
"docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp" "docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp"
}, },
"type": "commonjs",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
"files": [ "files": [
"binding.gyp", "install",
"install/**", "lib",
"lib/**", "src/*.{cc,h,gyp}"
"src/**"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
@@ -136,31 +136,30 @@
"dependencies": { "dependencies": {
"color": "^4.2.3", "color": "^4.2.3",
"detect-libc": "^2.0.2", "detect-libc": "^2.0.2",
"node-addon-api": "^7.0.0",
"semver": "^7.5.4" "semver": "^7.5.4"
}, },
"optionalDependencies": { "optionalDependencies": {
"@sharpen/sharp-darwin-arm64": "0.0.1-alpha.2", "@sharpen/sharp-darwin-arm64": "0.0.1-alpha.6",
"@sharpen/sharp-darwin-x64": "0.0.1-alpha.2", "@sharpen/sharp-darwin-x64": "0.0.1-alpha.6",
"@sharpen/sharp-linux-arm": "0.0.1-alpha.2", "@sharpen/sharp-libvips-darwin-arm64": "0.0.1-alpha.2",
"@sharpen/sharp-linux-arm64": "0.0.1-alpha.2", "@sharpen/sharp-libvips-darwin-x64": "0.0.1-alpha.2",
"@sharpen/sharp-linux-x64": "0.0.1-alpha.2", "@sharpen/sharp-libvips-linux-arm": "0.0.1-alpha.2",
"@sharpen/sharp-linuxmusl-arm64": "0.0.1-alpha.2", "@sharpen/sharp-libvips-linux-arm64": "0.0.1-alpha.2",
"@sharpen/sharp-linuxmusl-x64": "0.0.1-alpha.2", "@sharpen/sharp-libvips-linux-x64": "0.0.1-alpha.2",
"@sharpen/sharp-win32-ia32": "0.0.1-alpha.2", "@sharpen/sharp-libvips-linuxmusl-arm64": "0.0.1-alpha.2",
"@sharpen/sharp-win32-x64": "0.0.1-alpha.2" "@sharpen/sharp-libvips-linuxmusl-x64": "0.0.1-alpha.2",
"@sharpen/sharp-linux-arm": "0.0.1-alpha.6",
"@sharpen/sharp-linux-arm64": "0.0.1-alpha.6",
"@sharpen/sharp-linux-x64": "0.0.1-alpha.6",
"@sharpen/sharp-linuxmusl-arm64": "0.0.1-alpha.6",
"@sharpen/sharp-linuxmusl-x64": "0.0.1-alpha.6",
"@sharpen/sharp-win32-ia32": "0.0.1-alpha.6",
"@sharpen/sharp-win32-x64": "0.0.1-alpha.6"
}, },
"devDependencies": { "devDependencies": {
"@sharpen/sharp-libvips-darwin-arm64": "0.0.1-alpha.1", "@sharpen/sharp-libvips-dev": "0.0.1-alpha.2",
"@sharpen/sharp-libvips-darwin-x64": "0.0.1-alpha.1", "@sharpen/sharp-libvips-win32-ia32": "0.0.1-alpha.2",
"@sharpen/sharp-libvips-dev": "0.0.1-alpha.1", "@sharpen/sharp-libvips-win32-x64": "0.0.1-alpha.2",
"@sharpen/sharp-libvips-linux-arm": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-linux-arm64": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-linux-x64": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-linuxmusl-arm64": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-linuxmusl-x64": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-win32-ia32": "0.0.1-alpha.1",
"@sharpen/sharp-libvips-win32-x64": "0.0.1-alpha.1",
"@types/node": "*", "@types/node": "*",
"async": "^3.2.4", "async": "^3.2.4",
"cc": "^3.0.1", "cc": "^3.0.1",
@@ -170,6 +169,7 @@
"jsdoc-to-markdown": "^8.0.0", "jsdoc-to-markdown": "^8.0.0",
"license-checker": "^25.0.1", "license-checker": "^25.0.1",
"mocha": "^10.2.0", "mocha": "^10.2.0",
"node-addon-api": "^7.0.0",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"prebuild": "^12.1.0", "prebuild": "^12.1.0",
"semistandard": "^17.0.0", "semistandard": "^17.0.0",

View File

@@ -3,14 +3,14 @@
{ {
'variables': { 'variables': {
'vips_version': '<!(node -p "require(\'./lib/libvips\').minimumLibvipsVersion")', 'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
'platform_and_arch': '<!(node -p "require(\'./lib/libvips\').buildPlatformArch()")', 'platform_and_arch': '<!(node -p "require(\'../lib/libvips\').buildPlatformArch()")',
'sharp_libvips_include_dir': '<!(node -p "require(\'./lib/libvips\').buildSharpLibvipsIncludeDir()")', 'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'./lib/libvips\').buildSharpLibvipsCPlusPlusDir()")', 'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsCPlusPlusDir()")',
'sharp_libvips_lib_dir': '<!(node -p "require(\'./lib/libvips\').buildSharpLibvipsLibDir()")' 'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
}, },
'targets': [{ 'targets': [{
'target_name': 'win-libvips-cpp', 'target_name': 'libvips-cpp',
'conditions': [ 'conditions': [
['OS == "win"', { ['OS == "win"', {
# Build libvips C++ binding for Windows due to MSVC std library ABI changes # Build libvips C++ binding for Windows due to MSVC std library ABI changes
@@ -81,13 +81,13 @@
], ],
'dependencies': [ 'dependencies': [
'<!(node -p "require(\'node-addon-api\').gyp")', '<!(node -p "require(\'node-addon-api\').gyp")',
'win-libvips-cpp' 'libvips-cpp'
], ],
'variables': { 'variables': {
'conditions': [ 'conditions': [
['OS != "win"', { ['OS != "win"', {
'pkg_config_path': '<!(node -p "require(\'./lib/libvips\').pkgConfigPath()")', 'pkg_config_path': '<!(node -p "require(\'../lib/libvips\').pkgConfigPath()")',
'use_global_libvips': '<!(node -p "Boolean(require(\'./lib/libvips\').useGlobalLibvips()).toString()")' 'use_global_libvips': '<!(node -p "Boolean(require(\'../lib/libvips\').useGlobalLibvips()).toString()")'
}, { }, {
'pkg_config_path': '', 'pkg_config_path': '',
'use_global_libvips': '' 'use_global_libvips': ''
@@ -95,13 +95,13 @@
] ]
}, },
'sources': [ 'sources': [
'src/common.cc', 'common.cc',
'src/metadata.cc', 'metadata.cc',
'src/stats.cc', 'stats.cc',
'src/operations.cc', 'operations.cc',
'src/pipeline.cc', 'pipeline.cc',
'src/utilities.cc', 'utilities.cc',
'src/sharp.cc' 'sharp.cc'
], ],
'include_dirs': [ 'include_dirs': [
'<!(node -p "require(\'node-addon-api\').include_dir")', '<!(node -p "require(\'node-addon-api\').include_dir")',
@@ -154,7 +154,6 @@
'OTHER_LDFLAGS': [ 'OTHER_LDFLAGS': [
# Ensure runtime linking is relative to sharp.node # Ensure runtime linking is relative to sharp.node
'-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'', '-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'',
'-Wl,-rpath,\'@loader_path/../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'',
'-Wl,-rpath,\'@loader_path/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'' '-Wl,-rpath,\'@loader_path/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\''
] ]
} }
@@ -175,7 +174,6 @@
'-Wl,-s', '-Wl,-s',
'-Wl,--disable-new-dtags', '-Wl,--disable-new-dtags',
'-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'', '-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
'-Wl,-rpath=\'$$ORIGIN/../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'',
'-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'' '-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\''
] ]
} }
@@ -243,7 +241,7 @@
} }
}, },
}, { }, {
'target_name': 'win-copy-dlls', 'target_name': 'copy-dll',
'type': 'none', 'type': 'none',
'dependencies': [ 'dependencies': [
'sharp-<(platform_and_arch)' 'sharp-<(platform_and_arch)'

View File

@@ -363,12 +363,13 @@ namespace sharp {
if (descriptor->isBuffer) { if (descriptor->isBuffer) {
if (descriptor->rawChannels > 0) { if (descriptor->rawChannels > 0) {
// Raw, uncompressed pixel data // Raw, uncompressed pixel data
bool const is8bit = vips_band_format_is8bit(descriptor->rawDepth);
image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength, image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth); descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth);
if (descriptor->rawChannels < 3) { if (descriptor->rawChannels < 3) {
image.get_image()->Type = VIPS_INTERPRETATION_B_W; image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_GREY16;
} else { } else {
image.get_image()->Type = VIPS_INTERPRETATION_sRGB; image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_RGB16;
} }
if (descriptor->rawPremultiplied) { if (descriptor->rawPremultiplied) {
image = image.unpremultiply(); image = image.unpremultiply();

View File

@@ -1,6 +1,8 @@
// Copyright 2013 Lovell Fuller and others. // Copyright 2013 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#include <mutex> // NOLINT(build/c++11)
#include <napi.h> #include <napi.h>
#include <vips/vips8> #include <vips/vips8>
@@ -10,14 +12,11 @@
#include "utilities.h" #include "utilities.h"
#include "stats.h" #include "stats.h"
static void* sharp_vips_init(void*) {
vips_init("sharp");
return nullptr;
}
Napi::Object init(Napi::Env env, Napi::Object exports) { Napi::Object init(Napi::Env env, Napi::Object exports) {
static GOnce sharp_vips_init_once = G_ONCE_INIT; static std::once_flag sharp_vips_init_once;
g_once(&sharp_vips_init_once, static_cast<GThreadFunc>(sharp_vips_init), nullptr); std::call_once(sharp_vips_init_once, []() {
vips_init("sharp");
});
g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING), g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr); static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);

View File

@@ -284,4 +284,42 @@ describe('Raw pixel data', function () {
); );
} }
}); });
describe('16-bit roundtrip', () => {
it('grey', async () => {
const grey = 42000;
const png = await sharp(
Uint16Array.from([grey]),
{ raw: { width: 1, height: 1, channels: 1 } }
)
.toColourspace('grey16')
.png({ compressionLevel: 0 })
.toBuffer();
const raw = await sharp(png)
.toColourspace('grey16')
.raw({ depth: 'ushort' })
.toBuffer();
assert.strictEqual(raw.readUint16LE(0), grey);
});
it('RGB', async () => {
const rgb = [10946, 28657, 46368];
const png = await sharp(
Uint16Array.from(rgb),
{ raw: { width: 1, height: 1, channels: 3 } }
)
.toColourspace('rgb16')
.png({ compressionLevel: 0 })
.toBuffer();
const raw = await sharp(png)
.toColourspace('rgb16')
.raw({ depth: 'ushort' })
.toBuffer();
assert.strictEqual(raw.readUint16LE(0), rgb[0]);
assert.strictEqual(raw.readUint16LE(2), rgb[1]);
assert.strictEqual(raw.readUint16LE(4), rgb[2]);
});
});
}); });