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, 1995, 1996, 1997, 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: gxicolor.c,v 1.9 2003/08/18 21:21:57 dan Exp $ */
18
/* Color image rendering */
19
#include "gx.h"
20
#include "memory_.h"
21
#include "gpcheck.h"
22
#include "gserrors.h"
23
#include "gxfixed.h"
24
#include "gxfrac.h"
25
#include "gxarith.h"
26
#include "gxmatrix.h"
27
#include "gsccolor.h"
28
#include "gspaint.h"
29
#include "gzstate.h"
30
#include "gxdevice.h"
31
#include "gxcmap.h"
32
#include "gxdcconv.h"
33
#include "gxdcolor.h"
34
#include "gxistate.h"
35
#include "gxdevmem.h"
36
#include "gxcpath.h"
37
#include "gximage.h"
38
 
39
typedef union {
40
    byte v[GS_IMAGE_MAX_COLOR_COMPONENTS];
41
#define BYTES_PER_BITS32 4
42
#define BITS32_PER_COLOR_SAMPLES\
43
  ((GS_IMAGE_MAX_COLOR_COMPONENTS + BYTES_PER_BITS32 - 1) / BYTES_PER_BITS32)
44
    bits32 all[BITS32_PER_COLOR_SAMPLES];	/* for fast comparison */
45
} color_samples;
46
 
47
/* ------ Strategy procedure ------ */
48
 
49
/* Check the prototype. */
50
iclass_proc(gs_image_class_4_color);
51
 
52
private irender_proc(image_render_color);
53
irender_proc_t
54
gs_image_class_4_color(gx_image_enum * penum)
55
{
56
    if (penum->use_mask_color) {
57
	/*
58
	 * Scale the mask colors to match the scaling of each sample to
59
	 * a full byte, and set up the quick-filter parameters.
60
	 */
61
	int i;
62
	color_samples mask, test;
63
	bool exact = penum->spp <= BYTES_PER_BITS32;
64
 
65
	memset(&mask, 0, sizeof(mask));
66
	memset(&test, 0, sizeof(test));
67
	for (i = 0; i < penum->spp; ++i) {
68
	    byte v0, v1;
69
	    byte match = 0xff;
70
 
71
	    gx_image_scale_mask_colors(penum, i);
72
	    v0 = (byte)penum->mask_color.values[2 * i];
73
	    v1 = (byte)penum->mask_color.values[2 * i + 1];
74
	    while ((v0 & match) != (v1 & match))
75
		match <<= 1;
76
	    mask.v[i] = match;
77
	    test.v[i] = v0 & match;
78
	    exact &= (v0 == match && (v1 | match) == 0xff);
79
	}
80
	penum->mask_color.mask = mask.all[0];
81
	penum->mask_color.test = test.all[0];
82
	penum->mask_color.exact = exact;
83
    } else {
84
	penum->mask_color.mask = 0;
85
	penum->mask_color.test = ~0;
86
    }
87
    return &image_render_color;
88
}
89
 
90
/* ------ Rendering procedures ------ */
91
 
92
/* Test whether a color is transparent. */
93
private bool
94
mask_color_matches(const byte *v, const gx_image_enum *penum,
95
		   int num_components)
96
{
97
    int i;
98
 
99
    for (i = num_components * 2, v += num_components - 1; (i -= 2) >= 0; --v)
100
	if (*v < penum->mask_color.values[i] ||
101
	    *v > penum->mask_color.values[i + 1]
102
	    )
103
	    return false;
104
    return true;
105
}
106
 
107
/* Render a color image with 8 or fewer bits per sample. */
108
private int
109
image_render_color(gx_image_enum *penum_orig, const byte *buffer, int data_x,
110
		   uint w, int h, gx_device * dev)
111
{
112
    const gx_image_enum *const penum = penum_orig; /* const within proc */
113
    gx_image_clue *const clues = penum_orig->clues; /* not const */
114
    const gs_imager_state *pis = penum->pis;
115
    gs_logical_operation_t lop = penum->log_op;
116
    gx_dda_fixed_point pnext;
117
    image_posture posture = penum->posture;
118
    fixed xprev, yprev;
119
    fixed pdyx, pdyy;		/* edge of parallelogram */
120
    int vci, vdi;
121
    const gs_color_space *pcs = penum->pcs;
122
    cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
123
    cs_proc_remap_concrete_color((*remap_concrete_color)) =
124
	    pcs->type->remap_concrete_color;
125
    gs_client_color cc;
126
    bool device_color = penum->device_color;
127
    const gx_color_map_procs *cmap_procs = gx_get_cmap_procs(pis, dev);
128
    bits32 mask = penum->mask_color.mask;
129
    bits32 test = penum->mask_color.test;
130
    gx_image_clue *pic = &clues[0];
131
#define pdevc (&pic->dev_color)
132
    gx_image_clue *pic_next = &clues[1];
133
#define pdevc_next (&pic_next->dev_color)
134
    gx_image_clue empty_clue;
135
    gx_image_clue clue_temp;
136
    int spp = penum->spp;
137
    const byte *psrc_initial = buffer + data_x * spp;
138
    const byte *psrc = psrc_initial;
139
    const byte *rsrc = psrc + spp; /* psrc + spp at start of run */
140
    fixed xrun;			/* x ditto */
141
    fixed yrun;			/* y ditto */
142
    int irun;			/* int x/rrun */
143
    color_samples run;		/* run value */
144
    color_samples next;		/* next sample value */
145
    const byte *bufend = psrc + w;
146
    bool use_cache = spp * penum->bps <= 12;
147
    int code = 0, mcode = 0;
148
 
149
    if (h == 0)
150
	return 0;
151
    pnext = penum->dda.pixel0;
152
    xrun = xprev = dda_current(pnext.x);
153
    yrun = yprev = dda_current(pnext.y);
154
    pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
155
    pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
156
    switch (posture) {
157
	case image_portrait:
158
	    vci = penum->yci, vdi = penum->hci;
159
	    irun = fixed2int_var_rounded(xrun);
160
	    break;
161
	case image_landscape:
162
	default:    /* we don't handle skew -- treat as landscape */
163
	    vci = penum->xci, vdi = penum->wci;
164
	    irun = fixed2int_var_rounded(yrun);
165
	    break;
166
    }
167
 
168
    if_debug5('b', "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
169
	      penum->y, data_x, w, fixed2float(xprev), fixed2float(yprev));
170
    memset(&run, 0, sizeof(run));
171
    memset(&next, 0, sizeof(next));
172
    /* Ensure that we don't get any false dev_color_eq hits. */
173
    if (use_cache) {
174
	set_nonclient_dev_color(&empty_clue.dev_color, gx_no_color_index);
175
	pic = &empty_clue;
176
    }
177
    cs_full_init_color(&cc, pcs);
178
    run.v[0] = ~psrc[0];	/* force remap */
179
    while (psrc < bufend) {
180
	dda_next(pnext.x);
181
	dda_next(pnext.y);
182
#define CLUE_HASH3(penum, next)\
183
  &clues[(next.v[0] + (next.v[1] << 2) + (next.v[2] << 4)) & 255];
184
#define CLUE_HASH4(penum, next)\
185
  &clues[(next.v[0] + (next.v[1] << 2) + (next.v[2] << 4) +\
186
		 (next.v[3] << 6)) & 255]
187
 
188
	if (spp == 4) {		/* may be CMYK or RGBA */
189
	    next.v[0] = psrc[0];
190
	    next.v[1] = psrc[1];
191
	    next.v[2] = psrc[2];
192
	    next.v[3] = psrc[3];
193
	    psrc += 4;
194
map4:	    if (next.all[0] == run.all[0])
195
		goto inc;
196
	    if (use_cache) {
197
		pic_next = CLUE_HASH4(penum, next);
198
		if (pic_next->key == next.all[0])
199
		    goto f;
200
		/*
201
		 * If we are really unlucky, pic_next == pic,
202
		 * so mapping this color would clobber the one
203
		 * we're about to use for filling the run.
204
		 */
205
		if (pic_next == pic) {
206
		    clue_temp = *pic;
207
		    pic = &clue_temp;
208
		}
209
		pic_next->key = next.all[0];
210
	    }
211
	    /* Check for transparent color. */
212
	    if ((next.all[0] & mask) == test &&
213
		(penum->mask_color.exact ||
214
		 mask_color_matches(next.v, penum, 4))
215
		) {
216
		color_set_null(pdevc_next);
217
		goto mapped;
218
	    }
219
	    if (device_color) {
220
		frac frac_color[4];
221
 
222
		if (penum->alpha) {
223
		    /*
224
		     * We do not have support for DeviceN color and alpha.
225
		     */
226
		    cmap_procs->map_rgb_alpha
227
			(byte2frac(next.v[0]), byte2frac(next.v[1]),
228
			 byte2frac(next.v[2]), byte2frac(next.v[3]),
229
			 pdevc_next, pis, dev,
230
			 gs_color_select_source);
231
		    goto mapped;
232
		}
233
		/*
234
		 * We can call the remap concrete_color for the colorspace
235
		 * directly since device_color is only true if the colorspace
236
		 * is concrete.
237
		 */
238
		frac_color[0] = byte2frac(next.v[0]);
239
		frac_color[1] = byte2frac(next.v[1]);
240
		frac_color[2] = byte2frac(next.v[2]);
241
		frac_color[3] = byte2frac(next.v[3]);
242
		remap_concrete_color(frac_color, pcs, pdevc_next, pis,
243
					    dev, gs_color_select_source);
244
		goto mapped;
245
	    }
246
	    decode_sample(next.v[3], cc, 3);
247
	    if_debug1('B', "[B]cc[3]=%g\n", cc.paint.values[3]);
248
do3:	    decode_sample(next.v[0], cc, 0);
249
	    decode_sample(next.v[1], cc, 1);
250
	    decode_sample(next.v[2], cc, 2);
251
	    if_debug3('B', "[B]cc[0..2]=%g,%g,%g\n",
252
		      cc.paint.values[0], cc.paint.values[1],
253
		      cc.paint.values[2]);
254
	} else if (spp == 3) {	    /* may be RGB */
255
	    next.v[0] = psrc[0];
256
	    next.v[1] = psrc[1];
257
	    next.v[2] = psrc[2];
258
	    psrc += 3;
259
	    if (next.all[0] == run.all[0])
260
		goto inc;
261
	    if (use_cache) {
262
		pic_next = CLUE_HASH3(penum, next);
263
		if (pic_next->key == next.all[0])
264
		    goto f;
265
		/* See above re the following check. */
266
		if (pic_next == pic) {
267
		    clue_temp = *pic;
268
		    pic = &clue_temp;
269
		}
270
		pic_next->key = next.all[0];
271
	    }
272
	    /* Check for transparent color. */
273
	    if ((next.all[0] & mask) == test &&
274
		(penum->mask_color.exact ||
275
		 mask_color_matches(next.v, penum, 3))
276
		) {
277
		color_set_null(pdevc_next);
278
		goto mapped;
279
	    }
280
	    if (device_color) {
281
		frac frac_color[3];
282
		/*
283
		 * We can call the remap concrete_color for the colorspace
284
		 * directly since device_color is only true if the colorspace
285
		 * is concrete.
286
		 */
287
		frac_color[0] = byte2frac(next.v[0]);
288
		frac_color[1] = byte2frac(next.v[1]);
289
		frac_color[2] = byte2frac(next.v[2]);
290
		remap_concrete_color(frac_color, pcs, pdevc_next, pis,
291
						dev, gs_color_select_source);
292
		goto mapped;
293
	    }
294
	    goto do3;
295
	} else if (penum->alpha) {
296
	    if (spp == 2) {	/* might be Gray + alpha */
297
		next.v[2] = next.v[1] = next.v[0] = psrc[0];
298
		next.v[3] = psrc[1];
299
		psrc += 2;
300
		goto map4;
301
	    } else if (spp == 5) {	/* might be CMYK + alpha */
302
		/* Convert CMYK to RGB. */
303
		frac rgb[3];
304
 
305
		color_cmyk_to_rgb(byte2frac(psrc[0]), byte2frac(psrc[1]),
306
				  byte2frac(psrc[2]), byte2frac(psrc[3]),
307
				  pis, rgb);
308
		/*
309
		 * It seems silly to do all this converting between
310
		 * fracs and bytes, but that's what the current
311
		 * APIs require.
312
		 */
313
		next.v[0] = frac2byte(rgb[0]);
314
		next.v[1] = frac2byte(rgb[1]);
315
		next.v[2] = frac2byte(rgb[2]);
316
		next.v[3] = psrc[4];
317
		psrc += 5;
318
		goto map4;
319
	    }
320
	} else {		/* DeviceN */
321
	    int i;
322
 
323
	    use_cache = false;	/* should do in initialization */
324
	    if (!memcmp(psrc, run.v, spp)) {
325
		psrc += spp;
326
		goto inc;
327
	    }
328
	    memcpy(next.v, psrc, spp);
329
	    psrc += spp;
330
	    if ((next.all[0] & mask) == test &&
331
		(penum->mask_color.exact ||
332
		 mask_color_matches(next.v, penum, spp))
333
		) {
334
		color_set_null(pdevc_next);
335
		goto mapped;
336
	    }
337
	    for (i = 0; i < spp; ++i)
338
		decode_sample(next.v[i], cc, i);
339
#ifdef DEBUG
340
	    if (gs_debug_c('B')) {
341
		dprintf2("[B]cc[0..%d]=%g", spp - 1,
342
			 cc.paint.values[0]);
343
		for (i = 1; i < spp; ++i)
344
		    dprintf1(",%g", cc.paint.values[i]);
345
		dputs("\n");
346
	    }
347
#endif
348
	}
349
	mcode = remap_color(&cc, pcs, pdevc_next, pis, dev,
350
			   gs_color_select_source);
351
	if (mcode < 0)
352
	    goto fill;
353
mapped:	if (pic == pic_next)
354
	    goto fill;
355
f:	if_debug7('B', "[B]0x%x,0x%x,0x%x,0x%x -> %ld,%ld,0x%lx\n",
356
		  next.v[0], next.v[1], next.v[2], next.v[3],
357
		  pdevc_next->colors.binary.color[0],
358
		  pdevc_next->colors.binary.color[1],
359
		  (ulong) pdevc_next->type);
360
	/* Even though the supplied colors don't match, */
361
	/* the device colors might. */
362
	if (dev_color_eq(*pdevc, *pdevc_next))
363
	    goto set;
364
fill:	/* Fill the region between */
365
	/* xrun/irun and xprev */
366
        /*
367
	 * Note;  This section is nearly a copy of a simlar section below
368
         * for processing the last image pixel in the loop.  This would have been
369
         * made into a subroutine except for complications about the number of
370
         * variables that would have been needed to be passed to the routine.
371
	 */
372
	switch (posture) {
373
	case image_portrait:
374
	    {		/* Rectangle */
375
		int xi = irun;
376
		int wi = (irun = fixed2int_var_rounded(xprev)) - xi;
377
 
378
		if (wi < 0)
379
		    xi += wi, wi = -wi;
380
		if (wi > 0)
381
		    code = gx_fill_rectangle_device_rop(xi, vci, wi, vdi,
382
							pdevc, dev, lop);
383
	    }
384
	    break;
385
	case image_landscape:
386
	    {		/* 90 degree rotated rectangle */
387
		int yi = irun;
388
		int hi = (irun = fixed2int_var_rounded(yprev)) - yi;
389
 
390
		if (hi < 0)
391
		    yi += hi, hi = -hi;
392
		if (hi > 0)
393
		    code = gx_fill_rectangle_device_rop(vci, yi, vdi, hi,
394
							pdevc, dev, lop);
395
	    }
396
	    break;
397
	default:
398
	    {		/* Parallelogram */
399
		code = (*dev_proc(dev, fill_parallelogram))
400
		    (dev, xrun, yrun, xprev - xrun, yprev - yrun, pdyx, pdyy,
401
		     pdevc, lop);
402
		xrun = xprev;
403
		yrun = yprev;
404
	    }
405
	}
406
	if (code < 0)
407
	    goto err;
408
	rsrc = psrc;
409
	if ((code = mcode) < 0) {
410
	    /* Invalidate any partially built cache entry. */
411
	    if (use_cache)
412
		pic_next->key = ~next.all[0];
413
	    goto err;
414
	}
415
	if (use_cache)
416
	    pic = pic_next;
417
	else {
418
	    gx_image_clue *ptemp = pic;
419
 
420
	    pic = pic_next;
421
	    pic_next = ptemp;
422
	}
423
set:	run = next;
424
inc:	xprev = dda_current(pnext.x);
425
	yprev = dda_current(pnext.y);	/* harmless if no skew */
426
    }
427
    /* Fill the last run. */
428
    /*
429
     * Note;  This section is nearly a copy of a simlar section above
430
     * for processing an image pixel in the loop.  This would have been
431
     * made into a subroutine except for complications about the number
432
     * variables that would have been needed to be passed to the routine.
433
     */
434
    switch (posture) {
435
    	case image_portrait:
436
	    {		/* Rectangle */
437
		int xi = irun;
438
		int wi = (irun = fixed2int_var_rounded(xprev)) - xi;
439
 
440
		if (wi < 0)
441
		    xi += wi, wi = -wi;
442
		if (wi > 0)
443
		    code = gx_fill_rectangle_device_rop(xi, vci, wi, vdi,
444
							pdevc, dev, lop);
445
	    }
446
	    break;
447
	case image_landscape:
448
	    {		/* 90 degree rotated rectangle */
449
		int yi = irun;
450
		int hi = (irun = fixed2int_var_rounded(yprev)) - yi;
451
 
452
		if (hi < 0)
453
		    yi += hi, hi = -hi;
454
		if (hi > 0)
455
		    code = gx_fill_rectangle_device_rop(vci, yi, vdi, hi,
456
							pdevc, dev, lop);
457
	    }
458
	    break;
459
	default:
460
	    {		/* Parallelogram */
461
		code = (*dev_proc(dev, fill_parallelogram))
462
		    (dev, xrun, yrun, xprev - xrun, yprev - yrun, pdyx, pdyy,
463
		     pdevc, lop);
464
	    }
465
    }
466
    return (code < 0 ? code : 1);
467
    /* Save position if error, in case we resume. */
468
err:
469
    penum_orig->used.x = (rsrc - spp - psrc_initial) / spp;
470
    penum_orig->used.y = 0;
471
    return code;
472
}