diff --git a/package.json b/package.json index 24c32df1..a6277071 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "Chintan Thakkar ", "F. Orlando Galashan ", "Kleis Auke Wolthuizen ", - "Matt Hirsch " + "Matt Hirsch ", + "Matthias Thoemmes " ], "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images", "scripts": { diff --git a/src/pipeline.cc b/src/pipeline.cc index 6811a843..afc36961 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -581,6 +581,20 @@ class PipelineWorker : public Nan::AsyncWorker { // 'cut out' the image, premultiplication is not required image = sharp::Cutout(overlayImage, image, baton->overlayGravity); } else { + // Ensure overlay has alpha channel + if (!HasAlpha(overlayImage)) { + double const multiplier = sharp::Is16Bit(overlayImage.interpretation()) ? 256.0 : 1.0; + overlayImage = overlayImage.bandjoin( + VImage::new_matrix(overlayImage.width(), overlayImage.height()).new_from_image(255 * multiplier) + ); + } + // Ensure image has alpha channel + if (!HasAlpha(image)) { + double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0; + image = image.bandjoin( + VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier) + ); + } // Ensure overlay is premultiplied sRGB overlayImage = overlayImage.colourspace(VIPS_INTERPRETATION_sRGB).premultiply(); if (baton->overlayXOffset >= 0 && baton->overlayYOffset >= 0) { diff --git a/test/unit/overlay.js b/test/unit/overlay.js index e7425387..f67697ff 100644 --- a/test/unit/overlay.js +++ b/test/unit/overlay.js @@ -154,11 +154,20 @@ describe('Overlays', function() { }); } - it('Fail when overlay does not contain alpha channel', function(done) { + it('Composite JPEG onto PNG', function(done) { sharp(fixtures.inputPngOverlayLayer1) - .overlayWith(fixtures.inputJpg) + .overlayWith(fixtures.inputJpgWithLandscapeExif1) .toBuffer(function(error) { - assert.strictEqual(true, error instanceof Error); + if (error) return done(error); + done(); + }); + }); + + it('Composite opaque JPEG onto JPEG', function(done) { + sharp(fixtures.inputJpg) + .overlayWith(fixtures.inputJpgWithLandscapeExif1) + .toBuffer(function(error) { + if (error) return done(error); done(); }); });