diff --git a/docs/changelog.md b/docs/changelog.md index 3f5adcf3..16a474f6 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -19,6 +19,9 @@ Requires libvips v8.13.1 * Ensure AVIF output is always 8-bit. [#3358](https://github.com/lovell/sharp/issues/3358) +* Ensure greyscale images can be trimmed (regression in 0.31.0). + [#3386](https://github.com/lovell/sharp/issues/3386) + ### v0.31.0 - 5th September 2022 * Drop support for Node.js 12, now requires Node.js >= 14.15.0. diff --git a/src/operations.cc b/src/operations.cc index 89c2d6ee..cf5af224 100644 --- a/src/operations.cc +++ b/src/operations.cc @@ -289,17 +289,20 @@ namespace sharp { background = image.extract_area(0, 0, 1, 1)(0, 0); multiplier = 1.0; } - if (background.size() == 4) { + if (HasAlpha(image) && background.size() == 4) { // Just discard the alpha because flattening the background colour with // itself (effectively what find_trim() does) gives the same result backgroundAlpha[0] = background[3] * multiplier; } - background = { - background[0] * multiplier, - background[1] * multiplier, - background[2] * multiplier - }; - + if (image.bands() > 2) { + background = { + background[0] * multiplier, + background[1] * multiplier, + background[2] * multiplier + }; + } else { + background[0] = background[0] * multiplier; + } int left, top, width, height; left = image.find_trim(&top, &width, &height, VImage::option() ->set("background", background) diff --git a/test/unit/trim.js b/test/unit/trim.js index 022968a7..f1619b59 100644 --- a/test/unit/trim.js +++ b/test/unit/trim.js @@ -124,6 +124,32 @@ describe('Trim borders', function () { assert.strictEqual(trimOffsetLeft, -13); }); + it('Ensure greyscale image can be trimmed', async () => { + const greyscale = await sharp({ + create: { + width: 16, + height: 8, + channels: 3, + background: 'silver' + } + }) + .extend({ left: 12, right: 24, background: 'gray' }) + .toColourspace('b-w') + .png({ compressionLevel: 0 }) + .toBuffer(); + + const { info } = await sharp(greyscale) + .trim() + .raw() + .toBuffer({ resolveWithObject: true }); + + const { width, height, trimOffsetTop, trimOffsetLeft } = info; + assert.strictEqual(width, 16); + assert.strictEqual(height, 8); + assert.strictEqual(trimOffsetTop, 0); + assert.strictEqual(trimOffsetLeft, -12); + }); + it('Ensure trim of image with all pixels same is no-op', async () => { const { info } = await sharp({ create: {