Skip to content

Commit 751f999

Browse files
mbkleinkleisauke
authored andcommitted
Expose JPEG 2000 oneshot decoder option #4262
Requires libvips compiled with support for JP2 images Co-authored-by: Kleis Auke Wolthuizen <github@kleisauke.nl>
1 parent 01f6cbb commit 751f999

File tree

11 files changed

+67
-7
lines changed

11 files changed

+67
-7
lines changed

docs/src/content/docs/api-constructor.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ where the overall height is the `pageHeight` multiplied by the number of `pages`
4747
| [options.subifd] | <code>number</code> | <code>-1</code> | subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image. |
4848
| [options.level] | <code>number</code> | <code>0</code> | level to extract from a multi-level input (OpenSlide), zero based. |
4949
| [options.pdfBackground] | <code>string</code> \| <code>Object</code> | | Background colour to use when PDF is partially transparent. Parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. Requires the use of a globally-installed libvips compiled with support for PDFium, Poppler, ImageMagick or GraphicsMagick. |
50+
| [options.jp2Oneshot] | <code>boolean</code> | <code>false</code> | Set to `true` to decode tiled JPEG 2000 images in a single operation, improving compatibility. |
5051
| [options.animated] | <code>boolean</code> | <code>false</code> | Set to `true` to read all frames/pages of an animated image (GIF, WebP, TIFF), equivalent of setting `pages` to `-1`. |
5152
| [options.raw] | <code>Object</code> | | describes raw pixel input image data. See `raw()` for pixel ordering. |
5253
| [options.raw.width] | <code>number</code> | | integral number of pixels wide. |

docs/src/content/docs/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ Requires libvips v8.17.0
1010

1111
* Upgrade to libvips v8.17.0 for upstream bug fixes.
1212

13+
* Expose JPEG 2000 `oneshot` decoder option.
14+
[#4262](https://github.com/lovell/sharp/pull/4262)
15+
[@mbklein](https://github.com/mbklein)
16+
1317
* Support composite operation with non-sRGB pipeline colourspace.
1418
[#4412](https://github.com/lovell/sharp/pull/4412)
1519
[@kleisauke](https://github.com/kleisauke)

lib/constructor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const debuglog = util.debuglog('sharp');
156156
* @param {number} [options.subifd=-1] - subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image.
157157
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.
158158
* @param {string|Object} [options.pdfBackground] - Background colour to use when PDF is partially transparent. Parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. Requires the use of a globally-installed libvips compiled with support for PDFium, Poppler, ImageMagick or GraphicsMagick.
159+
* @param {boolean} [options.jp2Oneshot=false] - Set to `true` to decode tiled JPEG 2000 images in a single operation, improving compatibility.
159160
* @param {boolean} [options.animated=false] - Set to `true` to read all frames/pages of an animated image (GIF, WebP, TIFF), equivalent of setting `pages` to `-1`.
160161
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
161162
* @param {number} [options.raw.width] - integral number of pixels wide.

lib/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,8 @@ declare namespace sharp {
10091009
level?: number | undefined;
10101010
/** Background colour to use when PDF is partially transparent. Requires the use of a globally-installed libvips compiled with support for PDFium, Poppler, ImageMagick or GraphicsMagick. */
10111011
pdfBackground?: Colour | Color | undefined;
1012+
/** Set to `true` to load JPEG 2000 images using [oneshot mode](https://github.com/libvips/libvips/issues/4205) */
1013+
jp2Oneshot?: boolean | undefined;
10121014
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
10131015
animated?: boolean | undefined;
10141016
/** Describes raw pixel input image data. See raw() for pixel ordering. */

lib/input.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ const align = {
2727
* @private
2828
*/
2929
function _inputOptionsFromObject (obj) {
30-
const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient } = obj;
31-
return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient].some(is.defined)
32-
? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient }
30+
const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient, jp2Oneshot } = obj;
31+
return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient, jp2Oneshot].some(is.defined)
32+
? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient, jp2Oneshot }
3333
: undefined;
3434
}
3535

@@ -250,6 +250,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
250250
if (is.defined(inputOptions.pdfBackground)) {
251251
inputDescriptor.pdfBackground = this._getBackgroundColourOption(inputOptions.pdfBackground);
252252
}
253+
// JP2 oneshot
254+
if (is.defined(inputOptions.jp2Oneshot)) {
255+
if (is.bool(inputOptions.jp2Oneshot)) {
256+
inputDescriptor.jp2Oneshot = inputOptions.jp2Oneshot;
257+
} else {
258+
throw is.invalidParameterError('jp2Oneshot', 'boolean', inputOptions.jp2Oneshot);
259+
}
260+
}
253261
// Create new image
254262
if (is.defined(inputOptions.create)) {
255263
if (

src/common.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ namespace sharp {
113113
if (HasAttr(input, "pdfBackground")) {
114114
descriptor->pdfBackground = AttrAsVectorOfDouble(input, "pdfBackground");
115115
}
116+
// Use JPEG 2000 oneshot mode?
117+
if (HasAttr(input, "jp2Oneshot")) {
118+
descriptor->jp2Oneshot = AttrAsBool(input, "jp2Oneshot");
119+
}
116120
// Create new image
117121
if (HasAttr(input, "createChannels")) {
118122
descriptor->createChannels = AttrAsUint32(input, "createChannels");
@@ -434,6 +438,9 @@ namespace sharp {
434438
if (imageType == ImageType::PDF) {
435439
option->set("background", descriptor->pdfBackground);
436440
}
441+
if (imageType == ImageType::JP2) {
442+
option->set("oneshot", descriptor->jp2Oneshot);
443+
}
437444
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
438445
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
439446
image = SetDensity(image, descriptor->density);
@@ -541,6 +548,9 @@ namespace sharp {
541548
if (imageType == ImageType::PDF) {
542549
option->set("background", descriptor->pdfBackground);
543550
}
551+
if (imageType == ImageType::JP2) {
552+
option->set("oneshot", descriptor->jp2Oneshot);
553+
}
544554
image = VImage::new_from_file(descriptor->file.data(), option);
545555
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
546556
image = SetDensity(image, descriptor->density);

src/common.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ namespace sharp {
7878
VipsAlign joinHalign;
7979
VipsAlign joinValign;
8080
std::vector<double> pdfBackground;
81+
bool jp2Oneshot;
8182

8283
InputDescriptor():
8384
autoOrient(false),
@@ -120,7 +121,8 @@ namespace sharp {
120121
joinBackground{ 0.0, 0.0, 0.0, 255.0 },
121122
joinHalign(VIPS_ALIGN_LOW),
122123
joinValign(VIPS_ALIGN_LOW),
123-
pdfBackground{ 255.0, 255.0, 255.0, 255.0 } {}
124+
pdfBackground{ 255.0, 255.0, 255.0, 255.0 },
125+
jp2Oneshot(false) {}
124126
};
125127

126128
// Convenience methods to access the attributes of a Napi::Object

test/fixtures/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ module.exports = {
117117
inputTiffFogra: getPath('fogra-0-100-100-0.tif'), // https://github.com/lovell/sharp/issues/4045
118118

119119
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
120+
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
120121
inputGif: getPath('Crash_test.gif'), // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif
121122
inputGifGreyPlusAlpha: getPath('grey-plus-alpha.gif'), // http://i.imgur.com/gZ5jlmE.gif
122123
inputGifAnimated: getPath('rotating-squares.gif'), // CC0 https://loading.io/spinner/blocks/-rotating-squares-preloader-gif

test/fixtures/relax_tileparts.jp2

9.98 KB
Binary file not shown.

test/types/sharp.test-d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,9 @@ const color: sharp.Color = '#fff';
721721
sharp({ pdfBackground: colour });
722722
sharp({ pdfBackground: color });
723723

724+
sharp({ jp2Oneshot: true });
725+
sharp({ jp2Oneshot: false });
726+
724727
sharp({ autoOrient: true });
725728
sharp({ autoOrient: false });
726729
sharp().autoOrient();

0 commit comments

Comments
 (0)