[comp.graphics] conversion from RGB to CMYK

paul@manray.sgi.com (Paul Haeberli) (02/16/90)

Here is a little code fragment that converts from rgb to CMYK.
We have used this transformation for several years as part of
the process of creating digital color separations for various 
publications. 

Paul Haeberli 
paul@sgi.com

/*
 *	rgb_to_cmyk -
 *		Convert from rgb to cmyk.  This implements 100% 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. 
 *
 *				Paul Haeberli - 1988
 *		
 */
#define ULTRAC		160
#define ULTRAM		160
#define ULTRAY		0
#define ULTRAK		255
#define BLACKLERP	4

rgb_to_cmyk(r,g,b,c,m,y,k)
register int r, g, b;
int *c, *m, *y, *k;
{
    register int i;
    float param; 

/* 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 k plus some m and c */
    if(i == 0) {
	*c = ULTRAC;
	*m = ULTRAM;
	*y = ULTRAY;
	*k = ULTRAK;
	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;

/* if i is less than blacklerp start lerp towards ultra-black */
    if(i<BLACKLERP) {
	param = ((float)i)/((float)BLACKLERP);
	*c = lerp(ULTRAC,*c,param);
	*m = lerp(ULTRAM,*m,param);
	*y = lerp(ULTRAY,*y,param);
	*k = *k;
    }
}

lerp(i0,i1,p)
int i0, i1;
float p; 
{
    return ((i0*(1.0-p))+(i1*p));
}

buck@drax.gsfc.nasa.gov (Loren (Buck) Buchanan) (02/16/90)

In article <50957@sgi.sgi.com> paul@manray.sgi.com (Paul Haeberli) writes:
>#define ULTRAC		160
>#define ULTRAM		160
>#define ULTRAY		0
>#define ULTRAK		255
>#define BLACKLERP	4

How did you come up with this constants?  I assume that these are the
values you use for making separations for IRIS Universe (coated stock
and a fairly standard ink set).

B Cing U

Buck

Loren "Buck" Buchanan | internet: buck@drax.gsfc.nasa.gov | standard disclaimer
CSC, 1100 West St.    | uucp: ...!ames!dftsrv!drax!buck   | "By the horns of a
Laurel, MD 20707      | phonenet: (301) 497-2531 or 9898  | sky demon..."

cooper@arisia.Xerox.COM (Martin F N Cooper) (02/22/90)

It's my understanding that since CMYK is basically a device dependent
colour representation intended for optimising colour rendition on a
specific device, the actual transformation of RGB into CMYK must take
into account the device characteristics. This implies that any procedure
to perform such transformation must be parameterised with device
characteristics. Did I get something wrong, or was the posted code
fragment indeed tied to a particular device? I'd be interested in
hearing views on how parameterisation might be done, too.

	Martin.