xref: /plan9/sys/src/cmd/gs/src/gxipixel.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 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: gxipixel.c,v 1.12 2005/07/21 19:32:06 alexcher Exp $ */
18 /* Common code for ImageType 1 and 4 initialization */
19 #include "gx.h"
20 #include "math_.h"
21 #include "memory_.h"
22 #include "gpcheck.h"
23 #include "gscdefs.h"		/* for image class table */
24 #include "gserrors.h"
25 #include "gsstruct.h"
26 #include "gsutil.h"
27 #include "gxfixed.h"
28 #include "gxfrac.h"
29 #include "gxarith.h"
30 #include "gxmatrix.h"
31 #include "gsccolor.h"
32 #include "gspaint.h"
33 #include "gzstate.h"
34 #include "gxdevice.h"
35 #include "gzpath.h"
36 #include "gzcpath.h"
37 #include "gxdevmem.h"
38 #include "gximage.h"
39 #include "gxiparam.h"
40 #include "gdevmrop.h"
41 
42 /* Structure descriptors */
43 private_st_gx_image_enum();
44 
45 /* Image class procedures */
46 extern_gx_image_class_table();
47 
48 /* Enumerator procedures */
49 private const gx_image_enum_procs_t image1_enum_procs = {
50     gx_image1_plane_data, gx_image1_end_image, gx_image1_flush
51 };
52 
53 /* GC procedures */
54 private
ENUM_PTRS_WITH(image_enum_enum_ptrs,gx_image_enum * eptr)55 ENUM_PTRS_WITH(image_enum_enum_ptrs, gx_image_enum *eptr)
56 {
57     int bps;
58     gs_ptr_type_t ret;
59 
60     /* Enumerate the used members of clues.dev_color. */
61     index -= gx_image_enum_num_ptrs;
62     bps = eptr->unpack_bps;
63     if (eptr->spp != 1)
64 	bps = 8;
65     else if (bps > 8 || eptr->unpack == sample_unpack_copy)
66 	bps = 1;
67     if (index >= (1 << bps) * st_device_color_max_ptrs)		/* done */
68 	return 0;
69     ret = ENUM_USING(st_device_color,
70 		     &eptr->clues[(index / st_device_color_max_ptrs) *
71 				  (255 / ((1 << bps) - 1))].dev_color,
72 		     sizeof(eptr->clues[0].dev_color),
73 		     index % st_device_color_max_ptrs);
74     if (ret == 0)		/* don't stop early */
75 	ENUM_RETURN(0);
76     return ret;
77 }
78 #define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
gx_image_enum_do_ptrs(e1)79 gx_image_enum_do_ptrs(e1)
80 #undef e1
81 ENUM_PTRS_END
82 private RELOC_PTRS_WITH(image_enum_reloc_ptrs, gx_image_enum *eptr)
83 {
84     int i;
85 
86 #define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
87     gx_image_enum_do_ptrs(r1)
88 #undef r1
89     {
90 	int bps = eptr->unpack_bps;
91 
92 	if (eptr->spp != 1)
93 	    bps = 8;
94 	else if (bps > 8 || eptr->unpack == sample_unpack_copy)
95 	    bps = 1;
96 	for (i = 0; i <= 255; i += 255 / ((1 << bps) - 1))
97 	    RELOC_USING(st_device_color,
98 			&eptr->clues[i].dev_color, sizeof(gx_device_color));
99     }
100 }
101 RELOC_PTRS_END
102 
103 /* Forward declarations */
104 private int color_draws_b_w(gx_device * dev,
105 			    const gx_drawing_color * pdcolor);
106 private void image_init_map(byte * map, int map_size, const float *decode);
107 private void image_init_colors(gx_image_enum * penum, int bps, int spp,
108 			       gs_image_format_t format,
109 			       const float *decode,
110 			       const gs_imager_state * pis, gx_device * dev,
111 			       const gs_color_space * pcs, bool * pdcb);
112 
113 /* Procedures for unpacking the input data into bytes or fracs. */
114 /*extern SAMPLE_UNPACK_PROC(sample_unpack_copy); *//* declared above */
115 
116 /*
117  * Do common initialization for processing an ImageType 1 or 4 image.
118  * Allocate the enumerator and fill in the following members:
119  *	rect
120  */
121 int
gx_image_enum_alloc(const gs_image_common_t * pic,const gs_int_rect * prect,gs_memory_t * mem,gx_image_enum ** ppenum)122 gx_image_enum_alloc(const gs_image_common_t * pic,
123 		    const gs_int_rect * prect, gs_memory_t * mem,
124 		    gx_image_enum **ppenum)
125 {
126     const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
127     int width = pim->Width, height = pim->Height;
128     int bpc = pim->BitsPerComponent;
129     gx_image_enum *penum;
130 
131     if (width < 0 || height < 0)
132 	return_error(gs_error_rangecheck);
133     switch (pim->format) {
134     case gs_image_format_chunky:
135     case gs_image_format_component_planar:
136 	switch (bpc) {
137 	case 1: case 2: case 4: case 8: case 12: case 16: break;
138 	default: return_error(gs_error_rangecheck);
139 	}
140 	break;
141     case gs_image_format_bit_planar:
142 	if (bpc < 1 || bpc > 8)
143 	    return_error(gs_error_rangecheck);
144     }
145     if (prect) {
146 	if (prect->p.x < 0 || prect->p.y < 0 ||
147 	    prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
148 	    prect->q.x > width || prect->q.y > height
149 	    )
150 	    return_error(gs_error_rangecheck);
151     }
152     penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
153 			    "gx_default_begin_image");
154     if (penum == 0)
155 	return_error(gs_error_VMerror);
156     if (prect) {
157 	penum->rect.x = prect->p.x;
158 	penum->rect.y = prect->p.y;
159 	penum->rect.w = prect->q.x - prect->p.x;
160 	penum->rect.h = prect->q.y - prect->p.y;
161     } else {
162 	penum->rect.x = 0, penum->rect.y = 0;
163 	penum->rect.w = width, penum->rect.h = height;
164     }
165 #ifdef DEBUG
166     if (gs_debug_c('b')) {
167 	dlprintf2("[b]Image: w=%d h=%d", width, height);
168 	if (prect)
169 	    dprintf4(" ((%d,%d),(%d,%d))",
170 		     prect->p.x, prect->p.y, prect->q.x, prect->q.y);
171     }
172 #endif
173     *ppenum = penum;
174     return 0;
175 }
176 
177 /*
178  * Finish initialization for processing an ImageType 1 or 4 image.
179  * Assumes the following members of *penum are set in addition to those
180  * set by gx_image_enum_alloc:
181  *	alpha, use_mask_color, mask_color (if use_mask_color is true),
182  *	masked, adjust
183  */
184 int
gx_image_enum_begin(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum * penum)185 gx_image_enum_begin(gx_device * dev, const gs_imager_state * pis,
186 		    const gs_matrix *pmat, const gs_image_common_t * pic,
187 		const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
188 		gs_memory_t * mem, gx_image_enum *penum)
189 {
190     const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
191     gs_image_format_t format = pim->format;
192     const int width = pim->Width;
193     const int height = pim->Height;
194     const int bps = pim->BitsPerComponent;
195     bool masked = penum->masked;
196     const float *decode = pim->Decode;
197     gs_matrix mat;
198     int index_bps;
199     const gs_color_space *pcs = pim->ColorSpace;
200     gs_logical_operation_t lop = (pis ? pis->log_op : lop_default);
201     int code;
202     int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
203     int spp, nplanes, spread;
204     uint bsize;
205     byte *buffer;
206     fixed mtx, mty;
207     gs_fixed_point row_extent, col_extent, x_extent, y_extent;
208     bool device_color;
209     gs_fixed_rect obox, cbox;
210 
211     if (pmat == 0)
212 	pmat = &ctm_only(pis);
213     if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
214 	(code = gs_matrix_multiply(&mat, pmat, &mat)) < 0
215 	) {
216 	gs_free_object(mem, penum, "gx_default_begin_image");
217 	return code;
218     }
219     penum->matrix = mat;
220     if_debug6('b', " [%g %g %g %g %g %g]\n",
221 	      mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
222     /* following works for 1, 2, 4, 8, 12, 16 */
223     index_bps = (bps < 8 ? bps >> 1 : (bps >> 2) + 1);
224     mtx = float2fixed(mat.tx);
225     mty = float2fixed(mat.ty);
226     row_extent.x = float2fixed(width * mat.xx + mat.tx) - mtx;
227     row_extent.y =
228 	(is_fzero(mat.xy) ? fixed_0 :
229 	 float2fixed(width * mat.xy + mat.ty) - mty);
230     col_extent.x =
231 	(is_fzero(mat.yx) ? fixed_0 :
232 	 float2fixed(height * mat.yx + mat.tx) - mtx);
233     col_extent.y = float2fixed(height * mat.yy + mat.ty) - mty;
234     gx_image_enum_common_init((gx_image_enum_common_t *)penum,
235 			      (const gs_data_image_t *)pim,
236 			      &image1_enum_procs, dev,
237 			      (masked ? 1 : cs_num_components(pcs)),
238 			      format);
239     if (penum->rect.w == width && penum->rect.h == height) {
240 	x_extent = row_extent;
241 	y_extent = col_extent;
242     } else {
243 	int rw = penum->rect.w, rh = penum->rect.h;
244 
245 	x_extent.x = float2fixed(rw * mat.xx + mat.tx) - mtx;
246 	x_extent.y =
247 	    (is_fzero(mat.xy) ? fixed_0 :
248 	     float2fixed(rw * mat.xy + mat.ty) - mty);
249 	y_extent.x =
250 	    (is_fzero(mat.yx) ? fixed_0 :
251 	     float2fixed(rh * mat.yx + mat.tx) - mtx);
252 	y_extent.y = float2fixed(rh * mat.yy + mat.ty) - mty;
253     }
254     if (masked) {	/* This is imagemask. */
255 	if (bps != 1 || pcs != NULL || penum->alpha || decode[0] == decode[1]) {
256 	    gs_free_object(mem, penum, "gx_default_begin_image");
257 	    return_error(gs_error_rangecheck);
258 	}
259 	/* Initialize color entries 0 and 255. */
260 	set_nonclient_dev_color(&penum->icolor0, gx_no_color_index);
261 	penum->icolor1 = *pdcolor;
262 	memcpy(&penum->map[0].table.lookup4x1to32[0],
263 	       (decode[0] < decode[1] ? lookup4x1to32_inverted :
264 		lookup4x1to32_identity),
265 	       16 * 4);
266 	penum->map[0].decoding = sd_none;
267 	spp = 1;
268 	lop = rop3_know_S_0(lop);
269     } else {			/* This is image, not imagemask. */
270 	const gs_color_space_type *pcst = pcs->type;
271 	int b_w_color;
272 
273 	spp = cs_num_components(pcs);
274 	if (spp < 0) {		/* Pattern not allowed */
275 	    gs_free_object(mem, penum, "gx_default_begin_image");
276 	    return_error(gs_error_rangecheck);
277 	}
278 	if (penum->alpha)
279 	    ++spp;
280 	/* Use a less expensive format if possible. */
281 	switch (format) {
282 	case gs_image_format_bit_planar:
283 	    if (bps > 1)
284 		break;
285 	    format = gs_image_format_component_planar;
286 	case gs_image_format_component_planar:
287 	    if (spp == 1)
288 		format = gs_image_format_chunky;
289 	default:		/* chunky */
290 	    break;
291 	}
292 	device_color = (*pcst->concrete_space) (pcs, pis) == pcs;
293 	image_init_colors(penum, bps, spp, format, decode, pis, dev,
294 			  pcs, &device_color);
295 	/* Try to transform non-default RasterOps to something */
296 	/* that we implement less expensively. */
297 	if (!pim->CombineWithColor)
298 	    lop = rop3_know_T_0(lop) & ~lop_T_transparent;
299 	else {
300 	    if (rop3_uses_T(lop))
301 		switch (color_draws_b_w(dev, pdcolor)) {
302 		    case 0:
303 			lop = rop3_know_T_0(lop);
304 			break;
305 		    case 1:
306 			lop = rop3_know_T_1(lop);
307 			break;
308 		    default:
309 			;
310 		}
311 	}
312 	if (lop != rop3_S &&	/* if best case, no more work needed */
313 	    !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
314 	    (b_w_color =
315 	     color_draws_b_w(dev, &penum->icolor0)) >= 0 &&
316 	    color_draws_b_w(dev, &penum->icolor1) == (b_w_color ^ 1)
317 	    ) {
318 	    if (b_w_color) {	/* Swap the colors and invert the RasterOp source. */
319 		gx_device_color dcolor;
320 
321 		dcolor = penum->icolor0;
322 		penum->icolor0 = penum->icolor1;
323 		penum->icolor1 = dcolor;
324 		lop = rop3_invert_S(lop);
325 	    }
326 	    /*
327 	     * At this point, we know that the source pixels
328 	     * correspond directly to the S input for the raster op,
329 	     * i.e., icolor0 is black and icolor1 is white.
330 	     */
331 	    switch (lop) {
332 		case rop3_D & rop3_S:
333 		    /* Implement this as an inverted mask writing 0s. */
334 		    penum->icolor1 = penum->icolor0;
335 		    /* (falls through) */
336 		case rop3_D | rop3_not(rop3_S):
337 		    /* Implement this as an inverted mask writing 1s. */
338 		    memcpy(&penum->map[0].table.lookup4x1to32[0],
339 			   lookup4x1to32_inverted, 16 * 4);
340 		  rmask:	/* Fill in the remaining parameters for a mask. */
341 		    penum->masked = masked = true;
342 		    set_nonclient_dev_color(&penum->icolor0, gx_no_color_index);
343 		    penum->map[0].decoding = sd_none;
344 		    lop = rop3_T;
345 		    break;
346 		case rop3_D & rop3_not(rop3_S):
347 		    /* Implement this as a mask writing 0s. */
348 		    penum->icolor1 = penum->icolor0;
349 		    /* (falls through) */
350 		case rop3_D | rop3_S:
351 		    /* Implement this as a mask writing 1s. */
352 		    memcpy(&penum->map[0].table.lookup4x1to32[0],
353 			   lookup4x1to32_identity, 16 * 4);
354 		    goto rmask;
355 		default:
356 		    ;
357 	    }
358 	}
359     }
360     penum->device_color = device_color;
361     /*
362      * Adjust width upward for unpacking up to 7 trailing bits in
363      * the row, plus 1 byte for end-of-run, plus up to 7 leading
364      * bits for data_x offset within a packed byte.
365      */
366     bsize = ((bps > 8 ? width * 2 : width) + 15) * spp;
367     buffer = gs_alloc_bytes(mem, bsize, "image buffer");
368     if (buffer == 0) {
369 	gs_free_object(mem, penum, "gx_default_begin_image");
370 	return_error(gs_error_VMerror);
371     }
372     penum->bps = bps;
373     penum->unpack_bps = bps;
374     penum->log2_xbytes = log2_xbytes;
375     penum->spp = spp;
376     switch (format) {
377     case gs_image_format_chunky:
378 	nplanes = 1;
379 	spread = 1 << log2_xbytes;
380 	break;
381     case gs_image_format_component_planar:
382 	nplanes = spp;
383 	spread = spp << log2_xbytes;
384 	break;
385     case gs_image_format_bit_planar:
386 	nplanes = spp * bps;
387 	spread = spp << log2_xbytes;
388 	break;
389     default:
390 	/* No other cases are possible (checked by gx_image_enum_alloc). */
391 	return_error(gs_error_Fatal);
392     }
393     penum->num_planes = nplanes;
394     penum->spread = spread;
395     /*
396      * If we're asked to interpolate in a partial image, we have to
397      * assume that the client either really only is interested in
398      * the given sub-image, or else is constructing output out of
399      * overlapping pieces.
400      */
401     penum->interpolate = pim->Interpolate;
402     penum->x_extent = x_extent;
403     penum->y_extent = y_extent;
404     penum->posture =
405 	((x_extent.y | y_extent.x) == 0 ? image_portrait :
406 	 (x_extent.x | y_extent.y) == 0 ? image_landscape :
407 	 image_skewed);
408     penum->pis = pis;
409     penum->pcs = pcs;
410     penum->memory = mem;
411     penum->buffer = buffer;
412     penum->buffer_size = bsize;
413     penum->line = 0;
414     penum->line_size = 0;
415     penum->use_rop = lop != (masked ? rop3_T : rop3_S);
416 #ifdef DEBUG
417     if (gs_debug_c('*')) {
418 	if (penum->use_rop)
419 	    dprintf1("[%03x]", lop);
420 	dprintf5("%c%d%c%dx%d ",
421 		 (masked ? (color_is_pure(pdcolor) ? 'm' : 'h') : 'i'),
422 		 bps,
423 		 (penum->posture == image_portrait ? ' ' :
424 		  penum->posture == image_landscape ? 'L' : 'T'),
425 		 width, height);
426     }
427 #endif
428     penum->slow_loop = 0;
429     if (pcpath == 0) {
430 	(*dev_proc(dev, get_clipping_box)) (dev, &obox);
431 	cbox = obox;
432 	penum->clip_image = 0;
433     } else
434 	penum->clip_image =
435 	    (gx_cpath_outer_box(pcpath, &obox) |	/* not || */
436 	     gx_cpath_inner_box(pcpath, &cbox) ?
437 	     0 : image_clip_region);
438     penum->clip_outer = obox;
439     penum->clip_inner = cbox;
440     penum->log_op = rop3_T;	/* rop device takes care of this */
441     penum->clip_dev = 0;	/* in case we bail out */
442     penum->rop_dev = 0;		/* ditto */
443     penum->scaler = 0;		/* ditto */
444     /*
445      * If all four extrema of the image fall within the clipping
446      * rectangle, clipping is never required.  When making this check,
447      * we must carefully take into account the fact that we only care
448      * about pixel centers.
449      */
450     {
451 	fixed
452 	    epx = min(row_extent.x, 0) + min(col_extent.x, 0),
453 	    eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
454 	    epy = min(row_extent.y, 0) + min(col_extent.y, 0),
455 	    eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
456 
457 	{
458 	    int hwx, hwy;
459 
460 	    switch (penum->posture) {
461 		case image_portrait:
462 		    hwx = width, hwy = height;
463 		    break;
464 		case image_landscape:
465 		    hwx = height, hwy = width;
466 		    break;
467 		default:
468 		    hwx = hwy = 0;
469 	    }
470 	    /*
471 	     * If the image is only 1 sample wide or high,
472 	     * and is less than 1 device pixel wide or high,
473 	     * move it slightly so that it covers pixel centers.
474 	     * This is a hack to work around a bug in some old
475 	     * versions of TeX/dvips, which use 1-bit-high images
476 	     * to draw horizontal and vertical lines without
477 	     * positioning them properly.
478 	     */
479 	    if (hwx == 1 && eqx - epx < fixed_1) {
480 		fixed diff =
481 		arith_rshift_1(row_extent.x + col_extent.x);
482 
483 		mtx = (((mtx + diff) | fixed_half) & -fixed_half) - diff;
484 	    }
485 	    if (hwy == 1 && eqy - epy < fixed_1) {
486 		fixed diff =
487 		arith_rshift_1(row_extent.y + col_extent.y);
488 
489 		mty = (((mty + diff) | fixed_half) & -fixed_half) - diff;
490 	    }
491 	}
492 	if_debug5('b', "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
493 		  (masked? "masked, " : ""), spp, bps,
494 		  fixed2float(mtx), fixed2float(mty));
495 	if_debug9('b',
496 		  "[b]   cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
497 		  fixed2float(cbox.p.x), fixed2float(cbox.p.y),
498 		  fixed2float(cbox.q.x), fixed2float(cbox.q.y),
499 		  fixed2float(obox.p.x), fixed2float(obox.p.y),
500 		  fixed2float(obox.q.x), fixed2float(obox.q.y),
501 		  penum->clip_image);
502 	dda_init(penum->dda.row.x, mtx, col_extent.x, height);
503 	dda_init(penum->dda.row.y, mty, col_extent.y, height);
504 	if (penum->rect.y) {
505 	    dda_advance(penum->dda.row.x, penum->rect.y);
506 	    dda_advance(penum->dda.row.y, penum->rect.y);
507 	}
508 	penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
509 	penum->cur.y = penum->prev.y = dda_current(penum->dda.row.y);
510 	dda_init(penum->dda.strip.x, penum->cur.x, row_extent.x, width);
511 	dda_init(penum->dda.strip.y, penum->cur.y, row_extent.y, width);
512 	if (penum->rect.x) {
513 	    dda_advance(penum->dda.strip.x, penum->rect.x);
514 	    dda_advance(penum->dda.strip.y, penum->rect.x);
515 	} {
516 	    fixed ox = dda_current(penum->dda.strip.x);
517 	    fixed oy = dda_current(penum->dda.strip.y);
518 
519 	    if (!penum->clip_image)	/* i.e., not clip region */
520 		penum->clip_image =
521 		    (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
522 		     image_clip_xmin : 0) +
523 		    (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
524 		     image_clip_xmax : 0) +
525 		    (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
526 		     image_clip_ymin : 0) +
527 		    (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
528 		     image_clip_ymax : 0);
529 	}
530     }
531     penum->y = 0;
532     penum->used.x = 0;
533     penum->used.y = 0;
534     {
535 	static sample_unpack_proc_t procs[2][6] = {
536 	{   sample_unpack_1, sample_unpack_2,
537 	    sample_unpack_4, sample_unpack_8,
538 	    0, 0
539 	},
540 	{   sample_unpack_1_interleaved, sample_unpack_2_interleaved,
541 	    sample_unpack_4_interleaved, sample_unpack_8_interleaved,
542 	    0, 0
543 	}};
544 	int num_planes = penum->num_planes;
545 	bool interleaved = (num_planes == 1 && penum->plane_depths[0] != penum->bps);
546 	int i;
547 
548 	procs[0][4] = procs[1][4] = sample_unpack_12_proc;
549 	procs[0][5] = procs[1][5] = sample_unpack_16_proc;
550 	if (interleaved) {
551 	    int num_components = penum->plane_depths[0] / penum->bps;
552 
553 	    for (i = 1; i < num_components; i++) {
554 		if (decode[0] != decode[i * 2 + 0] ||
555 		    decode[1] != decode[i * 2 + 1])
556 		    break;
557 	    }
558 	    if (i == num_components)
559 		interleaved = false; /* Use single table. */
560 	}
561 	if (index_bps >= 4) {
562 	    if ((penum->unpack = procs[interleaved][index_bps]) == 0) {		/* bps case not supported. */
563 		gx_default_end_image(dev,
564 				     (gx_image_enum_common_t *) penum,
565 				     false);
566 		return_error(gs_error_rangecheck);
567 	    }
568 	} else {
569 	    penum->unpack = procs[interleaved][index_bps];
570 	}
571 	if_debug1('b', "[b]unpack=%d\n", bps);
572 	/* Set up pixel0 for image class procedures. */
573 	penum->dda.pixel0 = penum->dda.strip;
574 	for (i = 0; i < gx_image_class_table_count; ++i)
575 	    if ((penum->render = gx_image_class_table[i](penum)) != 0)
576 		break;
577 	if (i == gx_image_class_table_count) {
578 	    /* No available class can handle this image. */
579 	    gx_default_end_image(dev, (gx_image_enum_common_t *) penum,
580 				 false);
581 	    return_error(gs_error_rangecheck);
582 	}
583     }
584     if (penum->clip_image && pcpath) {	/* Set up the clipping device. */
585 	gx_device_clip *cdev =
586 	    gs_alloc_struct(mem, gx_device_clip,
587 			    &st_device_clip, "image clipper");
588 
589 	if (cdev == 0) {
590 	    gx_default_end_image(dev,
591 				 (gx_image_enum_common_t *) penum,
592 				 false);
593 	    return_error(gs_error_VMerror);
594 	}
595 	gx_make_clip_translate_device(cdev, gx_cpath_list(pcpath), 0, 0, mem);
596 	gx_device_retain((gx_device *)cdev, true); /* will free explicitly */
597 	gx_device_set_target((gx_device_forward *)cdev, dev);
598 	(*dev_proc(cdev, open_device)) ((gx_device *) cdev);
599 	penum->clip_dev = cdev;
600     }
601     if (penum->use_rop) {	/* Set up the RasterOp source device. */
602 	gx_device_rop_texture *rtdev;
603 
604 	code = gx_alloc_rop_texture_device(&rtdev, mem,
605 					   "image RasterOp");
606 	if (code < 0) {
607 	    gx_default_end_image(dev, (gx_image_enum_common_t *) penum,
608 				 false);
609 	    return code;
610 	}
611 	gx_make_rop_texture_device(rtdev,
612 				   (penum->clip_dev != 0 ?
613 				    (gx_device *) penum->clip_dev :
614 				    dev), lop, pdcolor);
615 	penum->rop_dev = rtdev;
616     }
617     return 0;
618 }
619 
620 /* If a drawing color is black or white, return 0 or 1 respectively, */
621 /* otherwise return -1. */
622 private int
color_draws_b_w(gx_device * dev,const gx_drawing_color * pdcolor)623 color_draws_b_w(gx_device * dev, const gx_drawing_color * pdcolor)
624 {
625     if (color_is_pure(pdcolor)) {
626 	gx_color_value rgb[3];
627 
628 	(*dev_proc(dev, map_color_rgb)) (dev, gx_dc_pure_color(pdcolor),
629 					 rgb);
630 	if (!(rgb[0] | rgb[1] | rgb[2]))
631 	    return 0;
632 	if ((rgb[0] & rgb[1] & rgb[2]) == gx_max_color_value)
633 	    return 1;
634     }
635     return -1;
636 }
637 
638 /* Export this for use by image_render_ functions */
639 void
image_init_clues(gx_image_enum * penum,int bps,int spp)640 image_init_clues(gx_image_enum * penum, int bps, int spp)
641 {
642     /* Initialize the color table */
643 #define ictype(i)\
644   penum->clues[i].dev_color.type
645 
646     switch ((spp == 1 ? bps : 8)) {
647 	case 8:		/* includes all color images */
648 	    {
649 		register gx_image_clue *pcht = &penum->clues[0];
650 		register int n = 64;	/* 8 bits means 256 clues, do	*/
651 					/* 4 at a time for efficiency	*/
652 		do {
653 		    pcht[0].dev_color.type =
654 			pcht[1].dev_color.type =
655 			pcht[2].dev_color.type =
656 			pcht[3].dev_color.type =
657 			gx_dc_type_none;
658 		    pcht[0].key = pcht[1].key =
659 			pcht[2].key = pcht[3].key = 0;
660 		    pcht += 4;
661 		}
662 		while (--n > 0);
663 		penum->clues[0].key = 1;	/* guarantee no hit */
664 		break;
665 	    }
666 	case 4:
667 	    ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
668 		ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
669 		ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
670 		ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
671 		gx_dc_type_none;
672 	    /* falls through */
673 	case 2:
674 	    ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none;
675 #undef ictype
676     }
677 }
678 
679 /* Initialize the color mapping tables for a non-mask image. */
680 private void
image_init_colors(gx_image_enum * penum,int bps,int spp,gs_image_format_t format,const float * decode,const gs_imager_state * pis,gx_device * dev,const gs_color_space * pcs,bool * pdcb)681 image_init_colors(gx_image_enum * penum, int bps, int spp,
682 		  gs_image_format_t format, const float *decode /*[spp*2] */ ,
683 		  const gs_imager_state * pis, gx_device * dev,
684 		  const gs_color_space * pcs, bool * pdcb)
685 {
686     int ci;
687     static const float default_decode[] = {
688 	0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
689     };
690 
691     image_init_clues(penum, bps, spp);
692 
693     /* Initialize the maps from samples to intensities. */
694     for (ci = 0; ci < spp; ci++) {
695 	sample_map *pmap = &penum->map[ci];
696 
697 	/* If the decoding is [0 1] or [1 0], we can fold it */
698 	/* into the expansion of the sample values; */
699 	/* otherwise, we have to use the floating point method. */
700 
701 	const float *this_decode = &decode[ci * 2];
702 	const float *map_decode;	/* decoding used to */
703 					/* construct the expansion map */
704 	const float *real_decode;	/* decoding for expanded samples */
705 
706 	bool no_decode;
707 
708 	map_decode = real_decode = this_decode;
709 	if (map_decode[0] == 0.0 && map_decode[1] == 1.0)
710 	    no_decode = true;
711 	else if (map_decode[0] == 1.0 && map_decode[1] == 0.0 && bps <= 8) {
712 	    no_decode = true;
713 	    real_decode = default_decode;
714 	} else {
715 	    no_decode = false;
716 	    *pdcb = false;
717 	    map_decode = default_decode;
718 	}
719 	if (bps > 2 || format != gs_image_format_chunky) {
720 	    if (bps <= 8)
721 		image_init_map(&pmap->table.lookup8[0], 1 << bps,
722 			       map_decode);
723 	} else {		/* The map index encompasses more than one pixel. */
724 	    byte map[4];
725 	    register int i;
726 
727 	    image_init_map(&map[0], 1 << bps, map_decode);
728 	    switch (bps) {
729 		case 1:
730 		    {
731 			register bits32 *p = &pmap->table.lookup4x1to32[0];
732 
733 			if (map[0] == 0 && map[1] == 0xff)
734 			    memcpy((byte *) p, lookup4x1to32_identity, 16 * 4);
735 			else if (map[0] == 0xff && map[1] == 0)
736 			    memcpy((byte *) p, lookup4x1to32_inverted, 16 * 4);
737 			else
738 			    for (i = 0; i < 16; i++, p++)
739 				((byte *) p)[0] = map[i >> 3],
740 				    ((byte *) p)[1] = map[(i >> 2) & 1],
741 				    ((byte *) p)[2] = map[(i >> 1) & 1],
742 				    ((byte *) p)[3] = map[i & 1];
743 		    }
744 		    break;
745 		case 2:
746 		    {
747 			register bits16 *p = &pmap->table.lookup2x2to16[0];
748 
749 			for (i = 0; i < 16; i++, p++)
750 			    ((byte *) p)[0] = map[i >> 2],
751 				((byte *) p)[1] = map[i & 3];
752 		    }
753 		    break;
754 	    }
755 	}
756 	pmap->decode_base /* = decode_lookup[0] */  = real_decode[0];
757 	pmap->decode_factor =
758 	    (real_decode[1] - real_decode[0]) /
759 	    (bps <= 8 ? 255.0 : (float)frac_1);
760 	pmap->decode_max /* = decode_lookup[15] */  = real_decode[1];
761 	if (no_decode) {
762 	    pmap->decoding = sd_none;
763 	    pmap->inverted = map_decode[0] != 0;
764 	} else if (bps <= 4) {
765 	    int step = 15 / ((1 << bps) - 1);
766 	    int i;
767 
768 	    pmap->decoding = sd_lookup;
769 	    for (i = 15 - step; i > 0; i -= step)
770 		pmap->decode_lookup[i] = pmap->decode_base +
771 		    i * (255.0 / 15) * pmap->decode_factor;
772 	} else
773 	    pmap->decoding = sd_compute;
774 	if (spp == 1) {		/* and ci == 0 *//* Pre-map entries 0 and 255. */
775 	    gs_client_color cc;
776 
777 	    cc.paint.values[0] = real_decode[0];
778 	    (*pcs->type->remap_color) (&cc, pcs, &penum->icolor0,
779 				       pis, dev, gs_color_select_source);
780 	    cc.paint.values[0] = real_decode[1];
781 	    (*pcs->type->remap_color) (&cc, pcs, &penum->icolor1,
782 				       pis, dev, gs_color_select_source);
783 	}
784     }
785 
786 }
787 /* Construct a mapping table for sample values. */
788 /* map_size is 2, 4, 16, or 256.  Note that 255 % (map_size - 1) == 0, */
789 /* so the division 0xffffL / (map_size - 1) is always exact. */
790 private void
image_init_map(byte * map,int map_size,const float * decode)791 image_init_map(byte * map, int map_size, const float *decode)
792 {
793     float min_v = decode[0];
794     float diff_v = decode[1] - min_v;
795 
796     if (diff_v == 1 || diff_v == -1) {	/* We can do the stepping with integers, without overflow. */
797 	byte *limit = map + map_size;
798 	uint value = (uint)(min_v * 0xffffL);
799 	int diff = (int)(diff_v * (0xffffL / (map_size - 1)));
800 
801 	for (; map != limit; map++, value += diff)
802 	    *map = value >> 8;
803     } else {			/* Step in floating point, with clamping. */
804 	int i;
805 
806 	for (i = 0; i < map_size; ++i) {
807 	    int value = (int)((min_v + diff_v * i / (map_size - 1)) * 255);
808 
809 	    map[i] = (value < 0 ? 0 : value > 255 ? 255 : value);
810 	}
811     }
812 }
813 
814 /*
815  * Scale a pair of mask_color values to match the scaling of each sample to
816  * a full byte, and complement and swap them if the map incorporates
817  * a Decode = [1 0] inversion.
818  */
819 void
gx_image_scale_mask_colors(gx_image_enum * penum,int component_index)820 gx_image_scale_mask_colors(gx_image_enum *penum, int component_index)
821 {
822     uint scale = 255 / ((1 << penum->bps) - 1);
823     uint *values = &penum->mask_color.values[component_index * 2];
824     uint v0 = values[0] *= scale;
825     uint v1 = values[1] *= scale;
826 
827     if (penum->map[component_index].decoding == sd_none &&
828 	penum->map[component_index].inverted
829 	) {
830 	values[0] = 255 - v1;
831 	values[1] = 255 - v0;
832     }
833 }
834