From b7fbffb3f7e4854da2d9629950bd3dbb63e26c45 Mon Sep 17 00:00:00 2001 From: Zaruike Date: Sun, 29 Aug 2021 00:02:09 +0200 Subject: [PATCH] Add support for libvips compiled with OpenJPEG --- docs/api-output.md | 41 +++++++++++++++++ lib/constructor.js | 5 ++ lib/output.js | 84 +++++++++++++++++++++++++++++++++- package.json | 4 +- src/common.cc | 8 ++++ src/common.h | 2 + src/pipeline.cc | 36 ++++++++++++++- src/pipeline.h | 10 ++++ src/utilities.cc | 2 +- test/fixtures/index.js | 2 + test/fixtures/relax.jp2 | Bin 0 -> 72580 bytes test/unit/jp2.js | 99 ++++++++++++++++++++++++++++++++++++++++ 12 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/relax.jp2 create mode 100644 test/unit/jp2.js diff --git a/docs/api-output.md b/docs/api-output.md index 391daf664..538b7f902 100644 --- a/docs/api-output.md +++ b/docs/api-output.md @@ -330,6 +330,47 @@ The prebuilt binaries do not include this - see Returns **Sharp** +## jp2 + +Use these JP2 options for output image. + +Requires libvips compiled with support for OpenJPEG. +The prebuilt binaries do not include this - see +[installing a custom libvips][11]. + +### Parameters + +* `options` **[Object][6]?** output options + + * `options.quality` **[number][9]** quality, integer 1-100 (optional, default `80`) + * `options.lossless` **[boolean][7]** use lossless compression mode (optional, default `false`) + * `options.tileWidth` **[number][9]** horizontal tile size (optional, default `512`) + * `options.tileHeight` **[number][9]** vertical tile size (optional, default `512`) + * `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`) + +### Examples + +```javascript +// Convert any input to lossless JP2 output +const data = await sharp(input) + .jp2({ lossless: true }) + .toBuffer(); +``` + +```javascript +// Convert any input to very high quality JP2 output +const data = await sharp(input) + .jp2({ + quality: 100, + chromaSubsampling: '4:4:4' + }) + .toBuffer(); +``` + +* Throws **[Error][4]** Invalid options + +Returns **Sharp** + ## tiff Use these TIFF options for output image. diff --git a/lib/constructor.js b/lib/constructor.js index 661915b77..711221f20 100644 --- a/lib/constructor.js +++ b/lib/constructor.js @@ -235,6 +235,11 @@ const Sharp = function (input, options) { pngQuality: 100, pngBitdepth: 8, pngDither: 1, + jp2Quality: 80, + jp2TileHeight: 512, + jp2TileWidth: 512, + jp2Lossless: false, + jp2ChromaSubsampling: '4:4:4', webpQuality: 80, webpAlphaQuality: 100, webpLossless: false, diff --git a/lib/output.js b/lib/output.js index 80277a3dd..46a37dcf8 100644 --- a/lib/output.js +++ b/lib/output.js @@ -13,10 +13,15 @@ const formats = new Map([ ['raw', 'raw'], ['tiff', 'tiff'], ['webp', 'webp'], - ['gif', 'gif'] + ['gif', 'gif'], + ['jp2', 'jp2'], + ['jpx', 'jp2'], + ['j2k', 'jp2'], + ['j2c', 'jp2'] ]); const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick'); +const errJp2Save = new Error('JP2 output requires libvips with support for OpenJPEG'); /** * Write output image data to a file. @@ -511,6 +516,82 @@ function gif (options) { return this._updateFormatOut('gif', options); } +/** + * Use these JP2 options for output image. + * + * Requires libvips compiled with support for OpenJPEG. + * The prebuilt binaries do not include this - see + * {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}. + * + * @example + * // Convert any input to lossless JP2 output + * const data = await sharp(input) + * .jp2({ lossless: true }) + * .toBuffer(); + * + * @example + * // Convert any input to very high quality JP2 output + * const data = await sharp(input) + * .jp2({ + * quality: 100, + * chromaSubsampling: '4:4:4' + * }) + * .toBuffer(); + * + * @param {Object} [options] - output options + * @param {number} [options.quality=80] - quality, integer 1-100 + * @param {boolean} [options.lossless=false] - use lossless compression mode + * @param {number} [options.tileWidth=512] - horizontal tile size + * @param {number} [options.tileHeight=512] - vertical tile size + * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling + * @returns {Sharp} + * @throws {Error} Invalid options + */ +/* istanbul ignore next */ +function jp2 (options) { + if (!this.constructor.format.jp2k.output.buffer) { + throw errJp2Save; + } + if (is.object(options)) { + if (is.defined(options.quality)) { + if (is.integer(options.quality) && is.inRange(options.quality, 1, 100)) { + this.options.jp2Quality = options.quality; + } else { + throw is.invalidParameterError('quality', 'integer between 1 and 100', options.quality); + } + } + if (is.defined(options.lossless)) { + if (is.bool(options.lossless)) { + this.options.jp2Lossless = options.lossless; + } else { + throw is.invalidParameterError('lossless', 'boolean', options.lossless); + } + } + if (is.defined(options.tileWidth)) { + if (is.integer(options.tileWidth) && is.inRange(options.tileWidth, 1, 32768)) { + this.options.jp2TileWidth = options.tileWidth; + } else { + throw is.invalidParameterError('tileWidth', 'integer between 1 and 32768', options.tileWidth); + } + } + if (is.defined(options.tileHeight)) { + if (is.integer(options.tileHeight) && is.inRange(options.tileHeight, 1, 32768)) { + this.options.jp2TileHeight = options.tileHeight; + } else { + throw is.invalidParameterError('tileHeight', 'integer between 1 and 32768', options.tileHeight); + } + } + if (is.defined(options.chromaSubsampling)) { + if (is.string(options.chromaSubsampling) && is.inArray(options.chromaSubsampling, ['4:2:0', '4:4:4'])) { + this.options.heifChromaSubsampling = options.chromaSubsampling; + } else { + throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling); + } + } + } + return this._updateFormatOut('jp2', options); +} + /** * Set animation options if available. * @private @@ -1035,6 +1116,7 @@ module.exports = function (Sharp) { withMetadata, toFormat, jpeg, + jp2, png, webp, tiff, diff --git a/package.json b/package.json index bc8024e54..daaa4c5bb 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,8 @@ "Jacob Smith ", "Michael Nutt ", "Brad Parham ", - "Taneli Vatanen " + "Taneli Vatanen ", + "Joris Dugué " ], "scripts": { "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)", @@ -112,6 +113,7 @@ "tiff", "gif", "svg", + "jp2", "dzi", "image", "resize", diff --git a/src/common.cc b/src/common.cc index 17e4634e1..a04b23196 100644 --- a/src/common.cc +++ b/src/common.cc @@ -157,6 +157,10 @@ namespace sharp { bool IsGif(std::string const &str) { return EndsWith(str, ".gif") || EndsWith(str, ".GIF"); } + bool IsJp2(std::string const &str) { + return EndsWith(str, ".jp2") || EndsWith(str, ".jpx") || EndsWith(str, ".j2k") || EndsWith(str, ".j2c") + || EndsWith(str, ".JP2") || EndsWith(str, ".JPX") || EndsWith(str, ".J2K") || EndsWith(str, ".J2C"); + } bool IsTiff(std::string const &str) { return EndsWith(str, ".tif") || EndsWith(str, ".tiff") || EndsWith(str, ".TIF") || EndsWith(str, ".TIFF"); } @@ -190,6 +194,7 @@ namespace sharp { case ImageType::WEBP: id = "webp"; break; case ImageType::TIFF: id = "tiff"; break; case ImageType::GIF: id = "gif"; break; + case ImageType::JP2: id = "jp2"; break; case ImageType::SVG: id = "svg"; break; case ImageType::HEIF: id = "heif"; break; case ImageType::PDF: id = "pdf"; break; @@ -226,6 +231,8 @@ namespace sharp { { "VipsForeignLoadGifBuffer", ImageType::GIF }, { "VipsForeignLoadNsgifFile", ImageType::GIF }, { "VipsForeignLoadNsgifBuffer", ImageType::GIF }, + { "VipsForeignLoadJp2kBuffer", ImageType::JP2 }, + { "VipsForeignLoadJp2kFile", ImageType::JP2 }, { "VipsForeignLoadSvgFile", ImageType::SVG }, { "VipsForeignLoadSvgBuffer", ImageType::SVG }, { "VipsForeignLoadHeifFile", ImageType::HEIF }, @@ -287,6 +294,7 @@ namespace sharp { imageType == ImageType::WEBP || imageType == ImageType::MAGICK || imageType == ImageType::GIF || + imageType == ImageType::JP2 || imageType == ImageType::TIFF || imageType == ImageType::HEIF || imageType == ImageType::PDF; diff --git a/src/common.h b/src/common.h index 93d09eb8f..9eaa772a6 100644 --- a/src/common.h +++ b/src/common.h @@ -116,6 +116,7 @@ namespace sharp { JPEG, PNG, WEBP, + JP2, TIFF, GIF, SVG, @@ -142,6 +143,7 @@ namespace sharp { bool IsJpeg(std::string const &str); bool IsPng(std::string const &str); bool IsWebp(std::string const &str); + bool IsJp2(std::string const &str); bool IsGif(std::string const &str); bool IsTiff(std::string const &str); bool IsHeic(std::string const &str); diff --git a/src/pipeline.cc b/src/pipeline.cc index 2a6fb69dd..1ce669988 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -791,6 +791,22 @@ class PipelineWorker : public Napi::AsyncWorker { } else { baton->channels = std::min(baton->channels, 3); } + } else if (baton->formatOut == "jp2" || (baton->formatOut == "input" + && inputImageType == sharp::ImageType::JP2)) { + // Write JP2 to Buffer + sharp::AssertImageTypeDimensions(image, sharp::ImageType::JP2); + VipsArea *area = reinterpret_cast(image.jp2ksave_buffer(VImage::option() + ->set("Q", baton->jp2Quality) + ->set("lossless", baton->jp2Lossless) + ->set("subsample_mode", baton->jp2ChromaSubsampling == "4:4:4" + ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON) + ->set("tile_height", baton->jp2TileHeight) + ->set("tile_width", baton->jp2TileWidth))); + baton->bufferOut = static_cast(area->data); + baton->bufferOutLength = area->length; + area->free_fn = nullptr; + vips_area_unref(area); + baton->formatOut = "jp2"; } else if (baton->formatOut == "png" || (baton->formatOut == "input" && (inputImageType == sharp::ImageType::PNG || (inputImageType == sharp::ImageType::GIF && !supportsGifOutput) || inputImageType == sharp::ImageType::SVG))) { @@ -922,13 +938,14 @@ class PipelineWorker : public Napi::AsyncWorker { bool const isWebp = sharp::IsWebp(baton->fileOut); bool const isGif = sharp::IsGif(baton->fileOut); bool const isTiff = sharp::IsTiff(baton->fileOut); + bool const isJp2 = sharp::IsJp2(baton->fileOut); bool const isHeif = sharp::IsHeif(baton->fileOut); bool const isDz = sharp::IsDz(baton->fileOut); bool const isDzZip = sharp::IsDzZip(baton->fileOut); bool const isV = sharp::IsV(baton->fileOut); bool const mightMatchInput = baton->formatOut == "input"; bool const willMatchInput = mightMatchInput && - !(isJpeg || isPng || isWebp || isGif || isTiff || isHeif || isDz || isDzZip || isV); + !(isJpeg || isPng || isWebp || isGif || isTiff || isJp2 || isHeif || isDz || isDzZip || isV); if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) || (willMatchInput && inputImageType == sharp::ImageType::JPEG)) { @@ -948,6 +965,18 @@ class PipelineWorker : public Napi::AsyncWorker { ->set("optimize_coding", baton->jpegOptimiseCoding)); baton->formatOut = "jpeg"; baton->channels = std::min(baton->channels, 3); + } else if (baton->formatOut == "jp2" || (mightMatchInput && isJp2) || + (willMatchInput && (inputImageType == sharp::ImageType::JP2))) { + // Write JP2 to file + sharp::AssertImageTypeDimensions(image, sharp::ImageType::JP2); + image.jp2ksave(const_cast(baton->fileOut.data()), VImage::option() + ->set("Q", baton->jp2Quality) + ->set("lossless", baton->jp2Lossless) + ->set("subsample_mode", baton->jp2ChromaSubsampling == "4:4:4" + ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON) + ->set("tile_height", baton->jp2TileHeight) + ->set("tile_width", baton->jp2TileWidth)); + baton->formatOut = "jp2"; } else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput && (inputImageType == sharp::ImageType::PNG || (inputImageType == sharp::ImageType::GIF && !supportsGifOutput) || inputImageType == sharp::ImageType::SVG))) { @@ -1438,6 +1467,11 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) { baton->pngQuality = sharp::AttrAsUint32(options, "pngQuality"); baton->pngBitdepth = sharp::AttrAsUint32(options, "pngBitdepth"); baton->pngDither = sharp::AttrAsDouble(options, "pngDither"); + baton->jp2Quality = sharp::AttrAsUint32(options, "jp2Quality"); + baton->jp2Lossless = sharp::AttrAsBool(options, "jp2Lossless"); + baton->jp2TileHeight = sharp::AttrAsUint32(options, "jp2TileHeight"); + baton->jp2TileWidth = sharp::AttrAsUint32(options, "jp2TileWidth"); + baton->jp2ChromaSubsampling = sharp::AttrAsStr(options, "jp2ChromaSubsampling"); baton->webpQuality = sharp::AttrAsUint32(options, "webpQuality"); baton->webpAlphaQuality = sharp::AttrAsUint32(options, "webpAlphaQuality"); baton->webpLossless = sharp::AttrAsBool(options, "webpLossless"); diff --git a/src/pipeline.h b/src/pipeline.h index ec9bf8dcb..2c2f1ee94 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -149,6 +149,11 @@ struct PipelineBaton { int pngQuality; int pngBitdepth; double pngDither; + int jp2Quality; + bool jp2Lossless; + int jp2TileHeight; + int jp2TileWidth; + std::string jp2ChromaSubsampling; int webpQuality; int webpAlphaQuality; bool webpNearLossless; @@ -280,6 +285,11 @@ struct PipelineBaton { pngQuality(100), pngBitdepth(8), pngDither(1.0), + jp2Quality(80), + jp2Lossless(false), + jp2TileHeight(512), + jp2TileWidth(512), + jp2ChromaSubsampling("4:4:4"), webpQuality(80), webpAlphaQuality(100), webpNearLossless(false), diff --git a/src/utilities.cc b/src/utilities.cc index ed36d76d5..37c1cefd3 100644 --- a/src/utilities.cc +++ b/src/utilities.cc @@ -115,7 +115,7 @@ Napi::Value format(const Napi::CallbackInfo& info) { Napi::Object format = Napi::Object::New(env); for (std::string const f : { "jpeg", "png", "webp", "tiff", "magick", "openslide", "dz", - "ppm", "fits", "gif", "svg", "heif", "pdf", "vips" + "ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k" }) { // Input Napi::Boolean hasInputFile = diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 9e8b019a7..e486934af 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -105,6 +105,8 @@ module.exports = { inputTiffUncompressed: getPath('uncompressed_tiff.tiff'), // https://code.google.com/archive/p/imagetestsuite/wikis/TIFFTestSuite.wiki file: 0c84d07e1b22b76f24cccc70d8788e4a.tif inputTiff8BitDepth: getPath('8bit_depth.tiff'), inputTifftagPhotoshop: getPath('tifftag-photoshop.tiff'), // https://github.com/lovell/sharp/issues/1600 + + inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2 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 diff --git a/test/fixtures/relax.jp2 b/test/fixtures/relax.jp2 new file mode 100644 index 0000000000000000000000000000000000000000..1823990f4a301a0c56880948363cb65337a02342 GIT binary patch literal 72580 zcmV(~K+nJbPybN>F8}}l00BS%008g+0000000000009610096100000000000|x;C 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 So9LL+XdzR09i(Nk_W#*=iCVD$ literal 0 HcmV?d00001 diff --git a/test/unit/jp2.js b/test/unit/jp2.js new file mode 100644 index 000000000..d30987c3d --- /dev/null +++ b/test/unit/jp2.js @@ -0,0 +1,99 @@ +'use strict'; + +const fs = require('fs'); +const assert = require('assert'); + +const sharp = require('../../'); +const fixtures = require('../fixtures'); + +describe('JP2 output', () => { + if (!sharp.format.jp2k.input.buffer) { + it('JP2 output should fail due to missing OpenJPEG', () => { + assert.rejects(() => + sharp(fixtures.inputJpg) + .jp2() + .toBuffer(), + /JP2 output requires libvips with support for OpenJPEG/ + ); + }); + + it('JP2 file output should fail due to missing OpenJPEG', () => { + assert.rejects(async () => await sharp().toFile('test.jp2'), + /JP2 output requires libvips with support for OpenJPEG/ + ); + }); + } else { + it('JP2 Buffer to PNG Buffer', () => { + sharp(fs.readFileSync(fixtures.inputJp2)) + .resize(8, 15) + .png() + .toBuffer({ resolveWithObject: true }) + .then(({ data, info }) => { + assert.strictEqual(true, data.length > 0); + assert.strictEqual(data.length, info.size); + assert.strictEqual('png', info.format); + assert.strictEqual(8, info.width); + assert.strictEqual(15, info.height); + assert.strictEqual(4, info.channels); + }); + }); + + it('JP2 quality', function (done) { + sharp(fixtures.inputJp2) + .resize(320, 240) + .jp2({ quality: 70 }) + .toBuffer(function (err, buffer70) { + if (err) throw err; + sharp(fixtures.inputJp2) + .resize(320, 240) + .toBuffer(function (err, buffer80) { + if (err) throw err; + sharp(fixtures.inputJp2) + .resize(320, 240) + .jp2({ quality: 90 }) + .toBuffer(function (err, buffer90) { + if (err) throw err; + assert(buffer70.length < buffer80.length); + assert(buffer80.length < buffer90.length); + done(); + }); + }); + }); + }); + + it('Without chroma subsampling generates larger file', function (done) { + // First generate with chroma subsampling (default) + sharp(fixtures.inputJp2) + .resize(320, 240) + .jp2({ chromaSubsampling: '4:2:0' }) + .toBuffer(function (err, withChromaSubsamplingData, withChromaSubsamplingInfo) { + if (err) throw err; + assert.strictEqual(true, withChromaSubsamplingData.length > 0); + assert.strictEqual(withChromaSubsamplingData.length, withChromaSubsamplingInfo.size); + assert.strictEqual('jp2', withChromaSubsamplingInfo.format); + assert.strictEqual(320, withChromaSubsamplingInfo.width); + assert.strictEqual(240, withChromaSubsamplingInfo.height); + // Then generate without + sharp(fixtures.inputJp2) + .resize(320, 240) + .jp2({ chromaSubsampling: '4:4:4' }) + .toBuffer(function (err, withoutChromaSubsamplingData, withoutChromaSubsamplingInfo) { + if (err) throw err; + assert.strictEqual(true, withoutChromaSubsamplingData.length > 0); + assert.strictEqual(withoutChromaSubsamplingData.length, withoutChromaSubsamplingInfo.size); + assert.strictEqual('jp2', withoutChromaSubsamplingInfo.format); + assert.strictEqual(320, withoutChromaSubsamplingInfo.width); + assert.strictEqual(240, withoutChromaSubsamplingInfo.height); + assert.strictEqual(true, withChromaSubsamplingData.length <= withoutChromaSubsamplingData.length); + done(); + }); + }); + }); + + it('Invalid JP2 chromaSubsampling value throws error', function () { + assert.throws(function () { + sharp().jpeg({ chromaSubsampling: '4:2:2' }); + }); + }); + } +});