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) 1989, 1995, 1996, 1998, 1999 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: gxdevndi.c,v 1.6 2005/05/05 05:35:22 dan Exp $ */
18
#include "gx.h"
19
#include "gsstruct.h"
20
#include "gsdcolor.h"
21
#include "gxdevice.h"
22
#include "gxlum.h"
23
#include "gxcmap.h"
24
#include "gxdither.h"
25
#include "gzht.h"
26
#include "gxfrac.h"
27
#include "gxwts.h"
28
 
29
/*
30
 * Binary halftoning algorithms.
31
 *
32
 * The procedures in this file use halftoning (if necessary)
33
 * to implement a given device color that has already gone through
34
 * the transfer function.  There are two major cases: gray and color.
35
 * Gray halftoning always uses a binary screen.  Color halftoning
36
 * uses either a fast algorithm with a binary screen that produces
37
 * relatively poor approximations, or a very slow algorithm with a
38
 * general colored screen (or screens) that faithfully implements
39
 * the Adobe specifications.
40
 */
41
 
42
/* Tables for fast computation of fractional color levels. */
43
/* We have to put the table before any uses of it because of a bug */
44
/* in the VAX C compiler. */
45
/* We have to split up the definition of the table itself because of a bug */
46
/*  in the IBM AIX 3.2 C compiler. */
47
private const gx_color_value q0[] = {
48
 
49
};
50
private const gx_color_value q1[] = {
51
    0, frac_color_(1, 1)
52
};
53
private const gx_color_value q2[] = {
54
    0, frac_color_(1, 2), frac_color_(2, 2)
55
};
56
private const gx_color_value q3[] = {
57
    0, frac_color_(1, 3), frac_color_(2, 3), frac_color_(3, 3)
58
};
59
private const gx_color_value q4[] = {
60
    0, frac_color_(1, 4), frac_color_(2, 4), frac_color_(3, 4),
61
    frac_color_(4, 4)
62
};
63
private const gx_color_value q5[] = {
64
    0, frac_color_(1, 5), frac_color_(2, 5), frac_color_(3, 5),
65
    frac_color_(4, 5), frac_color_(5, 5)
66
};
67
private const gx_color_value q6[] = {
68
    0, frac_color_(1, 6), frac_color_(2, 6), frac_color_(3, 6),
69
    frac_color_(4, 6), frac_color_(5, 6), frac_color_(6, 6)
70
};
71
private const gx_color_value q7[] = {
72
    0, frac_color_(1, 7), frac_color_(2, 7), frac_color_(3, 7),
73
    frac_color_(4, 7), frac_color_(5, 7), frac_color_(6, 7), frac_color_(7, 7)
74
};
75
 
76
/* We export fc_color_quo for the fractional_color macro in gzht.h. */
77
const gx_color_value *const fc_color_quo[8] = {
78
    q0, q1, q2, q3, q4, q5, q6, q7
79
};
80
 
81
/* Begin code for setting up WTS device color. This should probably
82
   move into its own module. */
83
 
84
/**
85
 * gx_render_device_DevN_wts: Render DeviceN color by halftoning with WTS.
86
 *
87
 * This routine is the primary constructor for WTS device colors.
88
 * Note that, in the WTS code path, we sample the plane_vector array
89
 * during device color construction, while in the legacy code path,
90
 * it is sampled in the set_ht_colors procedure, invoked from
91
 * fill_rectangle. Does it affect correctness? I don't think so, but
92
 * it needs to be tested.
93
 **/
94
private int
95
gx_render_device_DeviceN_wts(frac * pcolor,
96
			     gx_device_color * pdevc, gx_device * dev,
97
			     gx_device_halftone * pdht,
98
			     const gs_int_point * ht_phase)
99
{
100
    int i;
101
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
102
    int num_comp = pdht->num_comp;
103
 
104
    for (i = 0; i < num_comp; i++) {
105
	cv[i] = 0;
106
    }
107
 
108
    pdevc->type = gx_dc_type_wts;
109
    pdevc->colors.wts.w_ht = pdht;
110
 
111
    if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN) {
112
	/* Monochrome case may be inverted. */
113
	pdevc->colors.wts.plane_vector[1] =
114
	    dev_proc(dev, encode_color)(dev, cv);
115
    }
116
    for (i = 0; i < num_comp; i++) {
117
	pdevc->colors.wts.levels[i] = pcolor[i];
118
	cv[i] = gx_max_color_value;
119
	pdevc->colors.wts.plane_vector[i] =
120
	    dev_proc(dev, encode_color)(dev, cv);
121
	cv[i] = 0;
122
    }
123
    pdevc->colors.wts.num_components = num_comp;
124
    return 0;
125
}
126
 
127
/*
128
 * Render DeviceN possibly by halftoning.
129
 *  pcolors = pointer to an array color values (as fracs)
130
 *  pdevc - pointer to device color structure
131
 *  dev = pointer to device data structure
132
 *  pht = pointer to halftone data structure
133
 *  ht_phase  = halftone phase
134
 *  gray_colorspace = true -> current color space is DeviceGray.
135
 *  This is part of a kludge to minimize differences in the
136
 *  regression testing.
137
 */
138
int
139
gx_render_device_DeviceN(frac * pcolor,
140
	gx_device_color * pdevc, gx_device * dev,
141
	gx_device_halftone * pdht, const gs_int_point * ht_phase)
142
{
143
    uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
144
    frac dither_check = 0;
145
    uint int_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
146
    gx_color_value vcolor[GS_CLIENT_COLOR_MAX_COMPONENTS];
147
    int i;
148
    int num_colors = dev->color_info.num_components;
149
    uint l_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
150
 
151
    if (pdht && pdht->components && pdht->components[0].corder.wts)
152
	return gx_render_device_DeviceN_wts(pcolor, pdevc, dev, pdht,
153
					    ht_phase);
154
 
155
    for (i=0; i<num_colors; i++) {
156
	max_value[i] = (dev->color_info.gray_index == i) ?
157
	     dev->color_info.dither_grays - 1 :
158
	     dev->color_info.dither_colors - 1;
159
    }
160
 
161
    for (i = 0; i < num_colors; i++) {
162
	unsigned long hsize = pdht ?
163
		(unsigned) pdht->components[i].corder.num_levels
164
	    	: 1;
165
	unsigned long nshades = hsize * max_value[i] + 1;
166
	long shade = pcolor[i] * nshades / (frac_1_long + 1);
167
	int_color[i] = shade / hsize;
168
	l_color[i] = shade % hsize;
169
	if (max_value[i] < MIN_CONTONE_LEVELS)
170
	    dither_check |= l_color[i];
171
    }
172
 
173
#ifdef DEBUG
174
    if (gs_debug_c('c')) {
175
	dlprintf1("[c]ncomp=%d ", num_colors);
176
	for (i = 0; i < num_colors; i++)
177
	    dlprintf1("0x%x, ", pcolor[i]);
178
	dlprintf("-->   ");
179
	for (i = 0; i < num_colors; i++)
180
	    dlprintf2("%x+0x%x, ", int_color[i], l_color[i]);
181
	dlprintf("\n");
182
    }
183
#endif
184
 
185
    /* Check for no dithering required */
186
    if (!dither_check) {
187
	for (i = 0; i < num_colors; i++)
188
	    vcolor[i] = fractional_color(int_color[i], max_value[i]);
189
	color_set_pure(pdevc, dev_proc(dev, encode_color)(dev, vcolor));
190
	return 0;
191
    }
192
 
193
    /* Use the slow, general colored halftone algorithm. */
194
 
195
    for (i = 0; i < num_colors; i++)
196
        _color_set_c(pdevc, i, int_color[i], l_color[i]);
197
    gx_complete_halftone(pdevc, num_colors, pdht);
198
 
199
    color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
200
			    pdht->lcm_width, pdht->lcm_height);
201
 
202
    /* Determine if we are using only one component */
203
    if (!(pdevc->colors.colored.plane_mask &
204
	 (pdevc->colors.colored.plane_mask - 1))) {
205
	/* We can reduce this color to a binary halftone or pure color. */
206
	return gx_devn_reduce_colored_halftone(pdevc, dev);
207
    }
208
 
209
    return 1;
210
}
211
 
212
/* Reduce a colored halftone to a binary halftone or pure color. */
213
/* This routine is called when only one component is being halftoned. */
214
int
215
gx_devn_reduce_colored_halftone(gx_device_color *pdevc, gx_device *dev)
216
{
217
    int planes = pdevc->colors.colored.plane_mask;
218
    int num_colors = dev->color_info.num_components;
219
    uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
220
    uint b[GX_DEVICE_COLOR_MAX_COMPONENTS];
221
    gx_color_value v[GX_DEVICE_COLOR_MAX_COMPONENTS];
222
    gx_color_index c0, c1;
223
    int i;
224
 
225
    for (i = 0; i < num_colors; i++) {
226
	max_value[i] = (dev->color_info.gray_index == i) ?
227
	     dev->color_info.dither_grays - 1 :
228
	     dev->color_info.dither_colors - 1;
229
        b[i] = pdevc->colors.colored.c_base[i];
230
        v[i] = fractional_color(b[i], max_value[i]);
231
    }
232
    c0 = dev_proc(dev, encode_color)(dev, v);
233
 
234
    if (planes == 0) {
235
	/*
236
	 * Use a pure color.  This case is unlikely, but it can occur if
237
	 * (and only if) the difference of each component from the nearest
238
	 * device color is less than one halftone level.
239
	 */
240
	color_set_pure(pdevc, c0);
241
	return 0;
242
    } else {
243
	/* Use a binary color. */
244
	int i = 0;
245
	uint bi;
246
	const gx_device_halftone *pdht = pdevc->colors.colored.c_ht;
247
	/*
248
	 * NB: the halftone orders are all set up for an additive color
249
	 *     space.  To use these work with a subtractive color space, it is
250
	 *     necessary to invert both the color level and the color
251
	 *     pair. Note that if the original color was provided an
252
	 *     additive space, this will reverse (in an approximate sense)
253
	 *     the color conversion performed to express the color in
254
	 *     subtractive space.
255
	 */
256
	bool invert = dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE;
257
	uint level;
258
 
259
	/* Convert plane mask bit position to component number */
260
	/* Determine i = log2(planes);  This works for powers of two */
261
	while (planes > 7) {
262
	    i += 3;
263
	    planes >>= 3;
264
	}
265
	i += planes >> 1;  /* log2 for 1,2,4 */
266
 
267
	bi = b[i] + 1;
268
	v[i] = fractional_color(bi, max_value[i]);
269
	level = pdevc->colors.colored.c_level[i];
270
        c1 = dev_proc(dev, encode_color)(dev, v);
271
	if (invert) {
272
	    level = pdht->components[i].corder.num_levels - level;
273
	    color_set_binary_halftone_component(pdevc, pdht, i, c1, c0, level);
274
	} else
275
	    color_set_binary_halftone_component(pdevc, pdht, i, c0, c1, level);
276
 
277
	return 1;
278
    }
279
}