mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Add centre/center option to tile-based output (#2397)
This commit is contained in:
parent
9704ca4c18
commit
c213e9878d
@ -372,6 +372,7 @@ 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.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.centre|center` **[boolean][7]** center image in tile (optional, default `false`)
|
||||
|
||||
### Examples
|
||||
|
||||
|
@ -238,6 +238,7 @@ const Sharp = function (input, options) {
|
||||
tileAngle: 0,
|
||||
tileSkipBlanks: -1,
|
||||
tileBackground: [255, 255, 255, 255],
|
||||
tileCentre: false,
|
||||
linearA: 1,
|
||||
linearB: 0,
|
||||
// Function to notify of libvips warnings
|
||||
|
@ -658,6 +658,7 @@ 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 {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 {boolean} [options.centre=false] center image in tile.
|
||||
* @returns {Sharp}
|
||||
* @throws {Error} Invalid parameters
|
||||
*/
|
||||
@ -726,6 +727,10 @@ function tile (options) {
|
||||
} else if (is.defined(options.layout) && options.layout === 'google') {
|
||||
this.options.tileSkipBlanks = 5;
|
||||
}
|
||||
// Center image in tile
|
||||
if (is.defined(options.centre) || is.defined(options.center)) {
|
||||
this._setBooleanOption('tileCentre', options.centre || options.center);
|
||||
}
|
||||
}
|
||||
// Format
|
||||
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
||||
|
@ -1014,6 +1014,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
->set("suffix", const_cast<char*>(suffix.data()))
|
||||
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
||||
->set("background", baton->tileBackground)
|
||||
->set("centre", baton->tileCentre)
|
||||
->set("skip_blanks", baton->tileSkipBlanks);
|
||||
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
|
||||
// not passing anything - libvips will handle choice
|
||||
@ -1403,6 +1404,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
||||
baton->tileDepth = static_cast<VipsForeignDzDepth>(
|
||||
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
|
||||
sharp::AttrAsStr(options, "tileDepth").data()));
|
||||
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
|
||||
|
||||
// Force random access for certain operations
|
||||
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
|
||||
|
@ -79,6 +79,7 @@ struct PipelineBaton {
|
||||
int cropOffsetLeft;
|
||||
int cropOffsetTop;
|
||||
bool premultiplied;
|
||||
bool tileCentre;
|
||||
std::string kernel;
|
||||
bool fastShrinkOnLoad;
|
||||
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({
|
||||
center: 'true'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Deep Zoom layout', function (done) {
|
||||
const directory = fixtures.path('output.dzi_files');
|
||||
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) {
|
||||
const directory = fixtures.path('output.iiif.info');
|
||||
rimraf(directory, function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user