-
-
Notifications
You must be signed in to change notification settings - Fork 37
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
CMYK Support #283
Comments
Why not just add a virtual method "applyColorTransform" and let each subclass decide how best to handle this? It would make it much cleaner for eg the raster/svg subclasses which need the extra logic. |
Thanks! few notes: If document color mode is CMYK would be very useful to see warning if there is any RGB colors in use. IMO Color mode belongs to Document properties (like in Indesign), not into Styles. |
I would agree to @frspp: In my previous workflows done with ArcMap the assignment of icc profile was done in Illustrator. |
To have a more generic approach, avoid duplicate code which are error prone, ease maintenance if we want to change the way we transform color. |
@eurojam @frspp Thanks for you comment, that the kind of user workflow details I am looking for. If you don't set the ICC profile in QGIS, you cannot have an on-screen estimated rendering of what it would look like on paper. Maybe you don't care but how do you manage to choose correctly your color for your map ? Krita for instance offers the option to select the ICC profile for the document. |
I can describe one of my previous workflows when I used ArcMap. The goal was to make a paper map, for example "geology map". Our customer has a list of color values in CMYK for each geology unit displayed in the map. In ArcMap there is no need to define or asign the color model to the project. If you choose a color for "unit 1" you will have three color options: RGB, HSV and CMYK. In the CMYK dialog I will enter the values given for unit 1 (see image below...) After finishing the map and Layout the next step starts, postprocessing in Adobe Illustrator which starts with the export of the map (layout). Depending on the export format, ArcMap offers different color spaces (CMYK for PDF, AI, EPS)... Preparing the final print version will be done in Adobe Illustrator, which has a lot of possibilites in PDF formats, ICC profiles and so one. I am not sure, if QGIS should cover all theese steps? |
@eurojam Thank you for the workflow description Setting ICC profile is interesting for 2 things:
Like you said, the first one could be done with another tool, even though it would be better to have it directly set by QGIS else user would have to be informed that there is another needed step to have a fully compliant CMYK PDF. Regarding the second one...
IMHO the tricky point is here because the CMYK color has to be defined regarding a given colorspace i.e the ICC profile used for printing. In your situation, you get the color and ICC profile from a customer so you don't really care about on-screen rendering but I can imagine that some users would like to fine pick the CMYK and check an overall rendering as close as possible as what it look like on a paper. I don't know if such user really exists (if so, please raise your hand 🙋 ) and if this is needed
Me neither 🤷♂️ , I would say yes ! |
@troopa81 I can imagine that some users would like to ... check an overall rendering as close as possible as what it look like on a paper. I would assume CMYK view without ICC would give a good color match to general printing on coated paper which has a wide color gamut (I mean wide on cmyk scale; such as Fogra39 profile; total ink around 350% I recall). And if map will be printed on uncoated paper then the designer should itself know that he/she needs to preview with uncoated ICC (such as Euronewspaper26), as the total ink is only around 240% I recall and by that the color space/gamut is much narrower. |
I really like the rest of the proposal, but I strongly disagree with a property based approach for color handling
On the contrary, going with a qt based introspection is likely to lead to ongoing issues. My arguments against would be:
|
@nyalldawson This is an implementation detail and I can live with a virtual method (which could call a function which would transform an array of given color members) but I would like to avoid as much as possible things like this or that where IMHO, there is too much copy-paste code.
I get your point but it is a classic use of reflection mecanism. Q_PROPERTY define statically a member with a pair of getter/setter, and the code will go through QColor only properties to read/write QColor, so I don't really see what compile time checks we would miss.
I would be in favor of relying less on qt-isms but what exactly is the policy here, because I count more than 300 Q_PROPERTY in QGIS code. It looks like we don't use QMetaClass/QMetaProperty though, so I imagine that we don't use Qt reflection system on purpose, for the reasons you just described.
Is it really? I would say it's widely used for good reason 🤷♂️ |
Noted, Krita has also a default ICC profile, which would be better than the default "naïve" conversion. I'm gonna amend the QEP to state that QGIS will embed a default ICC profile selected as soon as you select CMYK color space |
Agreed 👍 how about dropping these details from the qep and we'll discuss them in depth when it's time to start coding? From a high level perspective this qep looks great and I don't really want to get side tracked on specifics either! |
I'm gonna edit the QEP to state that the color transformation is still to be determined |
I know this might be out of the scope of this proposal, but can it be implemented with color management in mind? Right now, QGIS like Qt itself is assuming sRGB output. But color industry professionals have AdobeRGB-screens since forever, and the general public is getting more and more P3-display capable screens. It's useless to provide a ICC for the paper output and then just assuming the screen will be sRGB. Also, most "sRBG" screens out there are horribly misconfigured and don't even produce a picture within the range of the sRGB standard. So, without color management, I propose to ditch the ICC-profiles completely and warn users, that the colors on the screens do not represent the paper output! Without color management one can use the CMYK colors like index colors. You or your printer predefine the colors, you set them as CMYK in QGIS, the screen doesn't match the later output, which is fine, because you'll be softproofing in a color managed application, or your allowed colors for the map have been already set in advance.
Color picker and all gradients in QGIS have suffered under the current implementation. There is always linear blending between the RBG values (128,128,128 is not neutral gray!), but the output is rendered with gamma 2.2. For proper RGB gradients, one would need to perform mixing with linear gamma and convert it to display gamma. Same for the color space. A green, defined in sRGB, might be way to bright on Display-P3 or AdobeRGB. And CMYK mixing will give completely different gradients, as the color model is fundamentally different!
This only works, if the user's screen is exactly adhering to the sRGB-standard. For proper display, you need a calibrated and profiled screen and color management in your app. Or, you do it like in video and film and have a monitor with properly set primaries, then you don't need to profile.
This definitely needs color management and a complete overhaul of how colors are internally represented. You need to do all color work internally in a color space big enough to fit at least sRGB and ISO-coated, do all the calculations in linear gamma and convert only the output, on the fly, to display gamma and display color space. QGIS would need to remove its own, Qt-based painting engine and switch to e.g. krita's, as Qt is not color managed at all and always assuming RGB and sRGB. Currently, most users don't need color management. Only a fraction of GIS mapmakers actually calibrate and profile their screen. If they produce paper maps, they will likely get printed with desktop printers (I also conflate laser printers and ink plotters of copy shops into that category) and not offset printers. Or the maps will be viewed on uncalibrated and unprofiled computer screens. If your map will end up on a offset printer, you either have the expertise to set the colors or you hopefully have someone else to set it for you. Already being able to set CMYK colors directly would be of great use, as one can define all black lines and text as pure black. So, I would leave out everything, that only results in a half-hearted attempt on color management. So no ICC-profiles for CMYK unless there is also a way to convert to display gamut and not just sRGB. And think about a solution for color mixing, since without color management, RGB and CMYK will yield visually different results. |
I realise we're deferring this conversation, but I forgot to answer this bit to fill you in! Q_PROPERTY is only currently used in QGIS code for the sole purpose of exposing things for use in QML (ie by QField/Mergin client), or for custom widgets which are designed to be usable within Qt Designer. That's why there's a lot in master. |
@tannenfreund87 Thank you for your valuable comment. I am not an expert in that particular area so any comment is helpful to provide the best implementation in QGIS.
For now, I proposed a technical solution which makes only one conversion, from the ICC profile CMYK color space to the sRGB Qt output, but we could apply several transformations and have an extra transformation to the screen colorspace. Do you think it would be enough to implement what you're calling "color management"? It would require thorough testing to check if it is actually working/relevant.
I tend to disagree here. Imagine a user creates a QGIS project and sets up its CMYK colors to match a specific printer. Then imagine another user taking over this QGIS project without any communication with the former user. If there is no ICC profile within the project, he has no idea in what color space CMYK colors are described and he has to review all its color to match a new printer/colorspace. IMHO color space are like projection for coordinates. The later are kind of useless if you don't know in what projection they are used. PDF/X specification format forces to embed the targeted color space in the PDF file, so I would say that it's relevant to embed it in the QGIS project.
Anyway, I think you would never have perfect paper rendering on screen, the goal is to get closer as possible, and yes it does require a calibrated screen. Regarding color management in app, see my first comment.
Could you elaborate about what Qt is missing to be color managed?
To be honest, I asked myself this very question from the beginning, What do users actually want ? Like what ArcGIS proposes maybe (and I don't know exactly what's the CMYK color suppport in ArcGIS ? You mentioned Krita in your comment. QGIS, like this software, can be used to produced output that would be printed using offset printers. And Krita proposes to select the ICC profile and to work regarding this ICC profile. So why not proposing this in QGIS?
What do you mean by color mixing ? You mean blending a color when painting over another ? When on-screen rendering, it will indeed be done in RGB, not in CMYK color space, so you would not get the color you would get on paper. You would have the issue only if you have transparency but that's a limitation we can live with I think. |
That makes complete sense. I think using property is not fondamental here and I can avoid duplicate code with helper methods. |
Great initiative. It would be fantastic if Qgis could be used to generate products for offset printing. |
@AAnderl I don't know much about Spot colors but I'm pretty sure that they are out of the scope of this proposal. From what I understand, that would require to define a way to select them, to encode them correctly into a QGIS project and to properly write them in a PDF export (meaning that it would require probably some Qt development).
No sure to understand what you mean here, could you elaborate? |
@troopa81 I will try to explain. In the offset printing process, the image to be printed is broken down into the 4 process colors (C, M, Y, K) and a printing plate is made for each of them. The image will be transferred in 4 stages onto the blank paper, and each color is applied on top of the previous one. For the process to be successful, it is essential that each color is applied to the paper in the exact place. When this does not happen, we say there are registration issues. The perfect plate registration does not exist. Fortunately, a minimal deviation goes unnoticed in most cases. Other times, however, a deviation, even if minimal, can be very evident and ruin the entire print. For example, imagine that in my design I include 0.1 mm lines that extend across the entire surface of the design and I do not take the precaution of assigning them a solid color (C, M, Y, or K). In this case, that 0.1 mm line would be broken down into the four plates and would require a very, very precise registration accuracy. This could be the case, for example, with contour lines, and to avoid registration problems, it is common to assign them a Spot color. This color requires an additional plate and, therefore, a fifth printing plate (or an extra color change) in offset printing. I'm afraid that assigning spot colors is mandatory when it comes to printing maps because it is certain that the design will include grid lines, contour lines, or both. If it were not possible, these lines would have to be assigned one of the process colors, which is a significant limitation. |
Totally disagree - I have never used spot colors in maps. I make everything in RGB/CMYK and at least where I live CMYK registration has always been excellent. I have worked with offset printing presses for past 15 years. |
@AAnderl Thank you for you detailed informations, I have a better understanding now. Implementing CMYK in QGIS is a step forward to have a better printing capabilities. Like I said before, Spot color is beyond the scope of this proposal and would require further development (in QGIS and probably Qt). If you are interested in funding or know someone that would be interested, please let me know. |
I've just had a look to the new CMYK mode in the color widget and I am wondering about that the CMYK values are between 0 - 255. Normally they should be between 0 - 100 %. |
@eurojam What version are you using ? CMYK components are in percent in 3.40 see qgis/QGIS#58376 |
I am just on 3.38.3, but if it comes with 3.40 in percent that would be great. I am aware that PDF export does not keep the CMYK colors so far, I suppose this will come with Qt6 in the near future. May be we can fund the upcoming features with CMYK support, depending on the decission of the company head...I will ask them... |
This has been already done, by KDAB for the Qt part and myself (Oslandia) for the QGIS part. And yes, the PDF export works only in Qt 6 (because QT 6 is EOL so all new features land in Qt 6), but you can test it using QGIS Qt 6 unofficial version OSGeo4W (qgis-qt6-dev version). |
Development has been completed and is available in QGIS 3.40 Qt 6. The rendering part, allowing users to have an on‑screen preview of how their document’s colors will look when reproduced on a specific device has not been implemented because I don't think there is a great user need. If you think otherwise, and/or willing to fund this part, please let me know. Until then, I close the issue. |
Hi Julien,
I will ask the head of WhereGroup, if they will fund this part. How much
money are we talking about here?
I've tested the export with CMYK with the qt6 nightly build from last
night, and there are some issues open:
- it is possible to mix colors models in one map, the color model is not
assigned to the document (e.g. the layout)
- opening the exported pdf in Illustrator shows, that the colors have
arbitrary CMYK values, not the defined values from qgis symbology
so far my first experiences...
best regards
Stefan
Am Di., 1. Okt. 2024 um 10:30 Uhr schrieb Julien Cabieces <
***@***.***>:
… Development has been completed and is available in QGIS 3.40 Qt 6.
The rendering part, allowing users to have an on‑screen preview of how
their document’s colors will look when reproduced on a specific device has
not been implemented because I don't think there is a great user need. If
you think otherwise, and/or willing to fund this part, please let me know.
Until then, I close the issue.
—
Reply to this email directly, view it on GitHub
<#283 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ALBUG2IPQJVSBBSLZ6IGRWLZZJMRHAVCNFSM6AAAAABD3WVZNSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGOBVGEZDKNRTGE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Hi Stefan, Actually we are still depending on Qt 6.6 and so we don't ship last Kdab development in 6.8. My mistake, I believed we were already on Qt 6.8. Qt 6.8 was expected for september 2024 so it should be released soon. Then, we would have to update our packaging. I don't know how long it takes, and I don't know if we have special policy on potential minimal Qt patch version we are relying on (I see we are currently on 6.6.3, could we imagine be on 6.8.0 @jef-n when its out ? ) That explains your issues. Regarding the remaining part requiring funding, I'll answer you by mail. |
We also would have to wait for PyQt 6.8, so a little more delay... |
Strongly appreciate this development and very detailed documentation! A question to the timeline: In QGIS 3.40 the CMYK-Export doesn't work yet. In the chapter limitations the complete support for CMYK is estimated with QGIS 4.XX. When will that be? The roadmap ends in January 2026 with v3.46. So no official support in 2025? |
@jsehner - CMYK is already available in QGIS 3.40 - however, only if QGIS was built against Qt 6. Our standard builds are still built against Qt5, because a switch to Qt6 would break most Python plugins. In short: if you want CMYK support in QGIS, please install (in parallel) a Qt6 version. The OSGeo4W installer contains both the Qt5 and the Qt6 versions: Select the qgis-qt6-dev versions It might be a while until we enable Qt6 for the standard version because of the Python compatibility issues mentioned above ... so until then, please use the "qgis-qt5-dev" version - which can be installed and run in parallel with the Qt5 versions. |
Not only qt6, but Qt 6.8 like I described here. I'm actually working on building a QGIS CMYK Qt 6.8 preview version. I hope it would be avaiable for testing next week |
CMYK Support
Date 2024/02/27
Author Julien Cabieces (@troopa81)
Contact julien dot cabieces at oslandia dot com
maintainer @troopa81
Version QGIS 3.38/3.40 (with a Qt 6 version)
Summary
CMYK support has been requested for a long time.
QGIS.org is actually funding Qt developments so it could support CMYK colorspace PDF rendering (you can take a look at this article if you want to know more about CMYK). This QEP describes the needed modifications into QGIS in order to be able to generate PDF layout/report using CMYK defined colors.
At the moment, it is already possible to use CMYK color in QGIS symbology BUT the CMYK defined color is then converted into RGB, resulting in a loss of color data and color shifts. The goal of this proposal is to be able to write native CMYK colors in PDF so it could be printed using CMYK components, not RGB components.
Limitations
Only in Qt 6
As it will be a new Qt feature, it won't be available in Qt 5 and will land in Qt 6 only (exact version is still to be determined). As a consequence, complete support for CMYK in QGIS will only be available with QGIS 4.XX version (or maybe a Qt6 preview non-official-3.XX-version).
However most of the development described hereafter is Qt 5 compatible and I hope it will be integrated into QGIS 3.38.
Only in PDF
Current Qt development will allow to:
But it will not be possible to paint natively in a CMYK image, and therefore on the screen. The reasons are that it would bring too much effort, complexity and further maintenance in Qt code. As a result, on-screen rendering or image rendering will convert on the fly the possible CMYK defined colors to RGB colorspace BEFORE the rendering.
Proposed Solution
Set project to CMYK colorspace
CMYK color definition is only meaningfull if it is done respectfully to the color space targeted for printing. If a user wants to work with CMYK colors, he needs to select the ICC profile of the device he plans to print on. This has to be done in the early stage of its project definition, meaning in project properties.
From the Styles tab of project properties, it will be possible to set :
QgsFileWidget
, enabled only when color model is CMYK, will allow to select the ICC profile to be used for this project. It will also inform the user if the loaded file is a valid profile or not.The profile will be added as an attached file using
QgsProject::createAttachedFile
method.A default ICC profile, still to be determined, would be embedded into QGIS and set when CMYK mode is enabled.
If CMYK color is used and QGIS is built upon Qt 5, a message will be displayed so user know that CMYK support will be incomplete.
CMYK widget selector
Color picker has to be modified to allow selecting a color in CMYK color space. I propose to add a combo box in order for the user to select the color model, either RGB/HSV or CMYK.
color picker in RGB mode
color picker in CMYK mode
Current color profile should be displayed to let the user know that color on-screen output will be adapted to current selected color profile (see rendering).
Color preview
color preview
If color is a CMYK defined color, HSV/RGB informations will be replaced with CMYK ones.
default color
Default color initialization (here for instance) has to be adaptated to return a CMYK color if CMYK mode is enabled within the project.
Expressions
In expressions, it is possible to build a color using some color functions (color_cmyk(a), color_rgb(a)..). All these methods convert the defined color in rgb and return a string representation of it. As discussed above, we want to avoid the CMYK to RGB conversion so that we can write CMYK colors in our generated PDF.
In order to keep API compatibility, I propose to add another set of color functions which will return a plain QColor instead of a string representation of it. for each
color_XXXX
function, I propose to deprecate it and add aqcolor_XXXX
instead.The default string representation of QColor has to be implemented to match the current one as best as possible, so it will be easy to migrate, although it will not be possible to be idempotent (qcolor_rgb and qcolor_rgba will get the same representation while alpha is not displayed with color_rgb version).
Implement Color ramp
A CMYK color interpolation algorithm has to be implemented using CMYK components without converting to RGB. A classic linear interpolation will be applied on each component like it is done for RGB interpolation algorithm.
Generating PDF
Print services often requires PDF/X format as input. This PDF format is specially adapted for printing because it enforces some already existing PDF features being mandatory when it comes to printing. Fox example, embedding fonts to be sure that the rendering would be the same for printer for instance.
Qt does not support this format at the moment. It does not allow setting the color profile for the output PDF file neither . These two limitations will have to be removed if we want to be able to print a correct CMYK PDF file.
PDF/X format (when available) will be choosen over default PDF 1.4 version when the user selects a CMYK color model in his project.
Rendering
As described above, when choosing to work in CMYK mode, we target a specific printer for the generated PDF layout/report. In that case, users may want to have an on‑screen preview of how their document’s colors will look, when reproduced on this specific device.
Qt applies a default "naïve" transformation for colors defined in CMYK mode when it comes to draw on an RGB device.
In order to get closer to what the color will actually look like on the printing device, we need to use
QColorSpace
to load selected ICC profile file, and create aQColorTransform
to transform CMYK defined colors from the selected ICC profile to the sRGB color space QColorSpace::SRgb, which Qt operates in by default.As a consequence, when CMYK mode is enabled, we need to convert all colors before painting.
Here is the proposed solution to do so, in order to be the less invasive as possible in rendering code.
Color transform & Render context
QgsColorTransform
will wrap Qt classesQColorSpace
andQColorTransform
and provide a method to make conversions.QgsMapSettings
andQgsRenderContext
will own an instance of this object, retrieved fromQgsProject
for the former and transferred to the later in theQgsRenderContext::fromMapSettings
method.Additionally, This class could also define other helper methods to transform QGIS classes which have colors (QgsSymbolLayer, QgsTextFormat, QgsPropertyCollection)
Vector layer
Indentifying color attributes
In order to be able to transform colors dynamically, we need to be able to identify symbol layer color attributes. To achieve this,
QgsSymbolLayer
class and those which inherits from it should use theQ_PROPERTY
macro to expose theirs attributes as properties.These classes are not
QObject
classes so theQ_GADGET
macro should be added.EDIT: This part is still under discussion. An alternative could be to let children classes implement a applyColorTransform method (using maybe an helper method taking array of colors as arguments).
Applying the color transformation
The transformation should take place in the
QgsSymbol::startRender
method which, if a color transform has been defined in the render context, will :QMetaObject
/QMetaProperty
Data defined property
When applying color transformation, a new
QgsColorTransformer
implementing theQgsPropertyTransformer
interface will be added on every data defined color properties.This class will apply the given color transformation to the property value if it is a CMYK defined color.
Image symbol layer
Symbol layers using images (QgsRasterFillSymbolLayer) will have to transform their image (if this one is a CMYK one) using the
QgsColorTransform
stored in the render context in theirstartRender
methods.Image reading/loading is done at rendering (because it could depend on a per feature data dependency for instance) and rely on
QgsImageCache
to avoid reading the image from disk for every feature (here for instance).As a consequence,
QgsImageCache::pathAsImage
will take an additionnalQgsColorTransform
parameter in order to return a CMYK image transformed.We assume here that the image color profile will be identical to the one selected for the project. If not, QGIS will raise a warning message.
QgsLinePatternFillSymbolLayer
andQgsPointPatternFillSymbolLayer
generate their own image thanks to color attributes, so nothing more should be done once we expose the color attributes as properties.QgsSVGFillSymbolLayer
cannot support CMYK SVG and transform them. Indeed, SVG Tiny 1.2 only supports RGB colors and is the only version supported in Qt. It looks like it is possible with SVG Color specification 1.2 though, but it would be a long road before being integrated into Qt.Raster layer
As it will not be possible to paint natively into a CMYK image, it will not be possible to generate CMYK image into a CMYK output PDF. So, there is no point in defining CMYK colors for raster layer.
We could consider develop soft-proofing in order to transform raster RGB working colors to CMYK space and then to screen device, so we can have a better estimation about how raster would look like when printed. This option has been developed in software like Krita or GIMP but I am not not sure that this would be something that QGIS users are interested in. For now, I consider it beyond the scope of this QEP.
Labels
The same approach as for vector layers should be used for labels. Inside QgsPalLayerSettings::startRender
QgsTextFormat
will be converted and aQgsColorPropertyTransformer
will be added to data dependencies.Other map layers
The same approach as for vector layers will be used in order to properly deal with others map layers (QgsMeshLayer, QgsGroupLayer, QgsAnnotationLayer, ...) going through the same steps :
This could represent a lot of work and could also be impossible for some layer type. QgsMapLayer should advertise whether or not color transform is supported by this map layer so that QGIS will display a warning message if his project contains map layers not supported, and CMYK mode is enabled.
Layout objects
The same approach as vector layers will be used. Inside QgsLayoutItem::paint, color properties will be converted before the call to the draw() method and then restored to their initial value after.
Tests
Automatic tests will be added in order to check that PDF output is consistent with what is expected, using the
qpdf
and the technique akin to vector selective masking one.Affected Files
Performance Implications
These modifications will have no impact on QGIS when CMYK mode is disabled. When enabled, it will only cost the color transformation which is not significant.
Backwards Compatibility
Nothing will break backward compatiblity.
Issue Tracking ID(s)
Votes
(required)
The text was updated successfully, but these errors were encountered: