Skip to content
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

WYSIWYG Printing colours #2299

Open
arenol opened this issue Nov 23, 2024 · 9 comments
Open

WYSIWYG Printing colours #2299

arenol opened this issue Nov 23, 2024 · 9 comments

Comments

@arenol
Copy link

arenol commented Nov 23, 2024

The colours, particularly the cyan colour, is far from realistic compared to the printing colours.

Here's an algorithm that will, reasoably accurate, convert CMYK to RGB that are within the printing gammut:

(c, m, y and k) are in the range 0 to 1, and so are will the rgb's be:

        double r = (1.0 - c) * (1.0 - m * 0.098) * (1.0 - k);
        double g = (1.0 - c * 0.376) * (1.0 - m) * (1.0 - y * 0.070) * (1.0 - k);
        double b = (1.0 - c * 0.109) * (1.0 - m * 0.505) * (1.0 - y) * (1.0 - k);
@krticka
Copy link
Contributor

krticka commented Nov 24, 2024

If it works well, I consider it beneficial. The biggest problem I see with the current appearance of 100% blue, for some mapping projects I even adjust its definition to achieve better readability on the display.

@dg0yt
Copy link
Member

dg0yt commented Nov 24, 2024

The colours, particularly the cyan colour, is far from realistic compared to the printing colours.

Fair enough.

Here's an algorithm that will, reasoably accurate, convert CMYK to RGB that are within the printing gammut:
...

Which environoment did you test these formulas with?
Are there any references?

This is what I learned in the past:

The CMYK/RGB conversion isn't part of Mapper's source code, but implemented in the Qt framework. This doesn't mean we couldn't integrate improvements. I'm just stating the fact.

@lpechacek
Copy link
Member

As an illustration.

Top left: OO Mapper (current master),
Top middle: Evince displaying a PDF exported from OCAD Viewer in CMYK color space.
Top right: LibreMapper with the proposed code change from comment #0.
Bottom middle: OCAD Viewer.

image

The patch.

diff --git a/src/core/map_color.h b/src/core/map_color.h
index e3a401eca273..0f2a8baf0844 100644
--- a/src/core/map_color.h
+++ b/src/core/map_color.h
@@ -579,7 +579,11 @@ MapColorCmyk::MapColorCmyk(const QColor& other) noexcept
 inline
 MapColorCmyk::operator QColor() const
 {
-       return QColor::fromCmykF(c, m, y, k);
+       double r = (1.0 - c) * (1.0 - m * 0.098) * (1.0 - k);
+       double g = (1.0 - c * 0.376) * (1.0 - m) * (1.0 - y * 0.070) * (1.0 - k);
+       double b = (1.0 - c * 0.109) * (1.0 - m * 0.505) * (1.0 - y) * (1.0 - k);
+
+       return QColor::fromRgbF(r, g, b);
 }
 
 inline

IMHO, it makes sense to make this change configurable as the differences in map appearance are substantial. In any case, I like the proposal. Thanks!

@lpechacek
Copy link
Member

differences in map appearance are substantial.

And a trivial test:

  1. Export map to PDF in Device CMYK mode.
  2. Add the map as a template, and align it with the existing map.
  3. Hide the map "layer" and show it again.
Screencast.From.2024-11-25.11-43-01.mp4

Mapper should be consistent with itself. :-)

@dg0yt
Copy link
Member

dg0yt commented Nov 26, 2024

Add the map as a template, and align it with the existing map.

@lpechacek Which GDAL binaries did you use in that test? I wonder how much this step is subject to the PDF backend in GDAL, possibly pulling in lcms2.

@arenol I would really appreciate some reference.

@lpechacek
Copy link
Member

@lpechacek Which GDAL binaries did you use in that test? I wonder how much this step is subject to the PDF backend in GDAL, possibly pulling in lcms2.

GDAL 3.10 on openSUSE Tumbleweed. But the result is roughly the same with a recent Windows build from Mapper CI. My guess is that Poppler interprets the PDF for GDAL on Linux. The PDF has the same color appearance in Evince, Inkscape, QGIS and Scribus, AFAICT.

I don't think that we need to perform full-blown colors management here. Adjust the colors so that they don't hurt user's eyes that much. My choice would be an attempt on replicating the OCAD calculation as users are used to it, so it can be considered as a "industry standard" and therefore widely accepted.

@lpechacek
Copy link
Member

My choice would be an attempt on replicating the OCAD calculation as users are used to it, so it can be considered as a "industry standard" and therefore widely accepted.

For there reference, this is the calculation:

	// OCAD-like transformation
	double r = (1.0 - c          ) * (1.0 - m * 0.00498) * (1.0 - y * 0.00703) * (1.0 - k);
	double g = (1.0 - c * 0.17416) * (1.0 - m * 0.89769) * (1.0 - y * 0.00272) * (1.0 - k);
	double b = (1.0 - c * 0.18420) *                       (1.0 - y * 0.91071) * (1.0 - k);
	return QColor::fromRgbF(r, g, b);

The constants were obtained like this:

  1. Take a map file with sample colors (a custom file with full C,M,Y and a few mixes, plus the IOF MC Print Test Sheet).
  2. Record CMYK combinations for the individual colors from the map file.
  3. Render the map file in OCAD Viewer with "color corrections". (the same corrections are employed for the on-screen display too)
  4. Sample the resulting RGB values from the image using Gimp.
  5. Throw all the CMYK and RGB values into one spreadsheet file. Model the above function, calculate the error squares.
  6. Optimize parameters of the non-linear transformation function with the LibreOffice Calc Solver tool.

@lpechacek
Copy link
Member

As a side note, this is how the color appearance issue was solved in Purple Pen: https://groups.io/g/purple-pen/topic/purple_pen_colors_different/87079064 (TL;DR: "Comparing colors on screen is really unimportant and a waste of time.")

As to my current knowledge, the IOF CMYK colors are in fact unspecified. It seems that there is no "standard CMYK" color model, so the CIE values of the individual process colors are not defined. I think that no one would be surprised these days that we need a geodetic datum to interpret spatial coordinates. The next step is to learn specifying color model along with the color component values.

@dg0yt
Copy link
Member

dg0yt commented Dec 8, 2024

I really wish the magic formulas from the original post would be backed by an external reference. Similar to us not using magic numbers in the source code.

As to my current knowledge, the IOF CMYK colors are in fact unspecified. It seems that there is no "standard CMYK" color model,

"Device-dependent" might be a sufficient identification of the desired CMYK color space, with 100% Cyan expected to be printed as 100% pure Cyan, regardless of the actual printer.

In need for color management and a device-independent CMYK color space, I would probably choose "ISO Coated v2 300% (ECI)" for European print shops. Combine this with "sRGB" for the computer screen. Pick representative pairs e.g. from gamutmap.com, and you have input for deriving simple formulas as a a proxy for proper color transformations. Not far away from the other two proposals, but with sound vendor-neutral reference points.

MapColorCmyk::operator QColor()

This can be modified to quickly demonstrate the effect, but for proper wiring, we may need to know whether we are rendering to a RGB screen, to a RGB printer driver, or to a CMKY PDF. If the custom CMYK-to-RGB transformation is enforced too early, the color might undergo another unmanaged RGB-to-CMYK transformation, leading to unexpected results.
The right hook might be near MapRenderables::draw or PainterConfig::activate. Maybe we also want to modify handling of the MapColor RGB aspect.

Last not least, an animation of the effect:
screenshot-rgb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants