mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Ensure id attr can be set for IIIF tile output #2612
This commit is contained in:
parent
5a9cc835b3
commit
00aece0538
@ -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.
|
* 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*
|
## v0.27 - *avif*
|
||||||
|
|
||||||
Requires libvips v8.10.5
|
Requires libvips v8.10.5
|
||||||
|
@ -279,6 +279,7 @@ const Sharp = function (input, options) {
|
|||||||
tileSkipBlanks: -1,
|
tileSkipBlanks: -1,
|
||||||
tileBackground: [255, 255, 255, 255],
|
tileBackground: [255, 255, 255, 255],
|
||||||
tileCentre: false,
|
tileCentre: false,
|
||||||
|
tileId: 'https://example.com/iiif',
|
||||||
linearA: 1,
|
linearA: 1,
|
||||||
linearB: 0,
|
linearB: 0,
|
||||||
// Function to notify of libvips warnings
|
// Function to notify of libvips warnings
|
||||||
|
@ -727,6 +727,7 @@ function raw () {
|
|||||||
* @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.centre=false] centre image in tile.
|
||||||
* @param {boolean} [options.center=false] alternative spelling of centre.
|
* @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}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@ -800,6 +801,14 @@ function tile (options) {
|
|||||||
if (is.defined(centre)) {
|
if (is.defined(centre)) {
|
||||||
this._setBooleanOption('tileCentre', 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
|
// Format
|
||||||
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
||||||
|
@ -1038,6 +1038,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
||||||
->set("background", baton->tileBackground)
|
->set("background", baton->tileBackground)
|
||||||
->set("centre", baton->tileCentre)
|
->set("centre", baton->tileCentre)
|
||||||
|
->set("id", const_cast<char*>(baton->tileId.data()))
|
||||||
->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
|
||||||
@ -1438,6 +1439,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
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");
|
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
|
||||||
|
baton->tileId = sharp::AttrAsStr(options, "tileId");
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -192,6 +192,7 @@ struct PipelineBaton {
|
|||||||
std::vector<double> tileBackground;
|
std::vector<double> tileBackground;
|
||||||
int tileSkipBlanks;
|
int tileSkipBlanks;
|
||||||
VipsForeignDzDepth tileDepth;
|
VipsForeignDzDepth tileDepth;
|
||||||
|
std::string tileId;
|
||||||
std::unique_ptr<double[]> recombMatrix;
|
std::unique_ptr<double[]> recombMatrix;
|
||||||
|
|
||||||
PipelineBaton():
|
PipelineBaton():
|
||||||
|
@ -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) {
|
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 () {
|
||||||
@ -815,11 +831,14 @@ describe('Tile', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('IIIF layout', function (done) {
|
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 () {
|
rimraf(directory, function () {
|
||||||
|
const id = 'https://sharp.test.com/iiif';
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.tile({
|
.tile({
|
||||||
layout: 'iiif'
|
layout: 'iiif',
|
||||||
|
id
|
||||||
})
|
})
|
||||||
.toFile(directory, function (err, info) {
|
.toFile(directory, function (err, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@ -828,6 +847,8 @@ describe('Tile', function () {
|
|||||||
assert.strictEqual(2225, info.height);
|
assert.strictEqual(2225, info.height);
|
||||||
assert.strictEqual(3, info.channels);
|
assert.strictEqual(3, info.channels);
|
||||||
assert.strictEqual('number', typeof info.size);
|
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) {
|
fs.stat(path.join(directory, '0,0,256,256', '256,', '0', 'default.jpg'), function (err, stat) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, stat.isFile());
|
assert.strictEqual(true, stat.isFile());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user