Expose JPEG 2000 oneshot decoder option #4262

Requires libvips compiled with support for JP2 images

Co-authored-by: Kleis Auke Wolthuizen <github@kleisauke.nl>
This commit is contained in:
Michael B. Klein
2024-11-12 11:32:41 -06:00
committed by Lovell Fuller
parent 01f6cbbaee
commit 751f9992c4
11 changed files with 67 additions and 7 deletions

View File

@@ -117,6 +117,7 @@ module.exports = {
inputTiffFogra: getPath('fogra-0-100-100-0.tif'), // https://github.com/lovell/sharp/issues/4045
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
inputJp2TileParts: getPath('relax_tileparts.jp2'), // kdu_expand -i relax.jp2 -o relax-tmp.tif ; kdu_compress -i relax-tmp.tif -o relax_tileparts.jp2 -jp2_space sRGB Clayers=8 -rate 1.0,0.04 Stiles='{128,128}' ORGtparts=L ; rm relax-tmp.tif
inputGif: getPath('Crash_test.gif'), // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif
inputGifGreyPlusAlpha: getPath('grey-plus-alpha.gif'), // http://i.imgur.com/gZ5jlmE.gif
inputGifAnimated: getPath('rotating-squares.gif'), // CC0 https://loading.io/spinner/blocks/-rotating-squares-preloader-gif

BIN
test/fixtures/relax_tileparts.jp2 vendored Normal file

Binary file not shown.

View File

@@ -721,6 +721,9 @@ const color: sharp.Color = '#fff';
sharp({ pdfBackground: colour });
sharp({ pdfBackground: color });
sharp({ jp2Oneshot: true });
sharp({ jp2Oneshot: false });
sharp({ autoOrient: true });
sharp({ autoOrient: false });
sharp().autoOrient();

View File

@@ -93,10 +93,38 @@ describe('JP2 output', () => {
});
});
it('Invalid JP2 chromaSubsampling value throws error', function () {
assert.throws(function () {
sharp().jpeg({ chromaSubsampling: '4:2:2' });
it('can use the jp2Oneshot option to handle multi-part tiled JPEG 2000 file', async () => {
const outputJpg = fixtures.path('output.jpg');
await assert.rejects(
() => sharp(fixtures.inputJp2TileParts).toFile(outputJpg)
);
await assert.doesNotReject(async () => {
await sharp(fixtures.inputJp2TileParts, { jp2Oneshot: true }).toFile(outputJpg);
const { format, width, height } = await sharp(outputJpg).metadata();
assert.strictEqual(format, 'jpeg');
assert.strictEqual(width, 320);
assert.strictEqual(height, 240);
});
});
it('Invalid JP2 chromaSubsampling value throws error', () => {
assert.throws(
() => sharp().jp2({ chromaSubsampling: '4:2:2' }),
/Expected one of 4:2:0, 4:4:4 but received 4:2:2 of type string/
);
});
}
it('valid JP2 oneshot value does not throw error', () => {
assert.doesNotThrow(
() => sharp(fixtures.inputJp2TileParts, { jp2Oneshot: true })
);
});
it('invalid JP2 oneshot value throws error', () => {
assert.throws(
() => sharp(fixtures.inputJp2TileParts, { jp2Oneshot: 'fail' }),
/Expected boolean for jp2Oneshot but received fail of type string/
);
});
});