Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for libvips JPEG 2000 one-shot load option #4262

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api-constructor.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ where the overall height is the `pageHeight` multiplied by the number of `pages`
| [options.subifd] | <code>number</code> | <code>-1</code> | subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image. |
| [options.level] | <code>number</code> | <code>0</code> | level to extract from a multi-level input (OpenSlide), zero based. |
| [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. |
| [options.jp2Oneshot] | <code>boolean</code> | <code>false</code> | Set to `true` to load JPEG 2000 images using [oneshot mode](https://github.com/libvips/libvips/issues/4205)|
| [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`. |
| [options.raw] | <code>Object</code> | | describes raw pixel input image data. See `raw()` for pixel ordering. |
| [options.raw.width] | <code>number</code> | | integral number of pixels wide. |
Expand Down
2 changes: 2 additions & 0 deletions lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ const debuglog = util.debuglog('sharp');
* @param {number} [options.subifd=-1] - subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image.
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.
* @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.
* @param {boolean} [options.jp2Oneshot=false] - Set to `true` to load JPEG 2000 images using [oneshot mode](https://github.com/libvips/libvips/issues/4205)
* @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`.
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
* @param {number} [options.raw.width] - integral number of pixels wide.
Expand Down Expand Up @@ -295,6 +296,7 @@ const Sharp = function (input, options) {
jp2TileWidth: 512,
jp2Lossless: false,
jp2ChromaSubsampling: '4:4:4',
jp2Oneshot: false,
webpQuality: 80,
webpAlphaQuality: 100,
webpLossless: false,
Expand Down
2 changes: 2 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,8 @@ declare namespace sharp {
/** 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. */
pdfBackground?: Colour | Color | undefined;
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
jp2Oneshot?: boolean | undefined;
/** Set to `true` to load JPEG 2000 images using [oneshot mode](https://github.com/libvips/libvips/issues/4205) **/
animated?: boolean | undefined;
/** Describes raw pixel input image data. See raw() for pixel ordering. */
raw?: CreateRaw | undefined;
Expand Down
18 changes: 14 additions & 4 deletions lib/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const align = {
* @private
*/
function _inputOptionsFromObject (obj) {
const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground } = obj;
return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground].some(is.defined)
? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground }
const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, jp2Oneshot } = obj;
return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, jp2Oneshot].some(is.defined)
? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, jp2Oneshot }
: undefined;
}

Expand All @@ -40,7 +40,8 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
limitInputPixels: Math.pow(0x3FFF, 2),
ignoreIcc: false,
unlimited: false,
sequentialRead: true
sequentialRead: true,
jp2Oneshot: false
};
if (is.string(input)) {
// filesystem
Expand Down Expand Up @@ -226,6 +227,15 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
if (is.defined(inputOptions.pdfBackground)) {
this._setBackgroundColourOption('pdfBackground', inputOptions.pdfBackground);
}

if (is.defined(inputOptions.jp2Oneshot)) {
if (is.bool(inputOptions.jp2Oneshot)) {
inputDescriptor.jp2Oneshot = inputOptions.jp2Oneshot;
} else {
throw is.invalidParameterError('jp2Oneshot', 'boolean', inputOptions.jp2Oneshot);
}
}

// Create new image
if (is.defined(inputOptions.create)) {
if (
Expand Down
11 changes: 11 additions & 0 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ namespace sharp {
if (HasAttr(input, "pdfBackground")) {
descriptor->pdfBackground = AttrAsVectorOfDouble(input, "pdfBackground");
}
// Use JPEG 2000 oneshot mode?
if (HasAttr(input, "jp2Oneshot")) {
descriptor->jp2Oneshot = AttrAsBool(input, "jp2Oneshot");
}

// Create new image
if (HasAttr(input, "createChannels")) {
descriptor->createChannels = AttrAsUint32(input, "createChannels");
Expand Down Expand Up @@ -409,6 +414,9 @@ namespace sharp {
if (imageType == ImageType::PDF) {
option->set("background", descriptor->pdfBackground);
}
if (imageType == ImageType::JP2 && descriptor->jp2Oneshot) {
option->set("oneshot", 1);
}
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
image = SetDensity(image, descriptor->density);
Expand Down Expand Up @@ -516,6 +524,9 @@ namespace sharp {
if (imageType == ImageType::PDF) {
option->set("background", descriptor->pdfBackground);
}
if (imageType == ImageType::JP2 && descriptor->jp2Oneshot) {
option->set("oneshot", 1);
}
image = VImage::new_from_file(descriptor->file.data(), option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
image = SetDensity(image, descriptor->density);
Expand Down
4 changes: 3 additions & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace sharp {
VipsTextWrap textWrap;
int textAutofitDpi;
std::vector<double> pdfBackground;
bool jp2Oneshot;

InputDescriptor():
buffer(nullptr),
Expand Down Expand Up @@ -110,7 +111,8 @@ namespace sharp {
textSpacing(0),
textWrap(VIPS_TEXT_WRAP_WORD),
textAutofitDpi(0),
pdfBackground{ 255.0, 255.0, 255.0, 255.0 } {}
pdfBackground{ 255.0, 255.0, 255.0, 255.0 },
jp2Oneshot(false) {}
};

// Convenience methods to access the attributes of a Napi::Object
Expand Down
Loading