4

I have been trying for some time to color grade a geological map according to CMYK values given in the attribute table. I have not yet succeeded. I am certain that is just a simple line of code that is needed and hope some of you can help me.

I am currently using QGIS 3.14. The column that I want to grade to colors after are the "cmykFargekode" column.

1
  • Have a look at data defined override (of symbol colours).
    – Erik
    Aug 27, 2020 at 14:21

2 Answers 2

6

Why so complicated Yoann Quenach de Quivillic ?

  1. Step 1 (the same) : Open the Layer Styling panel to set a data-defined color
  2. Step 2 : copy the formula in the expression builder eval('color_cmyk(' || "cmykFargekode" || ')')

EDIT

  1. Step 2 (bis) : here the formula without eval() function :

    with_variable('cmyk', string_to_array("cmykFargekode"),
        color_cmyk(
            @cmyk[0],
            @cmyk[1],
            @cmyk[2],
            @cmyk[3]
        )
    )
    
1
  • Oh, I was not aware of the with_variable syntax! Neat. Also, nice trick with the eval function. Aug 28, 2020 at 8:22
4

Since you mention you're a rookie, here is a detailed step-by-step guide :

Open the Layer Styling panel to set a data-defined color

enter image description here

  • Right click on the layer in the layer tree, and click Properties... to open the above panel
  • Click on Symbology (1) to open the layer styling tab
  • Click on Simple Fil (2) to configure symbol
  • Click on the button on the right of the fill color field (3)
  • Click on Edit to open the expression builder

Define a conversion function

Here are the CMYK to RGB conversion formula

r = 255 * (1-c) * (1-k)
g = 255 * (1-m) * (1-k)
b = 255 * (1-y) * (1-k)

The QGIS expression builder already includes a bunch of color-related functions, but unfortunately for you, none which convert a cmyk string to a rgb string. But you can easily add your own functions.

create_function

  • Click on the Function Editor tab (1)
  • Replace the content of the function panel (2) with the following code:
from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Color')
def cmyk_to_rgb(cmyk_string, feature, parent):
    """ Convert a cmyk color string to a rgb color string """
    c,m,y,k = [int(val)/100 for val in cmyk_string.split(',')]
    r = str(int(255 * (1-c) * (1-k)))
    g = str(int(255 * (1-m) * (1-k)))
    b = str(int(255 * (1-y) * (1-k)))
    return ",".join((r,g,b))
  • Click on the "Save and Load Functions" button
  • You can now use the newly-defined cmyk_to_rgb in the expression builder

Use the Expression Builder

Expression

  • Almost done now. Go back to the Expression tab (1)
  • Type cmyk_to_rgb( "cmykFargekode") in the Expression Field (2)
  • Press Ok (3)

This should do the trick.


Edit

QGIS provides a function color_cmyk that takes 4 integers (or string representation of integers) as input. As J. Monticolo pointed out, you can actually use the default QGIS functions to build an expression that performs the task. The whole "Define a conversion function" step can thus be avoided.

eval('color_cmyk(' || "cmykFargekode" || ')')

Explanation:

  • "cmykFargekode" is expanded to say '47,0,80,0'
  • It is then concatenated (|| syntax) with 'color_cmyk(' and ')' which gives the string 'color_cmyk(47,0,80,0)'
  • This string is evaluated with the eval function and tadaa!

The other suggested approach relies on the with_variable syntax

with_variable('cmyk', string_to_array("cmykFargekode"),
    color_cmyk(@cmyk[0], @cmyk[1], @cmyk[2], @cmyk[3])
)

Explanation:

  • "cmykFargekode" is expanded to say '47,0,80,0'
  • string_to_array converts the string to an array ['47', '0', '80', '0']
  • with_variable stores this array in a variable called 'cmyk', which is then accessible in the second part of the expression as `@cmyk'
  • The second part of the expression color_cmyk(@cmyk[0], @cmyk[1], @cmyk[2], @cmyk[3]) is evaluated
1
  • 1
    You have built-in functions for that, they are maintained, faster (C++) ... This answer is well documented yes, but not the simpliest and better answer IMHO. Aug 27, 2020 at 18:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.