Skip to content

Commit 00aece0

Browse files
committedMar 14, 2021
Ensure id attr can be set for IIIF tile output #2612
1 parent 5a9cc83 commit 00aece0

File tree

6 files changed

+40
-2
lines changed

6 files changed

+40
-2
lines changed
 

‎docs/changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Requires libvips v8.10.6
1616

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

19+
* Ensure `@id` attribute can be set for IIIF tile-based output.
20+
[#2612](https://github.com/lovell/sharp/issues/2612)
21+
[@edsilv](https://github.com/edsilv)
22+
1923
## v0.27 - *avif*
2024

2125
Requires libvips v8.10.5

‎lib/constructor.js

+1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ const Sharp = function (input, options) {
279279
tileSkipBlanks: -1,
280280
tileBackground: [255, 255, 255, 255],
281281
tileCentre: false,
282+
tileId: 'https://example.com/iiif',
282283
linearA: 1,
283284
linearB: 0,
284285
// Function to notify of libvips warnings

‎lib/output.js

+9
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ function raw () {
727727
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
728728
* @param {boolean} [options.centre=false] centre image in tile.
729729
* @param {boolean} [options.center=false] alternative spelling of centre.
730+
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`, sets the `@id` attribute of `info.json`
730731
* @returns {Sharp}
731732
* @throws {Error} Invalid parameters
732733
*/
@@ -800,6 +801,14 @@ function tile (options) {
800801
if (is.defined(centre)) {
801802
this._setBooleanOption('tileCentre', centre);
802803
}
804+
// @id attribute for IIIF layout
805+
if (is.defined(options.id)) {
806+
if (is.string(options.id)) {
807+
this.options.tileId = options.id;
808+
} else {
809+
throw is.invalidParameterError('id', 'string', options.id);
810+
}
811+
}
803812
}
804813
// Format
805814
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {

‎src/pipeline.cc

+2
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ class PipelineWorker : public Napi::AsyncWorker {
10381038
->set("angle", CalculateAngleRotation(baton->tileAngle))
10391039
->set("background", baton->tileBackground)
10401040
->set("centre", baton->tileCentre)
1041+
->set("id", const_cast<char*>(baton->tileId.data()))
10411042
->set("skip_blanks", baton->tileSkipBlanks);
10421043
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
10431044
// not passing anything - libvips will handle choice
@@ -1438,6 +1439,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
14381439
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
14391440
sharp::AttrAsStr(options, "tileDepth").data()));
14401441
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
1442+
baton->tileId = sharp::AttrAsStr(options, "tileId");
14411443

14421444
// Force random access for certain operations
14431445
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {

‎src/pipeline.h

+1
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ struct PipelineBaton {
192192
std::vector<double> tileBackground;
193193
int tileSkipBlanks;
194194
VipsForeignDzDepth tileDepth;
195+
std::string tileId;
195196
std::unique_ptr<double[]> recombMatrix;
196197

197198
PipelineBaton():

‎test/unit/tile.js

+23-2
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,22 @@ describe('Tile', function () {
297297
});
298298
});
299299

300+
it('Valid id parameter value passes', function () {
301+
assert.doesNotThrow(function () {
302+
sharp().tile({
303+
id: 'test'
304+
});
305+
});
306+
});
307+
308+
it('Invalid id parameter value fails', function () {
309+
assert.throws(function () {
310+
sharp().tile({
311+
id: true
312+
});
313+
});
314+
});
315+
300316
it('Deep Zoom layout', function (done) {
301317
const directory = fixtures.path('output.dzi_files');
302318
rimraf(directory, function () {
@@ -815,11 +831,14 @@ describe('Tile', function () {
815831
});
816832

817833
it('IIIF layout', function (done) {
818-
const directory = fixtures.path('output.iiif.info');
834+
const name = 'output.iiif.info';
835+
const directory = fixtures.path(name);
819836
rimraf(directory, function () {
837+
const id = 'https://sharp.test.com/iiif';
820838
sharp(fixtures.inputJpg)
821839
.tile({
822-
layout: 'iiif'
840+
layout: 'iiif',
841+
id
823842
})
824843
.toFile(directory, function (err, info) {
825844
if (err) throw err;
@@ -828,6 +847,8 @@ describe('Tile', function () {
828847
assert.strictEqual(2225, info.height);
829848
assert.strictEqual(3, info.channels);
830849
assert.strictEqual('number', typeof info.size);
850+
const infoJson = require(path.join(directory, 'info.json'));
851+
assert.strictEqual(`${id}/${name}`, infoJson['@id']);
831852
fs.stat(path.join(directory, '0,0,256,256', '256,', '0', 'default.jpg'), function (err, stat) {
832853
if (err) throw err;
833854
assert.strictEqual(true, stat.isFile());

0 commit comments

Comments
 (0)
Please sign in to comment.