1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
3 This file is part of GNU Ghostscript.
5 GNU Ghostscript is distributed in the hope that it will be useful, but
6 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7 to anyone for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing. Refer
9 to the GNU General Public License for full details.
11 Everyone is granted permission to copy, modify and redistribute GNU
12 Ghostscript, but only under the conditions described in the GNU General
13 Public License. A copy of this license is supposed to have been given
14 to you along with GNU Ghostscript so you can know your rights and
15 responsibilities. It should be in a file named COPYING. Among other
16 things, the copyright notice and this notice must be preserved on all
19 Aladdin Enterprises supports the work of the GNU Project, but is not
20 affiliated with the Free Software Foundation or the GNU Project. GNU
21 Ghostscript, as distributed by Aladdin Enterprises, does not require any
22 GNU software to build or run it.
26 /* Image setup procedures for Ghostscript library */
49 /* ---------------- Generic image support ---------------- */
51 /* Initialize the common parts of image structures. */
53 gs_image_common_t_init(gs_image_common_t
* pic
)
55 gs_make_identity(&pic
->ImageMatrix
);
58 gs_data_image_t_init(gs_data_image_t
* pim
, int num_components
)
62 gs_image_common_t_init((gs_image_common_t
*) pim
);
63 pim
->Width
= pim
->Height
= 0;
64 pim
->BitsPerComponent
= 1;
65 if (num_components
>= 0) {
66 for (i
= 0; i
< num_components
* 2; i
+= 2)
67 pim
->Decode
[i
] = 0, pim
->Decode
[i
+ 1] = 1;
69 for (i
= 0; i
< num_components
* -2; i
+= 2)
70 pim
->Decode
[i
] = 1, pim
->Decode
[i
+ 1] = 0;
72 pim
->Interpolate
= false;
75 gs_pixel_image_t_init(gs_pixel_image_t
* pim
, const gs_color_space
* color_space
)
79 if (color_space
== 0 ||
81 gs_color_space_num_components(color_space
)) < 0
84 gs_data_image_t_init((gs_data_image_t
*) pim
, num_components
);
85 pim
->format
= gs_image_format_chunky
;
86 pim
->ColorSpace
= color_space
;
87 pim
->CombineWithColor
= false;
90 /* Initialize the common part of an image-processing enumerator. */
92 gx_image_enum_common_init(gx_image_enum_common_t
* piec
,
93 const gs_image_common_t
* pic
, const gx_image_enum_procs_t
* piep
,
94 gx_device
* dev
, int bits_per_component
, int num_components
,
95 gs_image_format_t format
)
97 piec
->image_type
= pic
->type
;
100 piec
->id
= gs_next_ids(1);
102 case gs_image_format_chunky
:
103 piec
->num_planes
= 1;
104 piec
->plane_depths
[0] = bits_per_component
* num_components
;
106 case gs_image_format_component_planar
:
107 piec
->num_planes
= num_components
;
111 for (i
= 0; i
< num_components
; ++i
)
112 piec
->plane_depths
[i
] = bits_per_component
;
115 case gs_image_format_bit_planar
:
116 piec
->num_planes
= bits_per_component
* num_components
;
120 for (i
= 0; i
< piec
->num_planes
; ++i
)
121 piec
->plane_depths
[i
] = 1;
123 #if 0 /* **************** */
125 #endif /* **************** */
127 return_error(gs_error_rangecheck
);
132 /* ---------------- ImageType 1 images ---------------- */
134 /* Structure descriptors */
135 private_st_gx_image_enum();
136 public_st_gs_image_common();
137 public_st_gs_data_image();
138 public_st_gs_pixel_image();
140 /* Strategy procedures */
141 gx_image_strategies_t image_strategies
;
143 /* Define the image type for ImageType 1 images. */
144 private const gx_image_type_t image1_type
= {
145 gx_begin_image1
, gx_data_image_source_size
, 1
147 private const gx_image_enum_procs_t image1_enum_procs
= {
148 gx_image1_plane_data
, gx_image1_end_image
, gx_image1_flush
151 /* Define the procedures for initializing gs_image_ts to default values. */
153 gs_image_t_init(gs_image_t
* pim
, const gs_color_space
* color_space
)
155 gs_pixel_image_t_init((gs_pixel_image_t
*) pim
, color_space
);
156 pim
->type
= &image1_type
;
157 pim
->ImageMask
= pim
->adjust
= (color_space
== NULL
);
158 pim
->Alpha
= gs_image_alpha_none
;
161 gs_image_t_init_mask(gs_image_t
* pim
, bool write_1s
)
163 gs_image_t_init(pim
, NULL
);
165 pim
->Decode
[0] = 1, pim
->Decode
[1] = 0;
167 pim
->Decode
[0] = 0, pim
->Decode
[1] = 1;
170 /* Compute the source size of an ordinary image with explicit data. */
172 gx_data_image_source_size(const gs_imager_state
* pis
,
173 const gs_image_common_t
* pim
, gs_int_point
* psize
)
175 const gs_data_image_t
*pdi
= (const gs_data_image_t
*)pim
;
177 psize
->x
= pdi
->Width
;
178 psize
->y
= pdi
->Height
;
182 /* Process the next piece of an image with no source data. */
183 /* This procedure should never be called. */
185 gx_no_image_plane_data(gx_device
* dev
,
186 gx_image_enum_common_t
* info
, const gx_image_plane_t
* planes
, int height
)
188 return_error(gs_error_Fatal
);
191 /* Clean up after processing an image with no source data. */
192 /* This procedure may be called, but should do nothing. */
194 gx_ignore_end_image(gx_device
* dev
, gx_image_enum_common_t
* info
,
201 #define eptr ((gx_image_enum *)vptr)
203 ENUM_PTRS_BEGIN(image_enum_enum_ptrs
)
208 /* Enumerate the used members of clues.dev_color. */
209 index
-= gx_image_enum_num_ptrs
;
210 bps
= eptr
->unpack_bps
;
213 else if (bps
> 8 || eptr
->unpack
== sample_unpack_copy
)
215 if (index
>= (1 << bps
) * st_device_color_max_ptrs
) /* done */
217 ret
= ENUM_USING(st_device_color
,
218 &eptr
->clues
[(index
/ st_device_color_max_ptrs
) *
219 (255 / ((1 << bps
) - 1))].dev_color
,
220 sizeof(eptr
->clues
[0].dev_color
),
221 index
% st_device_color_max_ptrs
);
222 if (ret
== 0) /* don't stop early */
226 #define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
227 gx_image_enum_do_ptrs(e1
)
230 private RELOC_PTRS_BEGIN(image_enum_reloc_ptrs
)
234 #define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
235 gx_image_enum_do_ptrs(r1
)
238 int bps
= eptr
->unpack_bps
;
242 else if (bps
> 8 || eptr
->unpack
== sample_unpack_copy
)
244 for (i
= 0; i
<= 255; i
+= 255 / ((1 << bps
) - 1))
245 RELOC_USING(st_device_color
,
246 &eptr
->clues
[i
].dev_color
, sizeof(gx_device_color
));
252 /* Forward declarations */
253 private int color_draws_b_w(P2(gx_device
* dev
,
254 const gx_drawing_color
* pdcolor
));
255 private void image_init_map(P3(byte
* map
, int map_size
, const float *decode
));
256 private void image_init_colors(P9(gx_image_enum
* penum
, int bps
, int spp
,
257 bool multi
, const float *decode
,
258 const gs_imager_state
* pis
, gx_device
* dev
,
259 const gs_color_space
* pcs
, bool * pdcb
));
261 /* Procedures for unpacking the input data into bytes or fracs. */
262 /*extern sample_unpack_proc(sample_unpack_copy); *//* declared above */
263 extern sample_unpack_proc(sample_unpack_1
);
264 extern sample_unpack_proc(sample_unpack_2
);
265 extern sample_unpack_proc(sample_unpack_4
);
266 extern sample_unpack_proc(sample_unpack_8
);
268 sample_unpack_proc((*sample_unpack_12_proc
)); /* optional */
270 /* Start processing an ImageType 1 image. */
271 /* Note that since this is actually a begin_typed_image procedure, */
272 /* the type of pim is the more abstract one. */
274 gx_begin_image1(gx_device
* dev
,
275 const gs_imager_state
* pis
, const gs_matrix
* pmat
,
276 const gs_image_common_t
* pic
, const gs_int_rect
* prect
,
277 const gx_drawing_color
* pdcolor
, const gx_clip_path
* pcpath
,
278 gs_memory_t
* mem
, gx_image_enum_common_t
** pinfo
)
280 const gs_image_t
*pim
= (const gs_image_t
*)pic
;
281 gs_image_format_t format
= pim
->format
;
282 gx_image_enum
*penum
;
283 const int width
= pim
->Width
;
284 const int height
= pim
->Height
;
285 const int bps
= pim
->BitsPerComponent
;
286 bool masked
= pim
->ImageMask
;
287 const float *decode
= pim
->Decode
;
290 const gs_color_space
*pcs
= pim
->ColorSpace
;
291 gs_logical_operation_t lop
= (pis
? pis
->log_op
: lop_default
);
294 int log2_xbytes
= (bps
<= 8 ? 0 : arch_log2_sizeof_frac
);
295 int spp
, nplanes
, spread
;
299 gs_fixed_point row_extent
, col_extent
, x_extent
, y_extent
;
301 gs_fixed_rect obox
, cbox
;
304 if (width
< 0 || height
< 0)
305 return_error(gs_error_rangecheck
);
307 case gs_image_format_chunky
:
310 case gs_image_format_component_planar
:
314 return_error(gs_error_rangecheck
);
333 return_error(gs_error_rangecheck
);
336 if (prect
->p
.x
< 0 || prect
->p
.y
< 0 ||
337 prect
->q
.x
< prect
->p
.x
|| prect
->q
.y
< prect
->p
.y
||
338 prect
->q
.x
> width
|| prect
->q
.y
> height
340 return_error(gs_error_rangecheck
);
343 pmat
= &ctm_only(pis
);
344 if ((code
= gs_matrix_invert(&pim
->ImageMatrix
, &mat
)) < 0 ||
345 (code
= gs_matrix_multiply(&mat
, pmat
, &mat
)) < 0 ||
347 gs_distance_transform2fixed((const gs_matrix_fixed
*)&mat
,
348 (floatp
) width
, (floatp
) 0,
351 gs_distance_transform2fixed((const gs_matrix_fixed
*)&mat
,
352 (floatp
) 0, (floatp
) height
,
356 penum
= gs_alloc_struct(mem
, gx_image_enum
, &st_gx_image_enum
,
357 "gx_default_begin_image");
359 return_error(gs_error_VMerror
);
360 gx_image_enum_common_init((gx_image_enum_common_t
*) penum
, pic
,
361 &image1_enum_procs
, dev
, bps
,
362 (masked
? 1 : cs_num_components(pcs
)),
365 penum
->rect
.x
= prect
->p
.x
, penum
->rect
.y
= prect
->p
.y
;
366 penum
->rect
.w
= prect
->q
.x
- prect
->p
.x
,
367 penum
->rect
.h
= prect
->q
.y
- prect
->p
.y
;
369 gs_distance_transform2fixed((const gs_matrix_fixed
*)&mat
,
370 (floatp
) penum
->rect
.w
, (floatp
) 0,
373 gs_distance_transform2fixed((const gs_matrix_fixed
*)&mat
,
374 (floatp
) 0, (floatp
) penum
->rect
.h
,
377 gs_free_object(mem
, penum
, "gx_default_begin_image");
381 penum
->rect
.x
= 0, penum
->rect
.y
= 0;
382 penum
->rect
.w
= width
, penum
->rect
.h
= height
;
383 x_extent
= row_extent
;
384 y_extent
= col_extent
;
386 if ((penum
->masked
= masked
)) { /* This is imagemask. */
387 if (bps
!= 1 || multi
|| pcs
!= NULL
|| pim
->Alpha
||
388 !((decode
[0] == 0.0 && decode
[1] == 1.0) ||
389 (decode
[0] == 1.0 && decode
[1] == 0.0))
391 gs_free_object(mem
, penum
, "gx_default_begin_image");
392 return_error(gs_error_rangecheck
);
394 /* Initialize color entries 0 and 255. */
395 color_set_pure(&penum
->icolor0
, gx_no_color_index
);
396 penum
->icolor1
= *pdcolor
;
397 memcpy(&penum
->map
[0].table
.lookup4x1to32
[0],
398 (decode
[0] == 0 ? lookup4x1to32_inverted
:
399 lookup4x1to32_identity
),
401 penum
->map
[0].decoding
= sd_none
;
403 adjust
= (pim
->adjust
? float2fixed(0.25) : fixed_0
);
404 lop
= rop3_know_S_0(lop
);
405 } else { /* This is image, not imagemask. */
406 const gs_color_space_type
*pcst
= pcs
->type
;
409 spp
= cs_num_components(pcs
);
410 if (spp
< 0) { /* Pattern not allowed */
411 gs_free_object(mem
, penum
, "gx_default_begin_image");
412 return_error(gs_error_rangecheck
);
418 device_color
= (*pcst
->concrete_space
) (pcs
, pis
) == pcs
;
419 image_init_colors(penum
, bps
, spp
, multi
, decode
, pis
, dev
,
422 /* Try to transform non-default RasterOps to something */
423 /* that we implement less expensively. */
424 if (!pim
->CombineWithColor
)
425 lop
= rop3_know_T_0(lop
) & ~lop_T_transparent
;
427 if (rop3_uses_T(lop
))
428 switch (color_draws_b_w(dev
, pdcolor
)) {
430 lop
= rop3_know_T_0(lop
);
433 lop
= rop3_know_T_1(lop
);
439 if (lop
!= rop3_S
&& /* if best case, no more work needed */
440 !rop3_uses_T(lop
) && bps
== 1 && spp
== 1 &&
442 color_draws_b_w(dev
, &penum
->icolor0
)) >= 0 &&
443 color_draws_b_w(dev
, &penum
->icolor1
) == (b_w_color
^ 1)
445 if (b_w_color
) { /* Swap the colors and invert the RasterOp source. */
446 gx_device_color dcolor
;
448 dcolor
= penum
->icolor0
;
449 penum
->icolor0
= penum
->icolor1
;
450 penum
->icolor1
= dcolor
;
451 lop
= rop3_invert_S(lop
);
454 * At this point, we know that the source pixels
455 * correspond directly to the S input for the raster op,
456 * i.e., icolor0 is black and icolor1 is white.
459 case rop3_D
& rop3_S
:
460 /* Implement this as an inverted mask writing 0s. */
461 penum
->icolor1
= penum
->icolor0
;
462 /* (falls through) */
463 case rop3_D
| rop3_not(rop3_S
):
464 /* Implement this as an inverted mask writing 1s. */
465 memcpy(&penum
->map
[0].table
.lookup4x1to32
[0],
466 lookup4x1to32_inverted
, 16 * 4);
467 rmask
: /* Fill in the remaining parameters for a mask. */
468 penum
->masked
= masked
= true;
469 color_set_pure(&penum
->icolor0
, gx_no_color_index
);
470 penum
->map
[0].decoding
= sd_none
;
473 case rop3_D
& rop3_not(rop3_S
):
474 /* Implement this as a mask writing 0s. */
475 penum
->icolor1
= penum
->icolor0
;
476 /* (falls through) */
477 case rop3_D
| rop3_S
:
478 /* Implement this as a mask writing 1s. */
479 memcpy(&penum
->map
[0].table
.lookup4x1to32
[0],
480 lookup4x1to32_identity
, 16 * 4);
487 penum
->device_color
= device_color
;
489 * Adjust width upward for unpacking up to 7 trailing bits in
490 * the row, plus 1 byte for end-of-run, plus up to 7 leading
491 * bits for data_x offset within a packed byte.
493 bsize
= ((bps
> 8 ? width
* 2 : width
) + 15) * spp
;
494 buffer
= gs_alloc_bytes(mem
, bsize
, "image buffer");
496 gs_free_object(mem
, penum
, "gx_default_begin_image");
497 return_error(gs_error_VMerror
);
500 penum
->unpack_bps
= bps
;
501 penum
->log2_xbytes
= log2_xbytes
;
503 penum
->alpha
= pim
->Alpha
;
504 nplanes
= (multi
? spp
: 1);
505 penum
->num_planes
= nplanes
;
506 spread
= nplanes
<< log2_xbytes
;
507 penum
->spread
= spread
;
509 penum
->x_extent
= x_extent
;
510 penum
->y_extent
= y_extent
;
512 ((x_extent
.y
| y_extent
.x
) == 0 ? image_portrait
:
513 (x_extent
.x
| y_extent
.y
) == 0 ? image_landscape
:
515 mtx
= float2fixed(mat
.tx
);
516 mty
= float2fixed(mat
.ty
);
520 penum
->buffer
= buffer
;
521 penum
->buffer_size
= bsize
;
523 penum
->line_size
= 0;
525 * If we're asked to interpolate in a partial image, we have to
526 * assume that the client either really only is interested in
527 * the given sub-image, or else is constructing output out of
528 * overlapping pieces.
530 penum
->interpolate
= pim
->Interpolate
;
531 penum
->use_rop
= lop
!= (masked
? rop3_T
: rop3_S
);
533 if (gs_debug_c('*')) {
535 dprintf1("[%03x]", lop
);
536 dprintf5("%c%d%c%dx%d ",
537 (masked
? (color_is_pure(pdcolor
) ? 'm' : 'h') : 'i'),
539 (penum
->posture
== image_portrait
? ' ' :
540 penum
->posture
== image_landscape
? 'L' : 'T'),
544 penum
->slow_loop
= 0;
546 (*dev_proc(dev
, get_clipping_box
)) (dev
, &obox
);
548 penum
->clip_image
= 0;
551 (gx_cpath_outer_box(pcpath
, &obox
) | /* not || */
552 gx_cpath_inner_box(pcpath
, &cbox
) ?
553 0 : image_clip_region
);
554 penum
->clip_outer
= obox
;
555 penum
->clip_inner
= cbox
;
556 penum
->log_op
= rop3_T
; /* rop device takes care of this */
557 penum
->clip_dev
= 0; /* in case we bail out */
558 penum
->rop_dev
= 0; /* ditto */
559 penum
->scaler
= 0; /* ditto */
561 * If all four extrema of the image fall within the clipping
562 * rectangle, clipping is never required. When making this check,
563 * we must carefully take into account the fact that we only care
564 * about pixel centers.
568 epx
= min(row_extent
.x
, 0) + min(col_extent
.x
, 0),
569 eqx
= max(row_extent
.x
, 0) + max(col_extent
.x
, 0),
570 epy
= min(row_extent
.y
, 0) + min(col_extent
.y
, 0),
571 eqy
= max(row_extent
.y
, 0) + max(col_extent
.y
, 0);
576 switch (penum
->posture
) {
578 hwx
= width
, hwy
= height
;
580 case image_landscape
:
581 hwx
= height
, hwy
= width
;
587 * If the image is only 1 sample wide or high,
588 * and is less than 1 device pixel wide or high,
589 * move it slightly so that it covers pixel centers.
590 * This is a hack to work around a bug in some old
591 * versions of TeX/dvips, which use 1-bit-high images
592 * to draw horizontal and vertical lines without
593 * positioning them properly.
595 if (hwx
== 1 && eqx
- epx
< fixed_1
) {
597 arith_rshift_1(row_extent
.x
+ col_extent
.x
);
599 mtx
= (((mtx
+ diff
) | fixed_half
) & -fixed_half
) - diff
;
601 if (hwy
== 1 && eqy
- epy
< fixed_1
) {
603 arith_rshift_1(row_extent
.y
+ col_extent
.y
);
605 mty
= (((mty
+ diff
) | fixed_half
) & -fixed_half
) - diff
;
608 if_debug5('b', "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
609 (masked
? "masked, " : ""), spp
, bps
,
610 fixed2float(mtx
), fixed2float(mty
));
612 "[b] cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
613 fixed2float(cbox
.p
.x
), fixed2float(cbox
.p
.y
),
614 fixed2float(cbox
.q
.x
), fixed2float(cbox
.q
.y
),
615 fixed2float(obox
.p
.x
), fixed2float(obox
.p
.y
),
616 fixed2float(obox
.q
.x
), fixed2float(obox
.q
.y
),
618 dda_init(penum
->dda
.row
.x
, mtx
, col_extent
.x
, height
);
619 dda_init(penum
->dda
.row
.y
, mty
, col_extent
.y
, height
);
621 dda_advance(penum
->dda
.row
.x
, penum
->rect
.y
);
622 dda_advance(penum
->dda
.row
.y
, penum
->rect
.y
);
624 penum
->cur
.x
= penum
->prev
.x
= dda_current(penum
->dda
.row
.x
);
625 penum
->cur
.y
= penum
->prev
.y
= dda_current(penum
->dda
.row
.y
);
626 dda_init(penum
->dda
.pixel0
.x
, penum
->cur
.x
, row_extent
.x
,
628 dda_init(penum
->dda
.pixel0
.y
, penum
->cur
.y
, row_extent
.y
,
631 dda_advance(penum
->dda
.pixel0
.x
, penum
->rect
.x
);
632 dda_advance(penum
->dda
.pixel0
.y
, penum
->rect
.x
);
634 fixed ox
= dda_current(penum
->dda
.pixel0
.x
);
635 fixed oy
= dda_current(penum
->dda
.pixel0
.y
);
637 if (!penum
->clip_image
) /* i.e., not clip region */
639 (fixed_pixround(ox
+ epx
) < fixed_pixround(cbox
.p
.x
) ?
640 image_clip_xmin
: 0) +
641 (fixed_pixround(ox
+ eqx
) >= fixed_pixround(cbox
.q
.x
) ?
642 image_clip_xmax
: 0) +
643 (fixed_pixround(oy
+ epy
) < fixed_pixround(cbox
.p
.y
) ?
644 image_clip_ymin
: 0) +
645 (fixed_pixround(oy
+ eqy
) >= fixed_pixround(cbox
.q
.y
) ?
646 image_clip_ymax
: 0);
650 penum
->adjust
= adjust
;
652 static const sample_unpack_proc_t procs
[4] =
654 sample_unpack_1
, sample_unpack_2
,
655 sample_unpack_4
, sample_unpack_8
658 if (index_bps
== 4) {
659 if ((penum
->unpack
= sample_unpack_12_proc
) == 0) { /* 12-bit samples are not supported. */
660 gx_default_end_image(dev
,
661 (gx_image_enum_common_t
*) penum
,
663 return_error(gs_error_rangecheck
);
666 penum
->unpack
= procs
[index_bps
];
667 if_debug1('b', "[b]unpack=%d\n", bps
);
669 #define use_strategy(sp)\
670 (image_strategies.sp != 0 &&\
671 (penum->render = (*image_strategies.sp)(penum)) != 0)
673 use_strategy(interpolate
) ||
674 use_strategy(simple
) ||
675 use_strategy(fracs
) ||
676 use_strategy(mono
) ||
681 else { /* No available strategy can handle this image. */
682 gx_default_end_image(dev
, (gx_image_enum_common_t
*) penum
,
684 return_error(gs_error_rangecheck
);
687 if (penum
->clip_image
&& pcpath
) { /* Set up the clipping device. */
688 gx_device_clip
*cdev
=
689 gs_alloc_struct(mem
, gx_device_clip
,
690 &st_device_clip
, "image clipper");
693 gx_default_end_image(dev
,
694 (gx_image_enum_common_t
*) penum
,
696 return_error(gs_error_VMerror
);
698 gx_make_clip_device(cdev
, cdev
, gx_cpath_list(pcpath
));
700 (*dev_proc(cdev
, open_device
)) ((gx_device
*) cdev
);
701 penum
->clip_dev
= cdev
;
703 if (penum
->use_rop
) { /* Set up the RasterOp source device. */
704 gx_device_rop_texture
*rtdev
;
706 code
= gx_alloc_rop_texture_device(&rtdev
, mem
,
709 gx_default_end_image(dev
, (gx_image_enum_common_t
*) penum
,
713 gx_make_rop_texture_device(rtdev
,
714 (penum
->clip_dev
!= 0 ?
715 (gx_device
*) penum
->clip_dev
:
717 penum
->rop_dev
= rtdev
;
720 if (gs_debug_c('b')) {
721 dlprintf2("[b]Image: w=%d h=%d", width
, height
);
723 dprintf4(" ((%d,%d),(%d,%d))",
724 prect
->p
.x
, prect
->p
.y
, prect
->q
.x
, prect
->q
.y
);
725 dprintf6(" [%g %g %g %g %g %g]\n",
726 mat
.xx
, mat
.xy
, mat
.yx
, mat
.yy
, mat
.tx
, mat
.ty
);
729 *pinfo
= (gx_image_enum_common_t
*) penum
;
733 /* If a drawing color is black or white, return 0 or 1 respectively, */
734 /* otherwise return -1. */
736 color_draws_b_w(gx_device
* dev
, const gx_drawing_color
* pdcolor
)
738 if (color_is_pure(pdcolor
)) {
739 gx_color_value rgb
[3];
741 (*dev_proc(dev
, map_color_rgb
)) (dev
, gx_dc_pure_color(pdcolor
),
743 if (!(rgb
[0] | rgb
[1] | rgb
[2]))
745 if ((rgb
[0] & rgb
[1] & rgb
[2]) == gx_max_color_value
)
751 /* Initialize the color mapping tables for a non-mask image. */
753 image_init_colors(gx_image_enum
* penum
, int bps
, int spp
, bool multi
,
754 const float *decode
/*[spp*2] */ , const gs_imager_state
* pis
, gx_device
* dev
,
755 const gs_color_space
* pcs
, bool * pdcb
)
758 static const float default_decode
[] =
760 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
763 /* Initialize the color table */
766 penum->clues[i].dev_color.type
767 switch ((spp
== 1 ? bps
: 8)) {
768 case 8: /* includes all color images */
770 register gx_image_clue
*pcht
= &penum
->clues
[0];
774 pcht
[0].dev_color
.type
=
775 pcht
[1].dev_color
.type
=
776 pcht
[2].dev_color
.type
=
777 pcht
[3].dev_color
.type
=
779 pcht
[0].key
= pcht
[1].key
=
780 pcht
[2].key
= pcht
[3].key
= 0;
784 penum
->clues
[0].key
= 1; /* guarantee no hit */
788 ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
789 ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
790 ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
791 ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
795 ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none
;
799 /* Initialize the maps from samples to intensities. */
801 for (ci
= 0; ci
< spp
; ci
++) {
802 sample_map
*pmap
= &penum
->map
[ci
];
804 /* If the decoding is [0 1] or [1 0], we can fold it */
805 /* into the expansion of the sample values; */
806 /* otherwise, we have to use the floating point method. */
808 const float *this_decode
= &decode
[ci
* 2];
809 const float *map_decode
; /* decoding used to */
811 /* construct the expansion map */
813 const float *real_decode
; /* decoding for */
815 /* expanded samples */
819 map_decode
= real_decode
= this_decode
;
820 if (map_decode
[0] == 0.0 && map_decode
[1] == 1.0)
822 else if (map_decode
[0] == 1.0 && map_decode
[1] == 0.0)
824 real_decode
= default_decode
;
828 map_decode
= default_decode
;
829 if (bps
> 2 || multi
) {
831 image_init_map(&pmap
->table
.lookup8
[0], 1 << bps
,
833 } else { /* The map index encompasses more than one pixel. */
837 image_init_map(&map
[0], 1 << bps
, map_decode
);
841 register bits32
*p
= &pmap
->table
.lookup4x1to32
[0];
843 if (map
[0] == 0 && map
[1] == 0xff)
844 memcpy((byte
*) p
, lookup4x1to32_identity
, 16 * 4);
845 else if (map
[0] == 0xff && map
[1] == 0)
846 memcpy((byte
*) p
, lookup4x1to32_inverted
, 16 * 4);
848 for (i
= 0; i
< 16; i
++, p
++)
849 ((byte
*) p
)[0] = map
[i
>> 3],
850 ((byte
*) p
)[1] = map
[(i
>> 2) & 1],
851 ((byte
*) p
)[2] = map
[(i
>> 1) & 1],
852 ((byte
*) p
)[3] = map
[i
& 1];
857 register bits16
*p
= &pmap
->table
.lookup2x2to16
[0];
859 for (i
= 0; i
< 16; i
++, p
++)
860 ((byte
*) p
)[0] = map
[i
>> 2],
861 ((byte
*) p
)[1] = map
[i
& 3];
866 pmap
->decode_base
/* = decode_lookup[0] */ = real_decode
[0];
867 pmap
->decode_factor
=
868 (real_decode
[1] - real_decode
[0]) /
869 (bps
<= 8 ? 255.0 : (float)frac_1
);
870 pmap
->decode_max
/* = decode_lookup[15] */ = real_decode
[1];
872 pmap
->decoding
= sd_none
;
874 int step
= 15 / ((1 << bps
) - 1);
877 pmap
->decoding
= sd_lookup
;
878 for (i
= 15 - step
; i
> 0; i
-= step
)
879 pmap
->decode_lookup
[i
] = pmap
->decode_base
+
880 i
* (255.0 / 15) * pmap
->decode_factor
;
882 pmap
->decoding
= sd_compute
;
883 if (spp
== 1) { /* and ci == 0 *//* Pre-map entries 0 and 255. */
886 cc
.paint
.values
[0] = real_decode
[0];
887 (*pcs
->type
->remap_color
) (&cc
, pcs
, &penum
->icolor0
,
888 pis
, dev
, gs_color_select_source
);
889 cc
.paint
.values
[0] = real_decode
[1];
890 (*pcs
->type
->remap_color
) (&cc
, pcs
, &penum
->icolor1
,
891 pis
, dev
, gs_color_select_source
);
896 /* Construct a mapping table for sample values. */
897 /* map_size is 2, 4, 16, or 256. Note that 255 % (map_size - 1) == 0, */
898 /* so the division 0xffffL / (map_size - 1) is always exact. */
900 image_init_map(byte
* map
, int map_size
, const float *decode
)
902 float min_v
= decode
[0];
903 float diff_v
= decode
[1] - min_v
;
905 if (diff_v
== 1 || diff_v
== -1) { /* We can do the stepping with integers, without overflow. */
906 byte
*limit
= map
+ map_size
;
907 uint value
= min_v
* 0xffffL
;
908 int diff
= diff_v
* (0xffffL
/ (map_size
- 1));
910 for (; map
!= limit
; map
++, value
+= diff
)
912 } else { /* Step in floating point, with clamping. */
915 for (i
= 0; i
< map_size
; ++i
) {
916 int value
= (int)((min_v
+ diff_v
* i
/ (map_size
- 1)) * 255);
918 map
[i
] = (value
< 0 ? 0 : value
> 255 ? 255 : value
);