Skip to content

Commit

Permalink
Ensure id attr can be set for IIIF tile output #2612
Browse files Browse the repository at this point in the history
  • Loading branch information
lovell committed Mar 12, 2021
1 parent e6380fd commit a4b7580
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 2 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Requires libvips v8.10.6

* Reduce concurrency on glibc-based Linux when using the default memory allocator to help prevent fragmentation.

* Ensure `@id` attribute can be set for IIIF tile-based output.
[#2612](https://github.com/lovell/sharp/issues/2612)
[@edsilv](https://github.com/edsilv)

## v0.27 - *avif*

Requires libvips v8.10.5
Expand Down
1 change: 1 addition & 0 deletions lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ const Sharp = function (input, options) {
tileSkipBlanks: -1,
tileBackground: [255, 255, 255, 255],
tileCentre: false,
tileId: 'https://example.com/iiif',
linearA: 1,
linearB: 0,
// Function to notify of libvips warnings
Expand Down
9 changes: 9 additions & 0 deletions lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ function raw () {
* @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.
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`, sets the `@id` attribute of `info.json`
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
Expand Down Expand Up @@ -800,6 +801,14 @@ function tile (options) {
if (is.defined(centre)) {
this._setBooleanOption('tileCentre', centre);
}
// @id attribute for IIIF layout
if (is.defined(options.id)) {
if (is.string(options.id)) {
this.options.tileId = options.id;
} else {
throw is.invalidParameterError('id', 'string', options.id);
}
}
}
// Format
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
Expand Down
2 changes: 2 additions & 0 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,7 @@ class PipelineWorker : public Napi::AsyncWorker {
->set("angle", CalculateAngleRotation(baton->tileAngle))
->set("background", baton->tileBackground)
->set("centre", baton->tileCentre)
->set("id", const_cast<char*>(baton->tileId.data()))
->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
Expand Down Expand Up @@ -1438,6 +1439,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
sharp::AttrAsStr(options, "tileDepth").data()));
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
baton->tileId = sharp::AttrAsStr(options, "tileId");

// Force random access for certain operations
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
Expand Down
1 change: 1 addition & 0 deletions src/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct PipelineBaton {
std::vector<double> tileBackground;
int tileSkipBlanks;
VipsForeignDzDepth tileDepth;
std::string tileId;
std::unique_ptr<double[]> recombMatrix;

PipelineBaton():
Expand Down
25 changes: 23 additions & 2 deletions test/unit/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,22 @@ describe('Tile', function () {
});
});

it('Valid id parameter value passes', function () {
assert.doesNotThrow(function () {
sharp().tile({
id: 'test'
});
});
});

it('Invalid id parameter value fails', function () {
assert.throws(function () {
sharp().tile({
id: true
});
});
});

it('Deep Zoom layout', function (done) {
const directory = fixtures.path('output.dzi_files');
rimraf(directory, function () {
Expand Down Expand Up @@ -815,11 +831,14 @@ describe('Tile', function () {
});

it('IIIF layout', function (done) {
const directory = fixtures.path('output.iiif.info');
const name = 'output.iiif.info';
const directory = fixtures.path(name);
rimraf(directory, function () {
const id = 'https://sharp.test.com/iiif';
sharp(fixtures.inputJpg)
.tile({
layout: 'iiif'
layout: 'iiif',
id
})
.toFile(directory, function (err, info) {
if (err) throw err;
Expand All @@ -828,6 +847,8 @@ describe('Tile', function () {
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
const infoJson = require(path.join(directory, 'info.json'));
assert.strictEqual(`${id}/${name}`, infoJson['@id']);
fs.stat(path.join(directory, '0,0,256,256', '256,', '0', 'default.jpg'), function (err, stat) {
if (err) throw err;
assert.strictEqual(true, stat.isFile());
Expand Down

0 comments on commit a4b7580

Please sign in to comment.