mirror of
https://github.com/lovell/sharp.git
synced 2026-02-05 06:06:18 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbe48d75dd | ||
|
|
20ba0f49dd | ||
|
|
c213e9878d | ||
|
|
9704ca4c18 | ||
|
|
49dce6219e | ||
|
|
260ff6c94f | ||
|
|
3ec281d104 |
@@ -372,6 +372,8 @@ Warning: multiple sharp instances concurrently producing tile output can expose
|
|||||||
- `options.skipBlanks` **[number][9]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
|
- `options.skipBlanks` **[number][9]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
|
||||||
- `options.container` **[string][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
|
- `options.container` **[string][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
|
||||||
- `options.layout` **[string][2]** filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`. (optional, default `'dz'`)
|
- `options.layout` **[string][2]** filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`. (optional, default `'dz'`)
|
||||||
|
- `options.centre` **[boolean][7]** centre image in tile. (optional, default `false`)
|
||||||
|
- `options.center` **[boolean][7]** alternative spelling of centre. (optional, default `false`)
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,8 @@ Returns **Sharp**
|
|||||||
Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
||||||
Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
||||||
|
|
||||||
The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
The `info` response Object, obtained from callback of `.toFile()` or `.toBuffer()`,
|
||||||
|
will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,19 @@
|
|||||||
|
|
||||||
Requires libvips v8.10.0
|
Requires libvips v8.10.0
|
||||||
|
|
||||||
|
### v0.26.2 - 14th October 2020
|
||||||
|
|
||||||
|
* Add support for EXR input. Requires libvips compiled with OpenEXR.
|
||||||
|
[#698](https://github.com/lovell/sharp/issues/698)
|
||||||
|
|
||||||
|
* Ensure support for yarn v2.
|
||||||
|
[#2379](https://github.com/lovell/sharp/pull/2379)
|
||||||
|
[@jalovatt](https://github.com/jalovatt)
|
||||||
|
|
||||||
|
* Add centre/center option to tile-based output.
|
||||||
|
[#2397](https://github.com/lovell/sharp/pull/2397)
|
||||||
|
[@beig](https://github.com/beig)
|
||||||
|
|
||||||
### v0.26.1 - 20th September 2020
|
### v0.26.1 - 20th September 2020
|
||||||
|
|
||||||
* Ensure correct pageHeight when verifying multi-page image dimensions.
|
* Ensure correct pageHeight when verifying multi-page image dimensions.
|
||||||
|
|||||||
@@ -203,3 +203,6 @@ GitHub: https://github.com/derom
|
|||||||
|
|
||||||
Name: Stefan Probst
|
Name: Stefan Probst
|
||||||
GitHub: https://github.com/stefanprobst
|
GitHub: https://github.com/stefanprobst
|
||||||
|
|
||||||
|
Name: Thomas Beiganz
|
||||||
|
GitHub: https://github.com/beig
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
|
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
|
||||||
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
|
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
|
||||||
<link rel="author" href="/humans.txt" type="text/plain">
|
<link rel="author" href="/humans.txt" type="text/plain">
|
||||||
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.1/docs/README.md" as="fetch" type="text/markdown" crossorigin>
|
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.2/docs/README.md" as="fetch" type="text/markdown" crossorigin>
|
||||||
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
|
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
|
||||||
<link rel="dns-prefetch" href="https://pixel.plumbing">
|
<link rel="dns-prefetch" href="https://pixel.plumbing">
|
||||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
docuteApiTitlePlugin,
|
docuteApiTitlePlugin,
|
||||||
docuteApiSearchPlugin
|
docuteApiSearchPlugin
|
||||||
],
|
],
|
||||||
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.1/docs',
|
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.2/docs',
|
||||||
nav: [
|
nav: [
|
||||||
{
|
{
|
||||||
title: 'Funding',
|
title: 'Funding',
|
||||||
|
|||||||
@@ -80,9 +80,12 @@ try {
|
|||||||
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!semver.satisfies(process.versions.node, process.env.npm_package_engines_node)) {
|
|
||||||
throw new Error(`Expected Node.js version ${process.env.npm_package_engines_node} but found ${process.versions.node}`);
|
const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
|
||||||
|
if (!semver.satisfies(process.versions.node, supportedNodeVersion)) {
|
||||||
|
throw new Error(`Expected Node.js version ${supportedNodeVersion} but found ${process.versions.node}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download to per-process temporary file
|
// Download to per-process temporary file
|
||||||
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
|
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
|
||||||
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ const Sharp = function (input, options) {
|
|||||||
tileAngle: 0,
|
tileAngle: 0,
|
||||||
tileSkipBlanks: -1,
|
tileSkipBlanks: -1,
|
||||||
tileBackground: [255, 255, 255, 255],
|
tileBackground: [255, 255, 255, 255],
|
||||||
|
tileCentre: false,
|
||||||
linearA: 1,
|
linearA: 1,
|
||||||
linearB: 0,
|
linearB: 0,
|
||||||
// Function to notify of libvips warnings
|
// Function to notify of libvips warnings
|
||||||
|
|||||||
@@ -658,6 +658,8 @@ function raw () {
|
|||||||
* @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
|
* @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
|
||||||
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
||||||
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
|
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
|
||||||
|
* @param {boolean} [options.centre=false] centre image in tile.
|
||||||
|
* @param {boolean} [options.center=false] alternative spelling of centre.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@@ -726,6 +728,11 @@ function tile (options) {
|
|||||||
} else if (is.defined(options.layout) && options.layout === 'google') {
|
} else if (is.defined(options.layout) && options.layout === 'google') {
|
||||||
this.options.tileSkipBlanks = 5;
|
this.options.tileSkipBlanks = 5;
|
||||||
}
|
}
|
||||||
|
// Center image in tile
|
||||||
|
const centre = is.bool(options.center) ? options.center : options.centre;
|
||||||
|
if (is.defined(centre)) {
|
||||||
|
this._setBooleanOption('tileCentre', centre);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Format
|
// Format
|
||||||
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
||||||
|
|||||||
@@ -386,7 +386,8 @@ function extract (options) {
|
|||||||
* Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
* Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
||||||
* Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
* Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
||||||
*
|
*
|
||||||
* The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
* The `info` response Object, obtained from callback of `.toFile()` or `.toBuffer()`,
|
||||||
|
* will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
||||||
*
|
*
|
||||||
* @param {number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
|
* @param {number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
|
||||||
"version": "0.26.1",
|
"version": "0.26.2",
|
||||||
"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": [
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ namespace sharp {
|
|||||||
case ImageType::OPENSLIDE: id = "openslide"; break;
|
case ImageType::OPENSLIDE: id = "openslide"; break;
|
||||||
case ImageType::PPM: id = "ppm"; break;
|
case ImageType::PPM: id = "ppm"; break;
|
||||||
case ImageType::FITS: id = "fits"; break;
|
case ImageType::FITS: id = "fits"; break;
|
||||||
|
case ImageType::EXR: id = "exr"; break;
|
||||||
case ImageType::VIPS: id = "vips"; break;
|
case ImageType::VIPS: id = "vips"; break;
|
||||||
case ImageType::RAW: id = "raw"; break;
|
case ImageType::RAW: id = "raw"; break;
|
||||||
case ImageType::UNKNOWN: id = "unknown"; break;
|
case ImageType::UNKNOWN: id = "unknown"; break;
|
||||||
@@ -210,6 +211,7 @@ namespace sharp {
|
|||||||
{ "openslideload", ImageType::OPENSLIDE },
|
{ "openslideload", ImageType::OPENSLIDE },
|
||||||
{ "ppmload", ImageType::PPM },
|
{ "ppmload", ImageType::PPM },
|
||||||
{ "fitsload", ImageType::FITS },
|
{ "fitsload", ImageType::FITS },
|
||||||
|
{ "openexrload", ImageType::EXR },
|
||||||
{ "vipsload", ImageType::VIPS },
|
{ "vipsload", ImageType::VIPS },
|
||||||
{ "rawload", ImageType::RAW }
|
{ "rawload", ImageType::RAW }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ namespace sharp {
|
|||||||
OPENSLIDE,
|
OPENSLIDE,
|
||||||
PPM,
|
PPM,
|
||||||
FITS,
|
FITS,
|
||||||
|
EXR,
|
||||||
VIPS,
|
VIPS,
|
||||||
RAW,
|
RAW,
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
|||||||
@@ -1014,6 +1014,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("suffix", const_cast<char*>(suffix.data()))
|
->set("suffix", const_cast<char*>(suffix.data()))
|
||||||
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
||||||
->set("background", baton->tileBackground)
|
->set("background", baton->tileBackground)
|
||||||
|
->set("centre", baton->tileCentre)
|
||||||
->set("skip_blanks", baton->tileSkipBlanks);
|
->set("skip_blanks", baton->tileSkipBlanks);
|
||||||
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
|
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
|
||||||
// not passing anything - libvips will handle choice
|
// not passing anything - libvips will handle choice
|
||||||
@@ -1403,6 +1404,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->tileDepth = static_cast<VipsForeignDzDepth>(
|
baton->tileDepth = static_cast<VipsForeignDzDepth>(
|
||||||
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
|
||||||
sharp::AttrAsStr(options, "tileDepth").data()));
|
sharp::AttrAsStr(options, "tileDepth").data()));
|
||||||
|
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
|
||||||
|
|
||||||
// Force random access for certain operations
|
// Force random access for certain operations
|
||||||
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
|
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ struct PipelineBaton {
|
|||||||
int cropOffsetLeft;
|
int cropOffsetLeft;
|
||||||
int cropOffsetTop;
|
int cropOffsetTop;
|
||||||
bool premultiplied;
|
bool premultiplied;
|
||||||
|
bool tileCentre;
|
||||||
std::string kernel;
|
std::string kernel;
|
||||||
bool fastShrinkOnLoad;
|
bool fastShrinkOnLoad;
|
||||||
double tintA;
|
double tintA;
|
||||||
|
|||||||
BIN
test/fixtures/expected/tile_centered.jpg
vendored
Normal file
BIN
test/fixtures/expected/tile_centered.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
@@ -289,6 +289,14 @@ describe('Tile', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Invalid center parameter value fail', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tile({
|
||||||
|
centre: 'true'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Deep Zoom layout', function (done) {
|
it('Deep Zoom layout', function (done) {
|
||||||
const directory = fixtures.path('output.dzi_files');
|
const directory = fixtures.path('output.dzi_files');
|
||||||
rimraf(directory, function () {
|
rimraf(directory, function () {
|
||||||
@@ -765,6 +773,46 @@ describe('Tile', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Google layout with center image in tile', function (done) {
|
||||||
|
const directory = fixtures.path('output.google_center.dzi');
|
||||||
|
rimraf(directory, function () {
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.tile({
|
||||||
|
center: true,
|
||||||
|
layout: 'google'
|
||||||
|
})
|
||||||
|
.toFile(directory, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('dz', info.format);
|
||||||
|
assert.strictEqual(2725, info.width);
|
||||||
|
assert.strictEqual(2225, info.height);
|
||||||
|
assert.strictEqual(3, info.channels);
|
||||||
|
assert.strictEqual('number', typeof info.size);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Google layout with center image in tile centre', function (done) {
|
||||||
|
const directory = fixtures.path('output.google_center.dzi');
|
||||||
|
rimraf(directory, function () {
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.tile({
|
||||||
|
centre: true,
|
||||||
|
layout: 'google'
|
||||||
|
})
|
||||||
|
.toFile(directory, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('dz', info.format);
|
||||||
|
assert.strictEqual(2725, info.width);
|
||||||
|
assert.strictEqual(2225, info.height);
|
||||||
|
assert.strictEqual(3, info.channels);
|
||||||
|
assert.strictEqual('number', typeof info.size);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('IIIF layout', function (done) {
|
it('IIIF layout', function (done) {
|
||||||
const directory = fixtures.path('output.iiif.info');
|
const directory = fixtures.path('output.iiif.info');
|
||||||
rimraf(directory, function () {
|
rimraf(directory, function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user