Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1992, 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gxdcconv.c,v 1.6 2002/08/22 07:12:29 henrys Exp $ */
18
/* Conversion between device color spaces for Ghostscript */
19
#include "gx.h"
20
#include "gsdcolor.h"		/* for gxcmap.h */
21
#include "gxdcconv.h"		/* interface */
22
#include "gxdevice.h"		/* for gxcmap.h */
23
#include "gxcmap.h"
24
#include "gxfarith.h"
25
#include "gxlum.h"
26
#include "gxistate.h"
27
 
28
/*
29
 * The CMYK to RGB algorithms specified by Adobe are, e.g.,
30
 *      R = 1.0 - min(1.0, C + K)
31
 *      C = max(0.0, min(1.0, 1 - R - UCR))
32
 * We got better results on displays with
33
 *      R = (1.0 - C) * (1.0 - K)
34
 *      C = max(0.0, min(1.0, 1 - R / (1 - UCR)))
35
 * For utmost compatibility, we offer the Adobe algorithms as an option:
36
 */
37
#define USE_ADOBE_CMYK_RGB
38
 
39
/* ------ Color space conversion ------ */
40
 
41
/* Only 4 of the 6 conversions are implemented here; */
42
/* the other 2 (Gray to RGB/CMYK) are trivial. */
43
 
44
/* Convert RGB to Gray. */
45
frac
46
color_rgb_to_gray(frac r, frac g, frac b, const gs_imager_state * pis)
47
{
48
    return (r * (unsigned long)lum_red_weight +
49
	    g * (unsigned long)lum_green_weight +
50
	    b * (unsigned long)lum_blue_weight +
51
	    (lum_all_weights / 2))
52
	/ lum_all_weights;
53
}
54
 
55
/* Convert RGB to CMYK. */
56
/* Note that this involves black generation and undercolor removal. */
57
void
58
color_rgb_to_cmyk(frac r, frac g, frac b, const gs_imager_state * pis,
59
		  frac cmyk[4])
60
{
61
    frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
62
    frac k = (c < m ? min(c, y) : min(m, y));
63
 
64
    /*
65
     * The default UCR and BG functions are pretty arbitrary,
66
     * but they must agree with the ones in gs_init.ps.
67
     */
68
    frac bg =
69
	(pis == NULL ? k : pis->black_generation == NULL ? frac_0 :
70
	 gx_map_color_frac(pis, k, black_generation));
71
    signed_frac ucr =
72
	(pis == NULL ? k : pis->undercolor_removal == NULL ? frac_0 :
73
	 gx_map_color_frac(pis, k, undercolor_removal));
74
 
75
    if (ucr == frac_1)
76
	cmyk[0] = cmyk[1] = cmyk[2] = 0;
77
    else if (ucr == frac_0)
78
	cmyk[0] = c, cmyk[1] = m, cmyk[2] = y;
79
    else {
80
#ifdef USE_ADOBE_CMYK_RGB
81
	/* C = max(0.0, min(1.0, 1 - R - UCR)), etc. */
82
	signed_frac not_ucr = (ucr < 0 ? frac_1 + ucr : frac_1);
83
 
84
	cmyk[0] = (c < ucr ? frac_0 : c > not_ucr ? frac_1 : c - ucr);
85
	cmyk[1] = (m < ucr ? frac_0 : m > not_ucr ? frac_1 : m - ucr);
86
	cmyk[2] = (y < ucr ? frac_0 : y > not_ucr ? frac_1 : y - ucr);
87
#else
88
	/* C = max(0.0, min(1.0, 1 - R / (1 - UCR))), etc. */
89
	float denom = frac2float(frac_1 - ucr);		/* unscaled */
90
	float v;
91
 
92
	v = (float)frac_1 - r / denom;	/* unscaled */
93
	cmyk[0] =
94
	    (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
95
	v = (float)frac_1 - g / denom;	/* unscaled */
96
	cmyk[1] =
97
	    (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
98
	v = (float)frac_1 - b / denom;	/* unscaled */
99
	cmyk[2] =
100
	    (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v);
101
#endif
102
    }
103
    cmyk[3] = bg;
104
    if_debug7('c', "[c]RGB 0x%x,0x%x,0x%x -> CMYK 0x%x,0x%x,0x%x,0x%x\n",
105
	      r, g, b, cmyk[0], cmyk[1], cmyk[2], cmyk[3]);
106
}
107
 
108
/* Convert CMYK to Gray. */
109
frac
110
color_cmyk_to_gray(frac c, frac m, frac y, frac k, const gs_imager_state * pis)
111
{
112
    frac not_gray = color_rgb_to_gray(c, m, y, pis);
113
 
114
    return (not_gray > frac_1 - k ?	/* gray + k > 1.0 */
115
	    frac_0 : frac_1 - (not_gray + k));
116
}
117
 
118
/* Convert CMYK to RGB. */
119
void
120
color_cmyk_to_rgb(frac c, frac m, frac y, frac k, const gs_imager_state * pis,
121
		  frac rgb[3])
122
{
123
    switch (k) {
124
	case frac_0:
125
	    rgb[0] = frac_1 - c;
126
	    rgb[1] = frac_1 - m;
127
	    rgb[2] = frac_1 - y;
128
	    break;
129
	case frac_1:
130
	    rgb[0] = rgb[1] = rgb[2] = frac_0;
131
	    break;
132
	default:
133
	    {
134
#ifdef USE_ADOBE_CMYK_RGB
135
		/* R = 1.0 - min(1.0, C + K), etc. */
136
		frac not_k = frac_1 - k;
137
 
138
		rgb[0] = (c > not_k ? frac_0 : not_k - c);
139
		rgb[1] = (m > not_k ? frac_0 : not_k - m);
140
		rgb[2] = (y > not_k ? frac_0 : not_k - y);
141
#else
142
		/* R = (1.0 - C) * (1.0 - K), etc. */
143
		ulong not_k = frac_1 - k;
144
 
145
		/* Compute not_k * (frac_1 - v) / frac_1 efficiently. */
146
		ulong prod;
147
 
148
#define deduct_black(v)\
149
  (prod = (frac_1 - (v)) * not_k, frac_1_quo(prod))
150
		rgb[0] = deduct_black(c);
151
		rgb[1] = deduct_black(m);
152
		rgb[2] = deduct_black(y);
153
#undef deduct_black
154
#endif
155
	    }
156
    }
157
    if_debug7('c', "[c]CMYK 0x%x,0x%x,0x%x,0x%x -> RGB 0x%x,0x%x,0x%x\n",
158
	      c, m, y, k, rgb[0], rgb[1], rgb[2]);
159
}