diff --git a/docs/changelog.md b/docs/changelog.md index 5379f4e1..2665bef9 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -20,6 +20,9 @@ Requires libvips v8.14.2 [#3615](https://github.com/lovell/sharp/pull/3615) [@TomWis97](https://github.com/TomWis97) +* Ensure profile-less CMYK to CMYK roundtrip skips colourspace conversion. + [#3620](https://github.com/lovell/sharp/issues/3620) + ### v0.32.0 - 24th March 2023 * Default to using sequential rather than random access read where possible. diff --git a/src/pipeline.cc b/src/pipeline.cc index 458f30fb..f8cdb749 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -322,7 +322,10 @@ class PipelineWorker : public Napi::AsyncWorker { } catch(...) { sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid embedded profile", nullptr); } - } else if (image.interpretation() == VIPS_INTERPRETATION_CMYK) { + } else if ( + image.interpretation() == VIPS_INTERPRETATION_CMYK && + baton->colourspaceInput != VIPS_INTERPRETATION_CMYK + ) { image = image.icc_transform(processingProfile, VImage::option() ->set("input_profile", "cmyk") ->set("intent", VIPS_INTENT_PERCEPTUAL)); diff --git a/test/unit/colourspace.js b/test/unit/colourspace.js index 532877cd..71ce402d 100644 --- a/test/unit/colourspace.js +++ b/test/unit/colourspace.js @@ -93,6 +93,19 @@ describe('Colour space conversion', function () { }); }); + it('Profile-less CMYK roundtrip', async () => { + const [c, m, y, k] = await sharp(fixtures.inputJpgWithCmykNoProfile) + .pipelineColourspace('cmyk') + .toColourspace('cmyk') + .raw() + .toBuffer(); + + assert.deepStrictEqual( + { c, m, y, k }, + { c: 55, m: 27, y: 0, k: 0 } + ); + }); + it('From sRGB with RGB16 pipeline, resize with gamma, to sRGB', function (done) { sharp(fixtures.inputPngGradients) .pipelineColourspace('rgb16')