From 539f7f32099645cf3e0dac09f3ef78dab15f9c1a Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Sat, 16 Jul 2016 23:50:48 -0400 Subject: [PATCH 1/9] Add feature toColourspace / toColorspace to write output in desired colorspace Add feature joinChannels to add additional image channels to the input image --- docs/api.md | 26 +++- index.js | 65 ++++++++++ src/common.cc | 9 ++ src/common.h | 5 + src/pipeline.cc | 121 ++++++++++++++++-- src/pipeline.h | 5 + test/fixtures/expected/joinChannel-cmyk.jpg | Bin 0 -> 35683 bytes test/fixtures/expected/joinChannel-rgb.jpg | Bin 0 -> 17875 bytes test/fixtures/expected/joinChannel-rgba.png | Bin 0 -> 43013 bytes .../expected/output.greyscale-single.jpg | Bin 0 -> 12807 bytes test/fixtures/index.js | 1 + test/fixtures/stripesH.png | Bin 502 -> 338 bytes test/fixtures/stripesV.png | Bin 624 -> 418 bytes test/fixtures/testJoinChannel.png | Bin 0 -> 756 bytes test/unit/colourspace.js | 14 ++ test/unit/joinChannel.js | 116 +++++++++++++++++ 16 files changed, 345 insertions(+), 17 deletions(-) create mode 100644 test/fixtures/expected/joinChannel-cmyk.jpg create mode 100644 test/fixtures/expected/joinChannel-rgb.jpg create mode 100644 test/fixtures/expected/joinChannel-rgba.png create mode 100644 test/fixtures/expected/output.greyscale-single.jpg create mode 100644 test/fixtures/testJoinChannel.png create mode 100644 test/unit/joinChannel.js diff --git a/docs/api.md b/docs/api.md index 0d872b526..7dc5d1704 100644 --- a/docs/api.md +++ b/docs/api.md @@ -60,7 +60,7 @@ Fast access to image metadata without decoding any compressed image data. * `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg` * `width`: Number of pixels wide * `height`: Number of pixels high -* `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `scrgb`, `cmyk`, `lab`, `xyz`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L522) +* `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `scrgb`, `cmyk`, `lab`, `xyz`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568) * `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK * `density`: Number of pixels per inch (DPI), if present * `hasProfile`: Boolean indicating the presence of an embedded ICC profile @@ -445,7 +445,7 @@ Convert to 8-bit greyscale; 256 shades of grey. This is a linear operation. If the input image is in a non-linear colour space such as sRGB, use `gamma()` with `greyscale()` for the best results. -The output image will still be web-friendly sRGB and contain three (identical) channels. +By default the output image will be web-friendly sRGB and contain three (identical) color channels. This may be overridden by other sharp operations such as `toColourspace('b-w')`, which will produce an output image containing one color channel. An alpha channel may be present, and will be unchanged by the operation. #### normalize() / normalise() @@ -489,11 +489,17 @@ sharp('input.png') }); ``` +#### toColourspace(colourspace) / toColorspace(colorspace) + +Set the output colourspace. By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels. + +`colourspace` is a string or `sharp.colourspace` enum that identifies an output colourspace. String arguments comprise vips colour space interpretation names e.g. `srgb`, `rgb`, `scrgb`, `cmyk`, `lab`, `xyz`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568) + #### extractChannel(channel) Extract a single channel from a multi-channel image. -* `channel` is a zero-indexed integral Number representing the band number to extract. `red`, `green` or `blue` are also accepted as an alternative to `0`, `1` or `2` respectively. +`channel` is a zero-indexed integral Number representing the band number to extract. `red`, `green` or `blue` are also accepted as an alternative to `0`, `1` or `2` respectively. ```javascript sharp(input) @@ -504,6 +510,20 @@ sharp(input) }); ``` +#### joinChannel(channels) + +Join a data channel to the image. The meaning of the added channels depends on the output colourspace, set with `toColourspace()`. By default output will be web-friendly sRGB, with additional channels interpreted as alpha channels. + +`channels` is one of +* a single file path +* an array of file paths +* a single buffer +* an array of buffers + +Note that channel ordering follows vips convention: +* sRGB: 0: Red, 1: Green, 2: Blue, 3: Alpha +* CMYK: 0: Magenta, 1: Cyan, 2: Yellow, 3: Black, 4: Alpha + #### bandbool(operation) Perform a bitwise boolean operation on all input image channels (bands) to produce a single channel output image. diff --git a/index.js b/index.js index 941f7e191..502a58249 100644 --- a/index.js +++ b/index.js @@ -92,6 +92,8 @@ var Sharp = function(input, options) { normalize: 0, booleanBufferIn: null, booleanFileIn: '', + joinChannelBuffersIn: [], + joinChannelFilesIn: [], // overlay overlayFileIn: '', overlayBufferIn: null, @@ -117,6 +119,7 @@ var Sharp = function(input, options) { tileSize: 256, tileOverlap: 0, extractChannel: -1, + outputMode: 'srgb', // Function to notify of queue length changes queueListener: function(queueLength) { module.exports.queue.emit('change', queueLength); @@ -435,6 +438,47 @@ Sharp.prototype.overlayWith = function(overlay, options) { return this; }; +/* + Add another color channel to the image +*/ +Sharp.prototype.joinChannel = function(images) { + if (Array.isArray(images)) { + // Array of image file names or buffers, not mixed + var type = images.reduce(function(prev, curr) { + if((isBuffer(prev) && isBuffer(curr)) || (isString(prev) && isString(curr))) + return prev; + return false; + }); + if (isString(type)) { + // Array of files input + if(this.options.joinChannelBuffersIn.length > 0) + throw new Error('Already joining buffers'); + this.options.joinChannelFilesIn = this.options.joinChannelFilesIn.concat(images); + } else if (isBuffer(type)) { + // Array of buffers input + if(this.options.joinChannelFilesIn.length > 0) + throw new Error('Already joining files'); + this.options.joinChannelBuffersIn = this.options.joinChannelBuffersIn.concat(images); + } else { + // Mixed input or non-string or non-buffer input + throw new Error('Invalid input array to joinChannel'); + } + } else if (isString(images)) { + // File input + if(this.options.joinChannelBuffersIn.length > 0) + throw new Error('Already joining buffers'); + this.options.joinChannelFilesIn.push(images); + } else if (isBuffer(images)) { + // Buffer input + if(this.options.joinChannelFilesIn.length > 0) + throw new Error('Already joining files'); + this.options.joinChannelBuffersIn.push(images); + } else { + throw new Error('Invalid input to joinChannel'); + } + return this; +}; + /* Rotate output image by 0, 90, 180 or 270 degrees Auto-rotation based on the EXIF Orientation tag is represented by an angle of -1 @@ -643,6 +687,19 @@ Sharp.prototype.greyscale = function(greyscale) { }; Sharp.prototype.grayscale = Sharp.prototype.greyscale; + +/* + Set output colourspace +*/ +Sharp.prototype.toColourspace = function(colourspace) { + if (!isString(colourspace) ) { + throw new Error('Invalid output colourspace ' + colourspace); + } + this.options.outputMode = colourspace; + return this; +}; +Sharp.prototype.toColorspace = Sharp.prototype.toColourspace; + Sharp.prototype.progressive = function(progressive) { this.options.progressive = isBoolean(progressive) ? progressive : true; return this; @@ -831,6 +888,14 @@ module.exports.bool = { or: 'or', eor: 'eor' }; +// Colourspaces +module.exports.colourspace = { + multiband: 'multiband', + 'b-w': 'b-w', + bw: 'b-w', + cmyk: 'cmyk', + srgb: 'srgb' +}; /* Resize image to width x height pixels diff --git a/src/common.cc b/src/common.cc index baec435e0..b24b3e7d9 100644 --- a/src/common.cc +++ b/src/common.cc @@ -342,4 +342,13 @@ namespace sharp { ); } + /* + Get interpretation type from string + */ + VipsInterpretation GetInterpretation(std::string const typeStr) { + return static_cast( + vips_enum_from_nick(nullptr, VIPS_TYPE_INTERPRETATION, typeStr.data()) + ); + } + } // namespace sharp diff --git a/src/common.h b/src/common.h index e931e4601..db74f1b77 100644 --- a/src/common.h +++ b/src/common.h @@ -133,6 +133,11 @@ namespace sharp { */ VipsOperationBoolean GetBooleanOperation(std::string const opStr); + /* + Get interpretation type from string + */ + VipsInterpretation GetInterpretation(std::string const typeStr); + } // namespace sharp #endif // SRC_COMMON_H_ diff --git a/src/pipeline.cc b/src/pipeline.cc index 782237500..d1a1b8065 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -81,6 +82,7 @@ using sharp::CalculateCrop; using sharp::Is16Bit; using sharp::MaximumImageAlpha; using sharp::GetBooleanOperation; +using sharp::GetInterpretation; using sharp::counterProcess; using sharp::counterQueue; @@ -110,12 +112,20 @@ class PipelineWorker : public AsyncWorker { // Increment processing task counter g_atomic_int_inc(&counterProcess); + std::unordered_map profileMap; // Default sRGB ICC profile from https://packages.debian.org/sid/all/icc-profiles-free/filelist - std::string srgbProfile = baton->iccProfilePath + "sRGB.icc"; + profileMap.insert( + std::pair(VIPS_INTERPRETATION_sRGB, + baton->iccProfilePath + "sRGB.icc")); + // Convert to sRGB using default CMYK profile from http://www.argyllcms.com/cmyk.icm + profileMap.insert( + std::pair(VIPS_INTERPRETATION_CMYK, + baton->iccProfilePath + "cmyk.icm")); // Input ImageType inputImageType = ImageType::UNKNOWN; VImage image; + if (baton->bufferInLength > 0) { // From buffer if (baton->rawWidth > 0 && baton->rawHeight > 0 && baton->rawChannels > 0) { @@ -222,6 +232,7 @@ class PipelineWorker : public AsyncWorker { image = Trim(image, baton->trimTolerance); } + // Pre extraction if (baton->topOffsetPre != -1) { image = image.extract_area(baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre); @@ -395,7 +406,8 @@ class PipelineWorker : public AsyncWorker { if (HasProfile(image)) { // Convert to sRGB using embedded profile try { - image = image.icc_transform(const_cast(srgbProfile.data()), VImage::option() + image = image.icc_transform( + const_cast(profileMap[VIPS_INTERPRETATION_sRGB].data()), VImage::option() ->set("embedded", TRUE) ->set("intent", VIPS_INTENT_PERCEPTUAL) ); @@ -403,10 +415,9 @@ class PipelineWorker : public AsyncWorker { // Ignore failure of embedded profile } } else if (image.interpretation() == VIPS_INTERPRETATION_CMYK) { - // Convert to sRGB using default CMYK profile from http://www.argyllcms.com/cmyk.icm - std::string cmykProfile = baton->iccProfilePath + "cmyk.icm"; - image = image.icc_transform(const_cast(srgbProfile.data()), VImage::option() - ->set("input_profile", cmykProfile.data()) + image = image.icc_transform( + const_cast(profileMap[VIPS_INTERPRETATION_sRGB].data()), VImage::option() + ->set("input_profile", profileMap[VIPS_INTERPRETATION_CMYK].data()) ->set("intent", VIPS_INTENT_PERCEPTUAL) ); } @@ -549,6 +560,55 @@ class PipelineWorker : public AsyncWorker { RemoveExifOrientation(image); } + // Join additional color channels to the image + if(baton->joinChannelFilesIn.size() > 0 || baton->joinChannelBuffersIn.size() > 0) { + ImageType joinImageType = ImageType::UNKNOWN; + VImage joinImage; + if (baton->joinChannelBuffersIn.size() > 0 && + baton->joinChannelBuffersIn.size() == baton->joinChannelBuffersInLength.size()) { + // Joining with buffers + for(unsigned int i = 0; i < baton->joinChannelBuffersIn.size(); i++) { + joinImageType = DetermineImageType(baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i]); + if (joinImageType != ImageType::UNKNOWN) { + try { + joinImage = VImage::new_from_buffer( + baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i], + nullptr, VImage::option()->set("access", baton->accessMethod)); + image = image.bandjoin(joinImage); + } catch (...) { + (baton->err).append("Join Channel buffer has corrupt header"); + joinImageType = ImageType::UNKNOWN; + } + } else { + (baton->err).append("Join Channel buffer contains unsupported image format"); + } + } + } else if (baton->joinChannelFilesIn.size() > 0) { + // Joining with files + for(std::string joinChannelFileIn : baton->joinChannelFilesIn) { + joinImageType = DetermineImageType(joinChannelFileIn.data()); + if (joinImageType != ImageType::UNKNOWN) { + try { + joinImage = VImage::new_from_file( + joinChannelFileIn.data(), + VImage::option()->set("access", baton->accessMethod)); + image = image.bandjoin(joinImage); + } catch (...) { + (baton->err).append("Join channel file has corrupt header"); + joinImageType = ImageType::UNKNOWN; + } + } else { + (baton->err).append("Join channel file contains unsupported image format"); + } + } + } + if(joinImageType == ImageType::UNKNOWN) { + return Error(); + } else { + image = image.copy(VImage::option()->set("interpretation", baton->outputMode)); + } + } + // Crop/embed if (image.width() != baton->width || image.height() != baton->height) { if (baton->canvas == Canvas::EMBED) { @@ -802,7 +862,10 @@ class PipelineWorker : public AsyncWorker { VImage::option()->set("access", baton->accessMethod)); } catch (...) { (baton->err).append("Boolean operation file has corrupt header"); + booleanImageType = ImageType::UNKNOWN; } + } else { + (baton->err).append("Boolean operation file contains unsupported image format"); } } if (booleanImageType == ImageType::UNKNOWN) { @@ -826,16 +889,19 @@ class PipelineWorker : public AsyncWorker { image = image.extract_band(baton->extractChannel); } - // Convert image to sRGB, if not already + // Convert image to output profile, if not already if (Is16Bit(image.interpretation())) { image = image.cast(VIPS_FORMAT_USHORT); } - if (image.interpretation() != VIPS_INTERPRETATION_sRGB) { - image = image.colourspace(VIPS_INTERPRETATION_sRGB); - // Transform colours from embedded profile to sRGB profile - if (baton->withMetadata && HasProfile(image)) { - image = image.icc_transform(const_cast(srgbProfile.data()), VImage::option() - ->set("embedded", TRUE) + if (image.interpretation() != baton->outputMode) { + // Need to convert image + image = image.colourspace(baton->outputMode); + // Transform colours from embedded profile to output profile + if (baton->withMetadata && + HasProfile(image) && + profileMap[baton->outputMode] != std::string()) { + image = image.icc_transform(const_cast(profileMap[baton->outputMode].data()), + VImage::option()->set("embedded", TRUE) ); } } @@ -869,7 +935,11 @@ class PipelineWorker : public AsyncWorker { area->free_fn = nullptr; vips_area_unref(area); baton->formatOut = "jpeg"; - baton->channels = std::min(baton->channels, 3); + if(baton->outputMode == VIPS_INTERPRETATION_CMYK) { + baton->channels = std::min(baton->channels, 4); + } else { + baton->channels = std::min(baton->channels, 3); + } } else if (baton->formatOut == "png" || (baton->formatOut == "input" && inputImageType == ImageType::PNG)) { // Write PNG to buffer VipsArea *area = VIPS_AREA(image.pngsave_buffer(VImage::option() @@ -1001,6 +1071,7 @@ class PipelineWorker : public AsyncWorker { } catch (VError const &err) { (baton->err).append(err.what()); } + // Clean up libvips' per-request data and threads vips_error_clear(); vips_thread_shutdown(); @@ -1217,6 +1288,25 @@ NAN_METHOD(pipeline) { baton->crop = attrAs(options, "crop"); baton->kernel = attrAsStr(options, "kernel"); baton->interpolator = attrAsStr(options, "interpolator"); + // Join Channel Options + Local joinChannelFilesObject = Get(options, New("joinChannelFilesIn").ToLocalChecked()) + .ToLocalChecked().As(); + Local joinChannelFilesArray = joinChannelFilesObject.As(); + int joinChannelFilesArrayLength = attrAs(joinChannelFilesObject, "length"); + for(int i = 0; i < joinChannelFilesArrayLength; i++) { + baton->joinChannelFilesIn.push_back(*Utf8String(Get(joinChannelFilesArray, i).ToLocalChecked())); + } + Local joinChannelBuffersObject = Get(options, New("joinChannelBuffersIn").ToLocalChecked()) + .ToLocalChecked().As(); + Local joinChannelBuffersArray = joinChannelBuffersObject.As(); + int joinChannelBuffersArrayLength = attrAs(joinChannelBuffersObject, "length"); + for(int i = 0; i < joinChannelBuffersArrayLength; i++) { + Local joinChannelBufferIn = Get(joinChannelBuffersArray, i).ToLocalChecked().As(); + size_t joinChannelBufferLength = node::Buffer::Length(joinChannelBufferIn); + baton->joinChannelBuffersInLength.push_back(joinChannelBufferLength); + baton->joinChannelBuffersIn.push_back(node::Buffer::Data(joinChannelBufferIn)); + buffersToPersist.push_back(joinChannelBufferIn); + } // Operators baton->flatten = attrAs(options, "flatten"); baton->negate = attrAs(options, "negate"); @@ -1253,6 +1343,9 @@ NAN_METHOD(pipeline) { baton->optimiseScans = attrAs(options, "optimiseScans"); baton->withMetadata = attrAs(options, "withMetadata"); baton->withMetadataOrientation = attrAs(options, "withMetadataOrientation"); + baton->outputMode = GetInterpretation(attrAsStr(options, "outputMode")); + if(baton->outputMode == VIPS_INTERPRETATION_ERROR) + baton->outputMode = VIPS_INTERPRETATION_sRGB; // Output baton->formatOut = attrAsStr(options, "formatOut"); baton->fileOut = attrAsStr(options, "fileOut"); diff --git a/src/pipeline.h b/src/pipeline.h index 68961fd5d..e7457c267 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -42,6 +42,9 @@ struct PipelineBaton { std::string booleanFileIn; char *booleanBufferIn; size_t booleanBufferInLength; + std::vector joinChannelFilesIn; + std::vector joinChannelBuffersIn; + std::vector joinChannelBuffersInLength; int topOffsetPre; int leftOffsetPre; int widthPre; @@ -99,6 +102,7 @@ struct PipelineBaton { VipsOperationBoolean bandBoolOp; VipsOperationBoolean booleanOp; int extractChannel; + VipsInterpretation outputMode; int tileSize; int tileOverlap; VipsForeignDzContainer tileContainer; @@ -163,6 +167,7 @@ struct PipelineBaton { bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST), booleanOp(VIPS_OPERATION_BOOLEAN_LAST), extractChannel(-1), + outputMode(VIPS_INTERPRETATION_LAST), tileSize(256), tileOverlap(0), tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS), diff --git a/test/fixtures/expected/joinChannel-cmyk.jpg b/test/fixtures/expected/joinChannel-cmyk.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6c0fe42121e4b81b597e2a992d8ec8c016e12efb GIT binary patch literal 35683 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%0AY*T!` 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 66facc286..5ee799e16 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -80,6 +80,7 @@ module.exports = { inputPngAlphaPremultiplicationSmall: getPath('alpha-premultiply-1024x768-paper.png'), inputPngAlphaPremultiplicationLarge: getPath('alpha-premultiply-2048x1536-paper.png'), inputPngBooleanNoAlpha: getPath('bandbool.png'), + inputPngTestJoinChannel: getPath('testJoinChannel.png'), inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp diff --git a/test/fixtures/stripesH.png b/test/fixtures/stripesH.png index f0cff675b91f19b428eec5244f7cea0c2bfd455f..d2227e3ce1ebcaf5ba951ba06c2e72bcd0810e23 100644 GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX3pEh7h+$+kq5kfk$L90|U1(2s1Lwnj--e zWH0gbb!C6R&MzRWG^6TX5>V))r;B4q#jUrO90eH|I1X=k7;hqc@T0fNmstfys~P!@ zG(K>U;h>zd2w;}!U_RJrAwW4*xPZ+I%kPY%6$xo@elM^>bP0 Hl+XkKeBEJi literal 502 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX5Ps$$$P@Hb9EAz$3Dlfq`2Xgc%uT&5-~K zvX^-Jy0SlDlNA=z(tEJ#1yJKuPZ!6Kid%25ZscWP;5fYD)BlT4+09gbx9E5_Y+tsP zi{Zfm5Ncp%1|kMN9uTrH03nD3xpEK#v71R)4(bpzw?Om}AqVjQ+z%-F2+L9C@dpPW efr!WLGP-&v(iOPo#c2ZLjKR~@&t;ucLK6Vwr*?q= diff --git a/test/fixtures/stripesV.png b/test/fixtures/stripesV.png index d4482e957cb6e984211a7197a76c7a087095b1c4..9c015ee022c25c7aecc81db42712103839b72a20 100644 GIT binary patch literal 418 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX3pEh7h+$+kq5kfk$L90|U1(2s1Lwnj--e zWH0gbb!C6R&MzQrD05`~9-u}?PZ!6Kid%0l7z#2la4>I_`)AwCJZ;_2@(DS2Yyw3c z8WEoP8wf zccJ=$XeKsBW+pZk9uVe`5HJ8?g#-|GIMC4G2*iva1=tih93Wp2hXk^9Fq0S=n~|*} zNfFG^5I4b1g82+$9Z8B{-iNvgZqgejNbsQ91PLOTn@O?>%_O)@;243Kgu^-5qYTZ> dAVoX2M_+%ycW3>XkHFNz;OXk;vd$@?2>_XueNO-Y diff --git a/test/fixtures/testJoinChannel.png b/test/fixtures/testJoinChannel.png new file mode 100644 index 0000000000000000000000000000000000000000..888ce6a9b328887ddf6b06682ec3440d054b26dd GIT binary patch literal 756 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX3pEh7h+$+kq5kfk$L90|U1(2s1Lwnj--e zWH0gbb!C6R&MzR$w`$R*Mxc;vW=KSdbAE1aYF-JD%fR4Vl$uzQnxasiS(2gP?&%wl zqL<3fz`&H{>EaktaqI1!jfF9WJg$LncNnt2^VHp;qkem`k!AU#2aQkE3-Va!7`rqv ztnZip{patD<$rbvefay8J3;uMH{*Qe3hf8UEbCcox*qIp;1}E@@jju+@B?mvy9id z%h+S|ZpamEO{hO`w27JFI+q_qjFtsc!O{mj2U?q)8Lo5sF~+D_uoX;wAalUAshQzA zhaXdnk_A^m>jRwwtWAd*Ub8M|oW|Y9yhdyedxVaKz=p5_rG%9aJPvproY??0g7G!W za;9mVeXMJQ=5R--SV(MeD=)_1>*6-}?%+J2FFK0d$Y$InN$|AwV#KX$i z*2LiK*sxIHK!8Ak28V$NeT22mxqs!)zyH5QMMOo2i;0u9vZcww$x&*dLQlX1SB(xO z5fwqMCJt81mL>@&N3MkmEddvtOke#?Qt+IlLIM*1Dt={C)6$hvHfKP|(bLt>Wt~$( F699J}0XhHx literal 0 HcmV?d00001 diff --git a/test/unit/colourspace.js b/test/unit/colourspace.js index 2582516e8..b7de36405 100644 --- a/test/unit/colourspace.js +++ b/test/unit/colourspace.js @@ -29,6 +29,20 @@ describe('Colour space conversion', function() { .toFile(fixtures.path('output.greyscale-not.jpg'), done); }); + it('Greyscale with single channel output', function(done) { + sharp(fixtures.inputJpg) + .resize(320, 240) + .greyscale() + .toColourspace('b-w') + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(1, info.channels); + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + fixtures.assertSimilar(fixtures.expected('output.greyscale-single.jpg'), data, done); + }); + }); + if (sharp.format.tiff.input.file && sharp.format.webp.output.buffer) { it('From 1-bit TIFF to sRGB WebP [slow]', function(done) { sharp(fixtures.inputTiff) diff --git a/test/unit/joinChannel.js b/test/unit/joinChannel.js new file mode 100644 index 000000000..eb8d5c362 --- /dev/null +++ b/test/unit/joinChannel.js @@ -0,0 +1,116 @@ +'use strict'; + +var assert = require('assert'); +var fs = require('fs'); +var sharp = require('../../index'); +var fixtures = require('../fixtures'); + +describe('Image channel insertion', function() { + + it('Grayscale to RGB, buffer', function(done) { + sharp(fixtures.inputPng) // gray -> red + .resize(320,240) + .joinChannel(fixtures.inputPngTestJoinChannel) // new green channel + .joinChannel(fixtures.inputPngStripesH) // new blue channel + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(3, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgb.jpg'), data, done); + }); + }); + + it('Grayscale to RGB, file', function(done) { + sharp(fixtures.inputPng) // gray -> red + .resize(320,240) + .joinChannel(fs.readFileSync(fixtures.inputPngTestJoinChannel)) // new green channel + .joinChannel(fs.readFileSync(fixtures.inputPngStripesH)) // new blue channel + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(3, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgb.jpg'), data, done); + }); + }); + + it('Grayscale to RGBA, buffer', function(done) { + sharp(fixtures.inputPng) // gray -> red + .resize(320,240) + .joinChannel([fixtures.inputPngTestJoinChannel, + fixtures.inputPngStripesH, + fixtures.inputPngStripesV]) // new green + blue + alpha channel + .toColourspace(sharp.colourspace.srgb) + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(4, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgba.png'), data, done); + }); + }); + + it('Grayscale to RGBA, file', function(done) { + sharp(fixtures.inputPng) // gray -> red + .resize(320,240) + .joinChannel([fs.readFileSync(fixtures.inputPngTestJoinChannel), // new green channel + fs.readFileSync(fixtures.inputPngStripesH), // new blue channel + fs.readFileSync(fixtures.inputPngStripesV)]) // new alpha channel + .toColourspace('srgb') + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(4, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgba.png'), data, done); + }); + }); + + it('Grayscale to CMYK, buffers', function(done) { + sharp(fixtures.inputPng) // gray -> magenta + .resize(320,240) + .joinChannel([fs.readFileSync(fixtures.inputPngTestJoinChannel), // new cyan channel + fs.readFileSync(fixtures.inputPngStripesH), // new yellow channel + fs.readFileSync(fixtures.inputPngStripesV)]) // new black channel + .toColorspace('cmyk') + .toFormat('jpeg') + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(4, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-cmyk.jpg'), data, done); + }); + }); + + it('Invalid input', function() { + assert.throws(function() { + sharp(fixtures.inputJpg) + .joinChannel(1); + }); + }); + + it('No arguments', function() { + assert.throws(function() { + sharp(fixtures.inputJpg) + .joinChannel(); + }); + }); + + it('Invalid file / buffer mix', function() { + assert.throws(function() { + sharp(fixtures.inputPng) + .joinChannel([fixtures.inputPngTestJoinChannel, fs.readFileSync(fixtures.inputPngTestJoinChannel)]); + }); + }); + + it('Invalid file / buffer mix, two commands', function() { + assert.throws(function() { + sharp(fixtures.inputPng) + .joinChannel(fixtures.inputPngTestJoinChannel) + .joinChannel(fs.readFileSync(fixtures.inputPngTestJoinChannel)); + }); + }); + +}); From 70a6985ee2c9e038ceb8aa577ef02648ab1626bd Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Sun, 17 Jul 2016 00:11:27 -0400 Subject: [PATCH 2/9] cleanup a few details --- docs/api.md | 2 +- index.js | 2 +- src/pipeline.cc | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index 7dc5d1704..2af8c17bf 100644 --- a/docs/api.md +++ b/docs/api.md @@ -512,7 +512,7 @@ sharp(input) #### joinChannel(channels) -Join a data channel to the image. The meaning of the added channels depends on the output colourspace, set with `toColourspace()`. By default output will be web-friendly sRGB, with additional channels interpreted as alpha channels. +Join a data channel to the image. The meaning of the added channels depends on the output colourspace, set with `toColourspace()`. By default the output image will be web-friendly sRGB, with additional channels interpreted as alpha channels. `channels` is one of * a single file path diff --git a/index.js b/index.js index 502a58249..b43a6a8ec 100644 --- a/index.js +++ b/index.js @@ -687,7 +687,6 @@ Sharp.prototype.greyscale = function(greyscale) { }; Sharp.prototype.grayscale = Sharp.prototype.greyscale; - /* Set output colourspace */ @@ -896,6 +895,7 @@ module.exports.colourspace = { cmyk: 'cmyk', srgb: 'srgb' }; +module.exports.colorspace = module.exports.colourspace; /* Resize image to width x height pixels diff --git a/src/pipeline.cc b/src/pipeline.cc index d1a1b8065..1d23abe21 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -232,7 +232,6 @@ class PipelineWorker : public AsyncWorker { image = Trim(image, baton->trimTolerance); } - // Pre extraction if (baton->topOffsetPre != -1) { image = image.extract_area(baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre); @@ -1071,7 +1070,6 @@ class PipelineWorker : public AsyncWorker { } catch (VError const &err) { (baton->err).append(err.what()); } - // Clean up libvips' per-request data and threads vips_error_clear(); vips_thread_shutdown(); From 8f5da5880156666d128f8bd24fb2f2886acf8efa Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Mon, 18 Jul 2016 11:36:31 -0400 Subject: [PATCH 3/9] unordered_map -> map ?? maybe this will fix xcode build error? --- src/pipeline.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pipeline.cc b/src/pipeline.cc index 1d23abe21..a069f7700 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include @@ -112,7 +112,7 @@ class PipelineWorker : public AsyncWorker { // Increment processing task counter g_atomic_int_inc(&counterProcess); - std::unordered_map profileMap; + std::map profileMap; // Default sRGB ICC profile from https://packages.debian.org/sid/all/icc-profiles-free/filelist profileMap.insert( std::pair(VIPS_INTERPRETATION_sRGB, From 6d1d1b3ee311cd2d087f7bdfa368daf0234f9f22 Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Tue, 19 Jul 2016 04:13:57 -0400 Subject: [PATCH 4/9] Add ability to read raw buffers in joinChannel --- .jshintrc | 3 ++- docs/api.md | 4 +++- index.js | 21 ++++++++++++++++++- src/pipeline.cc | 44 +++++++++++++++++++++++++++++++--------- src/pipeline.h | 6 ++++++ test/unit/joinChannel.js | 40 +++++++++++++++++++++++++++++++----- 6 files changed, 100 insertions(+), 18 deletions(-) diff --git a/.jshintrc b/.jshintrc index 13d45c65d..03b87cf8f 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,6 +7,7 @@ "beforeEach": true, "afterEach": true, "describe": true, - "it": true + "it": true, + "Promise": true } } diff --git a/docs/api.md b/docs/api.md index 2af8c17bf..0d4ef6ff0 100644 --- a/docs/api.md +++ b/docs/api.md @@ -510,7 +510,7 @@ sharp(input) }); ``` -#### joinChannel(channels) +#### joinChannel(channels, [options]) Join a data channel to the image. The meaning of the added channels depends on the output colourspace, set with `toColourspace()`. By default the output image will be web-friendly sRGB, with additional channels interpreted as alpha channels. @@ -524,6 +524,8 @@ Note that channel ordering follows vips convention: * sRGB: 0: Red, 1: Green, 2: Blue, 3: Alpha * CMYK: 0: Magenta, 1: Cyan, 2: Yellow, 3: Black, 4: Alpha +Buffers may be any of the image formats supported by sharp: JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data. In the case of a RAW buffer, the `options` object should contain a `raw` attribute, which follows the format of the attribute of the same name in the `sharp()` constructor. See `sharp()` for details. See `raw()` for pixel ordering. + #### bandbool(operation) Perform a bitwise boolean operation on all input image channels (bands) to produce a single channel output image. diff --git a/index.js b/index.js index b43a6a8ec..d3148535b 100644 --- a/index.js +++ b/index.js @@ -94,6 +94,9 @@ var Sharp = function(input, options) { booleanFileIn: '', joinChannelBuffersIn: [], joinChannelFilesIn: [], + joinChannelRawWidth: 0, + joinChannelRawHeight: 0, + joinChannelRawChannels: 0, // overlay overlayFileIn: '', overlayBufferIn: null, @@ -441,7 +444,7 @@ Sharp.prototype.overlayWith = function(overlay, options) { /* Add another color channel to the image */ -Sharp.prototype.joinChannel = function(images) { +Sharp.prototype.joinChannel = function(images, options) { if (Array.isArray(images)) { // Array of image file names or buffers, not mixed var type = images.reduce(function(prev, curr) { @@ -476,6 +479,22 @@ Sharp.prototype.joinChannel = function(images) { } else { throw new Error('Invalid input to joinChannel'); } + if (isObject(options)) { + if (isDefined(options.raw)) { + if ( + isObject(options.raw) && + isInteger(options.raw.width) && inRange(options.raw.width, 1, maximum.width) && + isInteger(options.raw.height) && inRange(options.raw.height, 1, maximum.height) && + isInteger(options.raw.channels) && inRange(options.raw.channels, 1, 4) + ) { + this.options.joinChannelRawWidth = options.raw.width; + this.options.joinChannelRawHeight = options.raw.height; + this.options.joinChannelRawChannels = options.raw.channels; + } else { + throw new Error('joinChannel: expected width, height and channels for raw pixel input'); + } + } + } return this; }; diff --git a/src/pipeline.cc b/src/pipeline.cc index a069f7700..0cfbe4ec3 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -566,20 +566,41 @@ class PipelineWorker : public AsyncWorker { if (baton->joinChannelBuffersIn.size() > 0 && baton->joinChannelBuffersIn.size() == baton->joinChannelBuffersInLength.size()) { // Joining with buffers - for(unsigned int i = 0; i < baton->joinChannelBuffersIn.size(); i++) { - joinImageType = DetermineImageType(baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i]); - if (joinImageType != ImageType::UNKNOWN) { + if (baton->joinChannelRawWidth > 0 && baton->joinChannelRawHeight > 0 && baton->joinChannelRawChannels > 0) { + // Raw, uncompressed pixe data + for(unsigned int i = 0; i < baton->joinChannelBuffersIn.size(); i++) { try { - joinImage = VImage::new_from_buffer( - baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i], - nullptr, VImage::option()->set("access", baton->accessMethod)); + joinImage = VImage::new_from_memory(baton->joinChannelBuffersIn[i], + baton->joinChannelBuffersInLength[i], + baton->joinChannelRawWidth, baton->joinChannelRawHeight, + baton->joinChannelRawChannels, VIPS_FORMAT_UCHAR); image = image.bandjoin(joinImage); - } catch (...) { - (baton->err).append("Join Channel buffer has corrupt header"); + joinImageType = ImageType::RAW; + } catch (VError const &err) { + (baton->err).append(err.what()); joinImageType = ImageType::UNKNOWN; + break; + } + } + } else { + // Compressed data + for(unsigned int i = 0; i < baton->joinChannelBuffersIn.size(); i++) { + joinImageType = DetermineImageType(baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i]); + if (joinImageType != ImageType::UNKNOWN) { + try { + joinImage = VImage::new_from_buffer( + baton->joinChannelBuffersIn[i], baton->joinChannelBuffersInLength[i], + nullptr, VImage::option()->set("access", baton->accessMethod)); + image = image.bandjoin(joinImage); + } catch (...) { + (baton->err).append("Join Channel buffer has corrupt header"); + joinImageType = ImageType::UNKNOWN; + break; + } + } else { + (baton->err).append("Join Channel buffer contains unsupported image format"); + break; } - } else { - (baton->err).append("Join Channel buffer contains unsupported image format"); } } } else if (baton->joinChannelFilesIn.size() > 0) { @@ -1305,6 +1326,9 @@ NAN_METHOD(pipeline) { baton->joinChannelBuffersIn.push_back(node::Buffer::Data(joinChannelBufferIn)); buffersToPersist.push_back(joinChannelBufferIn); } + baton->joinChannelRawWidth = attrAs(options, "joinChannelRawWidth"); + baton->joinChannelRawHeight = attrAs(options, "joinChannelRawHeight"); + baton->joinChannelRawChannels = attrAs(options, "joinChannelRawChannels"); // Operators baton->flatten = attrAs(options, "flatten"); baton->negate = attrAs(options, "negate"); diff --git a/src/pipeline.h b/src/pipeline.h index e7457c267..5d9e0c733 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -45,6 +45,9 @@ struct PipelineBaton { std::vector joinChannelFilesIn; std::vector joinChannelBuffersIn; std::vector joinChannelBuffersInLength; + int joinChannelRawWidth; + int joinChannelRawHeight; + int joinChannelRawChannels; int topOffsetPre; int leftOffsetPre; int widthPre; @@ -125,6 +128,9 @@ struct PipelineBaton { overlayTile(false), overlayCutout(false), booleanBufferInLength(0), + joinChannelRawWidth(0), + joinChannelRawHeight(0), + joinChannelRawChannels(0), topOffsetPre(-1), topOffsetPost(-1), channels(0), diff --git a/test/unit/joinChannel.js b/test/unit/joinChannel.js index eb8d5c362..2d77074fa 100644 --- a/test/unit/joinChannel.js +++ b/test/unit/joinChannel.js @@ -9,7 +9,7 @@ describe('Image channel insertion', function() { it('Grayscale to RGB, buffer', function(done) { sharp(fixtures.inputPng) // gray -> red - .resize(320,240) + .resize(320, 240) .joinChannel(fixtures.inputPngTestJoinChannel) // new green channel .joinChannel(fixtures.inputPngStripesH) // new blue channel .toBuffer(function(err, data, info) { @@ -23,7 +23,7 @@ describe('Image channel insertion', function() { it('Grayscale to RGB, file', function(done) { sharp(fixtures.inputPng) // gray -> red - .resize(320,240) + .resize(320, 240) .joinChannel(fs.readFileSync(fixtures.inputPngTestJoinChannel)) // new green channel .joinChannel(fs.readFileSync(fixtures.inputPngStripesH)) // new blue channel .toBuffer(function(err, data, info) { @@ -37,7 +37,7 @@ describe('Image channel insertion', function() { it('Grayscale to RGBA, buffer', function(done) { sharp(fixtures.inputPng) // gray -> red - .resize(320,240) + .resize(320, 240) .joinChannel([fixtures.inputPngTestJoinChannel, fixtures.inputPngStripesH, fixtures.inputPngStripesV]) // new green + blue + alpha channel @@ -53,7 +53,7 @@ describe('Image channel insertion', function() { it('Grayscale to RGBA, file', function(done) { sharp(fixtures.inputPng) // gray -> red - .resize(320,240) + .resize(320, 240) .joinChannel([fs.readFileSync(fixtures.inputPngTestJoinChannel), // new green channel fs.readFileSync(fixtures.inputPngStripesH), // new blue channel fs.readFileSync(fixtures.inputPngStripesV)]) // new alpha channel @@ -69,7 +69,7 @@ describe('Image channel insertion', function() { it('Grayscale to CMYK, buffers', function(done) { sharp(fixtures.inputPng) // gray -> magenta - .resize(320,240) + .resize(320, 240) .joinChannel([fs.readFileSync(fixtures.inputPngTestJoinChannel), // new cyan channel fs.readFileSync(fixtures.inputPngStripesH), // new yellow channel fs.readFileSync(fixtures.inputPngStripesV)]) // new black channel @@ -84,6 +84,36 @@ describe('Image channel insertion', function() { }); }); + it('Join raw buffers to RGB', function(done) { + Promise.all([ + sharp(fixtures.inputPngTestJoinChannel).toColourspace('b-w').raw().toBuffer(), + sharp(fixtures.inputPngStripesH).toColourspace('b-w').raw().toBuffer() + ]).then( + function(buffers) { + sharp(fixtures.inputPng) + .resize(320, 240) + .joinChannel(buffers, + { raw: { + width: 320, + height: 240, + channels: 1 + }}) + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(3, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgb.jpg'), data, done); + }); + }); + }); + + it('Invalid raw buffer description', function() { + assert.throws(function() { + sharp().joinChannel(fs.readFileSync(fixtures.inputPng),{raw:{}}); + }); + }); + it('Invalid input', function() { assert.throws(function() { sharp(fixtures.inputJpg) From 68d6fa20914f864037af0be927884dbb33ef81d0 Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Tue, 19 Jul 2016 12:59:10 -0400 Subject: [PATCH 5/9] outputMode -> colourspace (variable name change) use BluebirdPromise instead of Promise to support old versions of node --- .jshintrc | 3 +-- index.js | 4 ++-- src/pipeline.cc | 18 +++++++++--------- src/pipeline.h | 4 ++-- test/unit/joinChannel.js | 3 ++- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.jshintrc b/.jshintrc index 03b87cf8f..13d45c65d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,7 +7,6 @@ "beforeEach": true, "afterEach": true, "describe": true, - "it": true, - "Promise": true + "it": true } } diff --git a/index.js b/index.js index d3148535b..8328305fe 100644 --- a/index.js +++ b/index.js @@ -122,7 +122,7 @@ var Sharp = function(input, options) { tileSize: 256, tileOverlap: 0, extractChannel: -1, - outputMode: 'srgb', + colourspace: 'srgb', // Function to notify of queue length changes queueListener: function(queueLength) { module.exports.queue.emit('change', queueLength); @@ -713,7 +713,7 @@ Sharp.prototype.toColourspace = function(colourspace) { if (!isString(colourspace) ) { throw new Error('Invalid output colourspace ' + colourspace); } - this.options.outputMode = colourspace; + this.options.colourspace = colourspace; return this; }; Sharp.prototype.toColorspace = Sharp.prototype.toColourspace; diff --git a/src/pipeline.cc b/src/pipeline.cc index 0cfbe4ec3..4cb1fd7a4 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -625,7 +625,7 @@ class PipelineWorker : public AsyncWorker { if(joinImageType == ImageType::UNKNOWN) { return Error(); } else { - image = image.copy(VImage::option()->set("interpretation", baton->outputMode)); + image = image.copy(VImage::option()->set("interpretation", baton->colourspace)); } } @@ -913,14 +913,14 @@ class PipelineWorker : public AsyncWorker { if (Is16Bit(image.interpretation())) { image = image.cast(VIPS_FORMAT_USHORT); } - if (image.interpretation() != baton->outputMode) { + if (image.interpretation() != baton->colourspace) { // Need to convert image - image = image.colourspace(baton->outputMode); + image = image.colourspace(baton->colourspace); // Transform colours from embedded profile to output profile if (baton->withMetadata && HasProfile(image) && - profileMap[baton->outputMode] != std::string()) { - image = image.icc_transform(const_cast(profileMap[baton->outputMode].data()), + profileMap[baton->colourspace] != std::string()) { + image = image.icc_transform(const_cast(profileMap[baton->colourspace].data()), VImage::option()->set("embedded", TRUE) ); } @@ -955,7 +955,7 @@ class PipelineWorker : public AsyncWorker { area->free_fn = nullptr; vips_area_unref(area); baton->formatOut = "jpeg"; - if(baton->outputMode == VIPS_INTERPRETATION_CMYK) { + if(baton->colourspace == VIPS_INTERPRETATION_CMYK) { baton->channels = std::min(baton->channels, 4); } else { baton->channels = std::min(baton->channels, 3); @@ -1365,9 +1365,9 @@ NAN_METHOD(pipeline) { baton->optimiseScans = attrAs(options, "optimiseScans"); baton->withMetadata = attrAs(options, "withMetadata"); baton->withMetadataOrientation = attrAs(options, "withMetadataOrientation"); - baton->outputMode = GetInterpretation(attrAsStr(options, "outputMode")); - if(baton->outputMode == VIPS_INTERPRETATION_ERROR) - baton->outputMode = VIPS_INTERPRETATION_sRGB; + baton->colourspace = GetInterpretation(attrAsStr(options, "colourspace")); + if(baton->colourspace == VIPS_INTERPRETATION_ERROR) + baton->colourspace = VIPS_INTERPRETATION_sRGB; // Output baton->formatOut = attrAsStr(options, "formatOut"); baton->fileOut = attrAsStr(options, "fileOut"); diff --git a/src/pipeline.h b/src/pipeline.h index 5d9e0c733..362d5c492 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -105,7 +105,7 @@ struct PipelineBaton { VipsOperationBoolean bandBoolOp; VipsOperationBoolean booleanOp; int extractChannel; - VipsInterpretation outputMode; + VipsInterpretation colourspace; int tileSize; int tileOverlap; VipsForeignDzContainer tileContainer; @@ -173,7 +173,7 @@ struct PipelineBaton { bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST), booleanOp(VIPS_OPERATION_BOOLEAN_LAST), extractChannel(-1), - outputMode(VIPS_INTERPRETATION_LAST), + colourspace(VIPS_INTERPRETATION_LAST), tileSize(256), tileOverlap(0), tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS), diff --git a/test/unit/joinChannel.js b/test/unit/joinChannel.js index 2d77074fa..e3d15ac08 100644 --- a/test/unit/joinChannel.js +++ b/test/unit/joinChannel.js @@ -4,6 +4,7 @@ var assert = require('assert'); var fs = require('fs'); var sharp = require('../../index'); var fixtures = require('../fixtures'); +var BluebirdPromise = require('bluebird'); describe('Image channel insertion', function() { @@ -85,7 +86,7 @@ describe('Image channel insertion', function() { }); it('Join raw buffers to RGB', function(done) { - Promise.all([ + BluebirdPromise.all([ sharp(fixtures.inputPngTestJoinChannel).toColourspace('b-w').raw().toBuffer(), sharp(fixtures.inputPngStripesH).toColourspace('b-w').raw().toBuffer() ]).then( From 856c7d1182924ebf932d8843b8ae8e5a5098b70c Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Mon, 8 Aug 2016 02:17:05 -0400 Subject: [PATCH 6/9] Add a test of invalid input for toColourspace --- test/unit/colourspace.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/colourspace.js b/test/unit/colourspace.js index b7de36405..1eb4ee31e 100644 --- a/test/unit/colourspace.js +++ b/test/unit/colourspace.js @@ -93,4 +93,10 @@ describe('Colour space conversion', function() { }); }); + it('Invalid input', function() { + assert.throws(function() { + sharp(fixtures.inputJpg) + .toColourspace(null); + }); + }); }); From b38bc038bd232f1a93aaf4d518f120183318a525 Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Sun, 14 Aug 2016 12:28:25 -0400 Subject: [PATCH 7/9] fix bandbool unit test to create 1-channel image now that toColourspace is available --- test/unit/bandbool.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/unit/bandbool.js b/test/unit/bandbool.js index 2194dcc42..81e1ec2a4 100644 --- a/test/unit/bandbool.js +++ b/test/unit/bandbool.js @@ -15,13 +15,12 @@ describe('Bandbool per-channel boolean operations', function() { it(op + ' operation', function(done) { sharp(fixtures.inputPngBooleanNoAlpha) .bandbool(op) + .toColourspace('b-w') .toBuffer(function(err, data, info) { - // should use .toColourspace('b-w') here to get 1 channel output, when it is merged if (err) throw err; assert.strictEqual(200, info.width); assert.strictEqual(200, info.height); - //assert.strictEqual(1, info.channels); - assert.strictEqual(3, info.channels); + assert.strictEqual(1, info.channels); fixtures.assertSimilar(fixtures.expected('bandbool_' + op + '_result.png'), data, done); }); }); From 816204b86cf42567cb848325324b90e91ccfdf7b Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Mon, 15 Aug 2016 23:34:43 -0400 Subject: [PATCH 8/9] fix problem where second joinChannel array is not added correctly --- index.js | 4 ++-- test/unit/joinChannel.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index d955d6603..9cc908c9d 100644 --- a/index.js +++ b/index.js @@ -428,8 +428,8 @@ Sharp.prototype.overlayWith = function(overlay, options) { */ Sharp.prototype.joinChannel = function(images, options) { if (Array.isArray(images)) { - images.forEach(function(image, index) { - this.options.joinChannelIn[index] = this._createInputDescriptor(image, options); + images.forEach(function(image) { + this.options.joinChannelIn.push(this._createInputDescriptor(image, options)); }, this); } else { this.options.joinChannelIn.push(this._createInputDescriptor(images, options)); diff --git a/test/unit/joinChannel.js b/test/unit/joinChannel.js index 94099d7f0..36c80e26f 100644 --- a/test/unit/joinChannel.js +++ b/test/unit/joinChannel.js @@ -112,6 +112,22 @@ describe('Image channel insertion', function() { }); }); + it('Grayscale to RGBA, files, two arrays', function(done) { + sharp(fixtures.inputPng) // gray -> red + .resize(320, 240) + .joinChannel([fs.readFileSync(fixtures.inputPngTestJoinChannel)]) // new green channel + .joinChannel([fs.readFileSync(fixtures.inputPngStripesH), // new blue channel + fs.readFileSync(fixtures.inputPngStripesV)]) // new alpha channel + .toColourspace('srgb') + .toBuffer(function(err, data, info) { + if (err) throw err; + assert.strictEqual(320, info.width); + assert.strictEqual(240, info.height); + assert.strictEqual(4, info.channels); + fixtures.assertSimilar(fixtures.expected('joinChannel-rgba.png'), data, done); + }); + }); + it('Invalid raw buffer description', function() { assert.throws(function() { sharp().joinChannel(fs.readFileSync(fixtures.inputPng),{raw:{}}); From 6f79a990cdc617b3dee1140ba82c5862404082c0 Mon Sep 17 00:00:00 2001 From: Matt Hirsch Date: Mon, 15 Aug 2016 23:46:08 -0400 Subject: [PATCH 9/9] only set the image interpretation once in joinChannel --- src/pipeline.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pipeline.cc b/src/pipeline.cc index 4c71c9325..4db7a4000 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -437,8 +437,8 @@ class PipelineWorker : public Nan::AsyncWorker { std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i], baton->accessMethod); image = image.bandjoin(joinImage); - image = image.copy(VImage::option()->set("interpretation", baton->colourspace)); } + image = image.copy(VImage::option()->set("interpretation", baton->colourspace)); } // Crop/embed