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