-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Output of profile conversion in combination with negate
seems off
#4045
Comments
My best guess would be that this relates to (a lack of) gamut. Does the following change help? It should ensure the input CMYK profile is respected when present, preventing the narrower, built-in CMYK profile being introduced and therefore allow the removal of --- a/src/pipeline.cc
+++ b/src/pipeline.cc
@@ -348,6 +348,7 @@ class PipelineWorker : public Napi::AsyncWorker {
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK
) {
image = image.icc_transform(processingProfile, VImage::option()
+ ->set("embedded", TRUE)
->set("input_profile", "cmyk")
->set("intent", VIPS_INTENT_PERCEPTUAL));
} It's also possible that Photoshop's idea of inverting CMYK values is different to libvips. In addition sharp always tells the underlying lcms to use perceptual rendering intent, which might differ from Photoshop's treatment. |
Thanks for the suggestion. I've did some tests without negating to see if the built-in CMYK profile is introduced by comparing with the output from Attached a 1000x1000 tiff file with all pixels set to # Get source pixel value (output: 0 255 255 0)
vips getpoint fogra.tif 0 0
# Convert to U.S. Web Coated (SWOP) v2
vips icc_transform fogra.tif swop.tif swop.icc
# Get destination pixel valuex (output: 10 255 255 1)
vips getpoint swop.tif 0 0 The destination pixels match exactly those of Photoshop when converting to the SWOP profile using relative colorimetric intent and black point compensation turned off (= the defaults of I did the same icc transform using sharp with every combination of await sharp('fogra.tif').toColourspace('cmyk').pipelineColourspace('cmyk').withIccProfile('swop.icc').toFile('swop1.tif');
await sharp('fogra.tif').toColourspace('cmyk').withIccProfile('swop.icc').toFile('swop2.tif');
await sharp('fogra.tif').pipelineColourspace('cmyk').withIccProfile('swop.icc').toFile('swop3.tif');
await sharp('fogra.tif').withIccProfile('swop.icc').toFile('swop4.tif'); Here's the output pixel values:
After applying your code change in Happy to test any other suggestion. |
Thank you, this is useful info, and points to the difference being rendering intent: $ vips icc_transform fogra.tif swop.tif swop.icc --intent=perceptual
$ vips getpoint swop.tif 0 0
25 255 255 4 sharp uses perceptual intent to try to avoid too much visually-obvious gamut clipping, but this can come at the cost of saturation levels, which from these examples appears to adversely affect CMYK-to-CMYK transformations. Maybe we should switch to always using relative intent when transforming CMYK images? |
Thank you for taking a look at this. I have tested the initial bug and played around in pipeline.cc by moving the It seems that when the conversion happens before the So in the case below, when
Place in the pipeline where the conversion to ICC happens: Line 810 in 52b9dc0
Negate works when moved to: Line 359 in 52b9dc0 I hope this helps! Thanks again for your help. |
@lovell Thanks for clarifying the difference in values due to the perceptual intent being used as. Great suggestion to use relative intent by default when transforming CMYK images, as it would match the behaviour from Alternatively, providing an optional parameter for Getting back to the I tried moving the color conversion to the top of the pipeline as suggested by @roeldl. It generates the correct output, but it causes many tests to fail. So, I tried moving the implementation of // Apply output ICC profile
if (!baton->withIccProfile.empty()) {
// ... implementation
}
// Negate the colours in the image
if (baton->negate) {
image = sharp::Negate(image, baton->negateAlpha);
} This produces the right result (see below + inverted image in Photoshop to compare with the original file)
I do see one test failing, though:
Do you think it makes sense to move I appreciate any directions on correcting the failing test if this solution fits, or other recommendations you might have for this issue. |
v0.33.4 now available with your fix, thank you. |
Possible bug
Is this a possible bug in a feature of sharp, unrelated to installation?
npm install sharp
completes without error.node -e "require('sharp')"
completes without error.If you cannot confirm both of these, please open an installation issue instead.
Are you using the latest version of sharp?
sharp
as reported bynpm view sharp dist-tags.latest
.If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.
If you are using another package which depends on a version of
sharp
that is not the latest, please open an issue against that package instead.What is the output of running
npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp
?What are the steps to reproduce?
I need to process a CMYK TIFF file (tiger-cmyk-fogra.tif) with an embedded Coated FOGRA39 profile. My goal is to convert this image to the
U.S. Web Coated (SWOP) v2
profile and invert the colors, ideally in a single operation. The following code performs these tasks in two steps and achieves the desired result:However, when I attempt to combine these operations into a single step using various approaches, none yield the same result as the two-step process. Here are the methods I've tried:
Each attempt successfully inverts the image and applies the SWOP profile but does not match the visual result of the two-step operation:
When viewed in Photoshop (after inverting back):
What is the expected behaviour?
To match the output when converting in 2 steps.
I guess attempt 4 has the correct code as it ensures all operations will use this colourspace before converting to the output colourspace, but the resulting image data seems off.
Question
How can I achieve the same result as the two-step operation in a single operation?
The text was updated successfully, but these errors were encountered: