[comp.graphics] RGB to printer CMYK conversion

paul@sgi.SGI.COM (Paul Haeberli) (02/02/88)

Someone asked about converting from RGB to prinyer CMYK.  Here is a
simple conversion technique.

			Paul Haeberli 

/*
 *	RGBtoCMYK -
 *		This program demonstrates an easy way to convert from
 *	RGB space to printer CMY and K.  This method does grey component 
 *	replacement, so achromatic parts of the image will be printed with 
 *	only black ink.  
 *
 *	R is red.	C is cyan.
 *	G is geen.	M is magenta.
 *	B is blue.	Y is yellow.
 *			K is black.
 *
 *		    Paul Haeberli / Silicon Graphics - 1987
 */
main()
{

/* print header */
    printf("r\tg\tb\t|\tc\tm\ty\tk\n");

/* transform the corners of the color cube */
    printf("-----------------------------------------------------------\n");
    printvals(0,0,0);
    printvals(0,0,255);
    printvals(0,255,0);
    printvals(0,255,255);
    printvals(255,0,0);
    printvals(255,0,255);
    printvals(255,255,0);
    printvals(255,255,255);

/* up one edge of the color cube */
    printf("-----------------------------------------------------------\n");
    printvals(0,0,0);
    printvals(0,0,32);
    printvals(0,0,64);
    printvals(0,0,128);
    printvals(0,0,192);
    printvals(0,0,255);

/* transform a few a chromatic colors */
    printf("-----------------------------------------------------------\n");
    printvals(0,0,0);
    printvals(1,1,1);
    printvals(16,16,16);
    printvals(32,32,32);
    printvals(64,64,64);
    printvals(128,128,128);
    printvals(192,192,192);
    printvals(255,255,255);
}

printvals(r,g,b)
int r, g, b; 
{
    int c,m,y,k;

    rgb_to_cmyk(r,g,b,&c,&m,&y,&k);
    printf("%d\t%d\t%d\t|\t%d\t%d\t%d\t%d\n",r,g,b,c,m,y,k);
}

/*
 *	rgb_to_cmyk -
 *		Convert from rgb to cmyk.  This implements grey component
 *	replacement. 
 *
 *	Inputs:
 *		r intensity 0 to 255
 *		g intensity 0 to 255
 *		b intensity 0 to 255
 *
 *	Outputs:
 *		c coverage 0 to 255
 *		m coverage 0 to 255
 *		y coverage 0 to 255
 *		k coverage 0 to 255
 *
 *
 *	An input value of rgb=[255,255,255] represents white.  When this is
 *	transformed to cmyk, we get cmyk=[0,0,0,0] which represents zero 
 *	coverage. 
 *
 *	An input value of rgb=[128,128,128] represents 50 percent grey.  When
 *	this is transformed to cmyk, we get cmyk=[0,0,0,127] which represents 
 *	zero coverage by cmy, and 50 percent coverage by black. 
 *
 */
rgb_to_cmyk(r,g,b,c,m,y,k)
int r, g, b;
int *c, *m, *y, *k;
{
    int i; 

/* i is the max of r, g, and b */
    i = 0;
    if(r>i)
	i = r;
    if(g>i)
	i = g;
    if(b>i)
	i = b;

/* if r, g and b are all zero then print full black */
    if(i == 0) {
	*c = 0;
	*m = 0;
	*y = 0;
	*k = 255;
	return;
    }
    r = (255*r)/i;
    g = (255*g)/i;
    b = (255*b)/i;
    *c = 255-r;
    *m = 255-g;
    *y = 255-b;
    *k = 255-i;
}

spencer@spline (Spencer W. Thomas) (02/03/88)

Paul's code is good, as far as it goes.  There is a more complete discussion of
this topic in the most recent (Third issue 1987 = Vol 1, No 3) PostScript
Language Journal.  It goes into derivation details and talks about alignment of
halftone screens.  One thing that is discussed there that Paul's code doesn't
do is "undercolor removal".  This is necessary because the inks aren't pure,
thus magenta ink typically appears to be contaminated by yellow, for example.
The code is similar to that used for black removal.

Anyway, the PSLJ is available from 
	The PSLJ
	P.O. Box 5763
	Parsippany, NJ  07054

Single issues are $5.

[I have no association with the PSLJ other than that of a happy reader.]
=Spencer (spencer@crim.eecs.umich.edu)

jonathan@hpisoa2.HP.COM (Jonathan Hue) (02/03/88)

>Someone asked about converting from RGB to prinyer CMYK.  Here is a
>simple conversion technique.

...which doesn't really produce anything useful.  If I had to do this,
(which I don't) here is what I would do:

Let's assume you have your system calibrated so that you can output
to a good film recorder (Dunn, Celco, Genigraphics, etc, but not a QCR)
and your transparency pretty much looks like your monitor.  Decide
what kind of paper and ink you are going to use.  Then, make a
Scitex CT2T magnetic tape of a bunch of color squares.  What would
probably be useful are the CMYK quads from (0,0,0,0) to (255,255,255,255)
in increments of 16.  Have a pre-press shop make a Cromalin from the
tape.  Next, make a transparency consisting of the RGB triplets from
(0,0,0) to (255,255,255) in little squares on your film recorder.  Then use
a transmission-reflection densitometer and measure the densities of your
17^3 RGB triplets and 17^4 CMYK quads.  Use a densitometer with an RS-232
on it so you don't have to write down all those numbers.  Interpolate the
17 levels of each color to some reasonable number, perhaps a number near a
hundred, maybe more for the CMYK quads.  Then map the RGB numbers into
the nearest CMYK quad.  Now you have an CMYK quad (for a given type of
ink and paper which is reasonably close to the RGB value you used to make
the color spot on your transparency.

This is what I thought of doing, other people presented with the same
problem have done the same thing as it's sort of the obvious thing to
do when you don't really understand the physics and math behind the
problem too well.  Some people think the results are pretty good.

This doesn't take too much work and you get way better results than
treating the inks as a "color space" which most people seem to
want to do for some reason, rather than real pigments.  If you are
smart I'm sure you can come up with a much better way, but at least
this does something useful.  If you have a big computer you can perhaps
interpolate 256^3 RGB triplets into 256^4 CMYK quads and get some
accurate numbers, even though you can't reproduce dots on the paper that
well.

Once you get this far it should be pretty easy to calibrate your monitor
to your transparency.  A color-tv analyzer (like Minolta's) would be
useful, and if you can find it, a densitometer that reads out in XYZ
or whatever that color space is called, I forget.

Jonathan Hue		..!hpda!jonathan

douglasg@hpgrla.HP.COM (@Douglas Genetten) (02/05/88)

Mr. Hue writes...

>...Then use
>a transmission-reflection densitometer and measure the densities of your
>17^3 RGB triplets and 17^4 CMYK quads... 

A common missunderstanding hides within this remark.  Densitomiters
DO NOT MEASURE NTSC RGB.  They typically measure using very narrow-
band filters which are designed to maximize sensitivity to variations
in process ink sets.  These filters block out most of the visible
spectrum---something you can't do if you want to measure color regardless
of the color space you use. These filters would have to have broad 
overlaping "standard observer" curves to make them useful for RGB 
measurement.

Using press room densities as estimates of NTSC RGB densities can cause
large objectionable color errors, especially when measuring strange 
pigments found in some color electronic printers.

A good alternative would be to use the Minolta Chroma Meter which is
a near-true "standard observer" colorimeter and measures using 
CIE XYZ and CIE LAB tristimuli.

Douglas Gennetten
Hewlett-Packard
Greeley Hardcopy Operation

raveling@vaxa.isi.edu (Paul Raveling) (02/10/88)

In article <4180010@hpgrla.HP.COM> douglasg@hpgrla.HP.COM (@Douglas Genetten) writes:
>Mr. Hue writes...
>
>>...Then use
>>a transmission-reflection densitometer and measure the densities of your
>>17^3 RGB triplets and 17^4 CMYK quads... 
>
>A common missunderstanding hides within this remark.  Densitomiters
>DO NOT MEASURE NTSC RGB.  They typically measure using very narrow-
>band filters which are designed to maximize sensitivity to variations
>in process ink sets.  These filters block out most of the visible
>spectrum---something you can't do if you want to measure color regardless
>of the color space you use. These filters would have to have broad 
>overlaping "standard observer" curves to make them useful for RGB 
>measurement.
>
>Using press room densities as estimates of NTSC RGB densities can cause
>large objectionable color errors, especially when measuring strange 
>pigments found in some color electronic printers.
>
	It sounds as if there's a specialized densitometer for
	printers.  About 10 years ago I used a transission/reflection
	color densitometer in Werner Frei's medical imaging group
	to get good RGB/CMYK measurements for color darkroom work.
	I don't recall the exact tolerances from its filter
	calibrations, but something under 1% in visible light
	seems familiar.

	Does anyone know if there are reasonably priced color
	densitometers available now?  Ability to do decent
	color measurements would help some aspects of our project
	(the ones dealing with digitized color maps), but
	the requirement isn't strong enough to warrant the
	$2,000+ price tag, in ~1978 dollars, of the instrument
	I mentioned above.


---------------------
Paul Raveling
Raveling@vaxa.isi.edu