diff --git a/src/sharp.cc b/src/sharp.cc index f0950c01..e461dbc4 100755 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -161,6 +161,19 @@ sharp_calc_crop(int const inWidth, int const inHeight, int const outWidth, int c return std::make_tuple(left, top); } +/* + Does this image have an alpha channel? + Uses colourspace interpretation with number of channels to guess this. +*/ +static bool +sharp_image_has_alpha(VipsImage *image) { + return ( + (image->Bands == 2 && image->Type == VIPS_INTERPRETATION_B_W) || + (image->Bands == 4 && image->Type != VIPS_INTERPRETATION_CMYK) || + (image->Bands == 5 && image->Type == VIPS_INTERPRETATION_CMYK) + ); +} + /* Initialise a VipsImage from a buffer. Supports JPEG, PNG and WebP. Returns the ImageType detected, if any. @@ -228,6 +241,7 @@ struct metadata_baton { int height; std::string space; int channels; + bool has_alpha; int orientation; std::string err; @@ -276,6 +290,7 @@ class MetadataWorker : public NanAsyncWorker { baton->height = image->Ysize; baton->space = vips_enum_nick(VIPS_TYPE_INTERPRETATION, image->Type); baton->channels = image->Bands; + baton->has_alpha = sharp_image_has_alpha(image); // EXIF Orientation const char *exif; if (!vips_image_get_string(image, "exif-ifd0-Orientation", &exif)) { @@ -303,6 +318,7 @@ class MetadataWorker : public NanAsyncWorker { info->Set(NanNew("height"), NanNew(baton->height)); info->Set(NanNew("space"), NanNew(baton->space)); info->Set(NanNew("channels"), NanNew(baton->channels)); + info->Set(NanNew("hasAlpha"), NanNew(baton->has_alpha)); if (baton->orientation > 0) { info->Set(NanNew("orientation"), NanNew(baton->orientation)); } diff --git a/tests/fixtures/blackbug.png b/tests/fixtures/blackbug.png new file mode 100644 index 00000000..f080d05b Binary files /dev/null and b/tests/fixtures/blackbug.png differ diff --git a/tests/unit.js b/tests/unit.js index 4c6123ee..174be885 100755 --- a/tests/unit.js +++ b/tests/unit.js @@ -21,6 +21,7 @@ var inputJpgWithExif = path.join(fixturesPath, "Landscape_8.jpg"); // https://gi var inputJpgWithGammaHoliness = path.join(fixturesPath, "gamma_dalai_lama_gray.jpg"); // http://www.4p8.com/eric.brasseur/gamma.html var inputPng = path.join(fixturesPath, "50020484-00001.png"); // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png +var inputPngWithTransparency = path.join(fixturesPath, "blackbug.png"); // public domain var inputWebP = path.join(fixturesPath, "4.webp"); // http://www.gstatic.com/webp/gallery/4.webp var inputGif = path.join(fixturesPath, "Crash_test.gif"); // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif @@ -593,6 +594,7 @@ async.series([ assert.strictEqual(600, metadata.height); assert.strictEqual('srgb', metadata.space); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); assert.strictEqual(8, metadata.orientation); done(); }); @@ -606,6 +608,7 @@ async.series([ assert.strictEqual(3248, metadata.height); assert.strictEqual('b-w', metadata.space); assert.strictEqual(1, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); done(); }); }, @@ -618,6 +621,20 @@ async.series([ assert.strictEqual(2074, metadata.height); assert.strictEqual('b-w', metadata.space); assert.strictEqual(1, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); + done(); + }); + }, + // Metadata - Transparent PNG + function(done) { + sharp(inputPngWithTransparency).metadata(function(err, metadata) { + if (err) throw err; + assert.strictEqual('png', metadata.format); + assert.strictEqual(2048, metadata.width); + assert.strictEqual(1536, metadata.height); + assert.strictEqual('srgb', metadata.space); + assert.strictEqual(4, metadata.channels); + assert.strictEqual(true, metadata.hasAlpha); done(); }); }, @@ -630,6 +647,7 @@ async.series([ assert.strictEqual(772, metadata.height); assert.strictEqual('srgb', metadata.space); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); done(); }); }, @@ -641,6 +659,7 @@ async.series([ assert.strictEqual(800, metadata.width); assert.strictEqual(533, metadata.height); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); done(); }); }, @@ -652,6 +671,7 @@ async.series([ assert.strictEqual(2225, metadata.height); assert.strictEqual('srgb', metadata.space); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); done(); }); }, @@ -665,6 +685,7 @@ async.series([ assert.strictEqual(2225, metadata.height); assert.strictEqual('srgb', metadata.space); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); done(); }); readable.pipe(pipeline); @@ -679,6 +700,7 @@ async.series([ assert.strictEqual(2225, metadata.height); assert.strictEqual('srgb', metadata.space); assert.strictEqual(3, metadata.channels); + assert.strictEqual(false, metadata.hasAlpha); image.resize(metadata.width / 2).toBuffer(function(err, data, info) { if (err) throw err; assert.strictEqual(true, data.length > 0);