9

I'm looking for an algorithm to convert an RGB color to CMYK. Photoshop is performing the conversion below:

R = 220 G = 233 B = 174

C = 15 M = 0 Y = 40 K = 0

Junior Developer
  • 161
  • 1
  • 1
  • 4
  • 1
    This seems to be about the algorithm itself; if you just want CMYK from RGB and don't care how it's done, just use ImageMagick/Magick.Net, as is being asked and answered here: http://stackoverflow.com/questions/10032335/how-can-i-convert-an-uploaded-image-of-rgb-format-to-cmyk-format-in-net – Chris Moschini Jul 22 '15 at 15:50

7 Answers7

10

The conversion from RGB to CMYK is dependent on the physical device/process being used to lay down the CMYK ink. These are represented in software as Color Profiles. ICC and ICM color profiles of physical devices determine the resulting colors.

If you are not concerned with true representation on a physical device then use the direct conversion formulas in other posts.

If, however, you are concerned with this aspect, then you need to use a either the Windows Color Management APIs or something like LittleCMS to do the color conversions for you (as they apply the proper color profile during the conversion).

8

Check out this link: http://www.codeproject.com/KB/applications/xcmyk.aspx. It gives this formula.

Black   = minimum(1-Red,1-Green,1-Blue)
Cyan    = (1-Red-Black)/(1-Black)
Magenta = (1-Green-Black)/(1-Black)
Yellow  = (1-Blue-Black)/(1-Black) 
37Stars
  • 2,489
  • 20
  • 23
  • 2
    Note: While the conversion comes close, most of the time it won't match photoshop. Comparing the generated colors in photoshop will often produce different results too. There's no direct conversion, but it's often close enough. – Will Eddins Mar 11 '10 at 16:17
  • The code found here is using the formula above: http://www.javascripter.net/faq/rgb2cmyk.htm – Junior Developer Mar 11 '10 at 16:47
  • 5
    Also important to note that the above formula assumes Red, Green and Blue have been normalised (between 0.0 and 1.0). – Dominique McDonnell Mar 08 '11 at 22:25
  • @DominicMcDonnell can we say that the taking minimum of **RGB** for **black** is _correct_ ? Because some websites have formulas with maximum , for example [Rapid Tables Website](http://www.rapidtables.com/convert/color/rgb-to-cmyk.htm) . Why there are difference formulas with **minimum** & **maximum** , i did not understand. – eemrah May 23 '17 at 23:16
  • 1
    @wade-watt formula in that website: 1-max(r,g,b). 1-max(r,g,b) == min(1-r, 1-b,1-g). It's a different way of calculating the same thing. – Dominique McDonnell May 29 '17 at 00:46
  • oh , i just realized that , here is the different formulas with to same calculation , Thanks – eemrah Jun 02 '17 at 23:59
4

If you want good result, you need to apply a color profile. In .NET, you can do it like that (assuming the the original CMYK components are in the range between 0 and 255):

float[] colorValues = new float[4];
colorValues[0] = c / 255f;
colorValues[1] = m / 255f;
colorValues[2] = y / 255f;
colorValues[3] = k / 255f;

System.Windows.Media.Color color = Color.FromValues(colorValues,
    new Uri(@"C:\Users\me\Documents\ISOcoated_v2_300_eci.icc"));
System.Drawing.Color rgbColor = System.Drawing.Color.FromArgb(color.R, color.G, color.B);

Note that two different Color classes from two different namespaces are used. And you probably need to add the PresentationCore DLL as a reference.

The required color profile can be downloaded from the downloads section of eci.org. It's part of a bigger ZIP file containing several profiles. They explicitly recommend to use the ISO Coated v2 300% (ECI) profile.

If you need to convert a complete image from CMYK to RGB, there are special classes for this in the same namespace.

Codo
  • 75,595
  • 17
  • 168
  • 206
3

My complete example for C# conversion between CMYK <-> HEX:

public class ColorConverter
{
    public static string CMYKtoHex(decimal[] cmyk)
    {
        if (cmyk.Length != 4) return null;

        var r = (int)(255 * (1 - cmyk[0]) * (1 - cmyk[3]));
        var g = (int)(255 * (1 - cmyk[1]) * (1 - cmyk[3]));
        var b = (int)(255 * (1 - cmyk[2]) * (1 - cmyk[3]));

        var hex = "#" + r.ToString("X2") + g.ToString("X2") + b.ToString("X2");
        return hex;
    }

    public static decimal[] HexToCMYK(string hex)
    {
        decimal computedC = 0;
        decimal computedM = 0;
        decimal computedY = 0;
        decimal computedK = 0;

        hex = (hex[0] == '#') ? hex.Substring(1, 6) : hex;

        if (hex.Length != 6)
        {
            return null;
        }

        decimal r = int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
        decimal g = int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
        decimal b = int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);

        // BLACK
        if (r == 0 && g == 0 && b == 0)
        {
            computedK = 1;
            return new[] { 0, 0, 0, computedK };
        }

        computedC = 1 - (r / 255);
        computedM = 1 - (g / 255);
        computedY = 1 - (b / 255);

        var minCMY = Math.Min(computedC, Math.Min(computedM, computedY));

        computedC = (computedC - minCMY) / (1 - minCMY);
        computedM = (computedM - minCMY) / (1 - minCMY);
        computedY = (computedY - minCMY) / (1 - minCMY);
        computedK = minCMY;

        return new[] { computedC, computedM, computedY, computedK };
    }
 }
Martin S
  • 39
  • 3
2

I agree with the previous answers, but I want to say that:

if ( K == 1 ) 
{ 
   C = 0
   M = 0
   Y = 0
} 

It can be if r = g = b = 0.

0

I think photoshop uses profile based conversions. Have a look at the documentation for the color options. If it is the case you won't be able to match this behavior with simple formula based solutions.

I have found LCMS to be very handy, simple and efficient for this kind of task.I don't known if there is any .net binding for it...

user18428
  • 1,216
  • 11
  • 17
0

For convert RGB to CMYK you can use ColorHelper library.

using ColorHelper;
RGB rgb = new RGB(220, 234, 174);
CMYK cmyk = ColorConverter.RgbToCmyk(rgb);

Conversion algorithm in this library:

public static CMYK RgbToCmyk(RGB rgb)
{
    double modifiedR, modifiedG, modifiedB, c, m, y, k;

    modifiedR = rgb.R / 255.0;
    modifiedG = rgb.G / 255.0;
    modifiedB = rgb.B / 255.0;

    k = 1 - new List<double>() { modifiedR, modifiedG, modifiedB }.Max();
    c = (1 - modifiedR - k) / (1 - k);
    m = (1 - modifiedG - k) / (1 - k);
    y = (1 - modifiedB - k) / (1 - k);

    return new CMYK(
        (byte)Math.Round(c * 100),
        (byte)Math.Round(m * 100),
        (byte)Math.Round(y * 100),
        (byte)Math.Round(k * 100));
}

Link - https://github.com/iamartyom/ColorHelper/blob/master/ColorHelper/Converter/ColorConverter.cs

progm
  • 2,782
  • 3
  • 14
  • 32