1 /* Copyright (C) 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: gximage2.c,v 1.5 2002/08/22 07:12:29 henrys Exp $ */
18 /* ImageType 2 image implementation */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsmatrix.h" /* for gscoord.h */
24 #include "gscoord.h"
25 #include "gscspace.h"
26 #include "gscpixel.h"
27 #include "gsdevice.h"
28 #include "gsiparm2.h"
29 #include "gxgetbit.h"
30 #include "gxiparam.h"
31 #include "gxpath.h"
32 #include "gscolor2.h"
33
34 /* Forward references */
35 private dev_proc_begin_typed_image(gx_begin_image2);
36 private image_proc_source_size(gx_image2_source_size);
37
38 /* Structure descriptor */
39 private_st_gs_image2();
40
41 /* Define the image type for ImageType 2 images. */
42 const gx_image_type_t gs_image_type_2 = {
43 &st_gs_image2, gx_begin_image2, gx_image2_source_size,
44 gx_image_no_sput, gx_image_no_sget, gx_image_default_release, 2
45 };
46
47 /* Initialize an ImageType 2 image. */
48 void
gs_image2_t_init(gs_image2_t * pim)49 gs_image2_t_init(gs_image2_t * pim)
50 {
51 pim->type = &gs_image_type_2;
52 pim->UnpaintedPath = 0;
53 pim->PixelCopy = false;
54 }
55
56 /*
57 * Compute the device space coordinates and source data size for an
58 * ImageType 2 image. This procedure fills in
59 * image.{Width,Height,ImageMatrix}.
60 */
61 typedef struct image2_data_s {
62 gs_point origin;
63 gs_int_rect bbox;
64 gs_image1_t image;
65 } image2_data_t;
66 private int
image2_set_data(const gs_image2_t * pim,image2_data_t * pid)67 image2_set_data(const gs_image2_t * pim, image2_data_t * pid)
68 {
69 gs_state *pgs = pim->DataSource;
70 gs_matrix smat;
71 gs_rect sbox, dbox;
72
73 gs_transform(pgs, pim->XOrigin, pim->YOrigin, &pid->origin);
74 sbox.q.x = (sbox.p.x = pim->XOrigin) + pim->Width;
75 sbox.q.y = (sbox.p.y = pim->YOrigin) + pim->Height;
76 gs_currentmatrix(pgs, &smat);
77 gs_bbox_transform(&sbox, &smat, &dbox);
78 pid->bbox.p.x = (int)floor(dbox.p.x);
79 pid->bbox.p.y = (int)floor(dbox.p.y);
80 pid->bbox.q.x = (int)ceil(dbox.q.x);
81 pid->bbox.q.y = (int)ceil(dbox.q.y);
82 pid->image.Width = pid->bbox.q.x - pid->bbox.p.x;
83 pid->image.Height = pid->bbox.q.y - pid->bbox.p.y;
84 pid->image.ImageMatrix = pim->ImageMatrix;
85 return 0;
86 }
87
88 /* Compute the source size of an ImageType 2 image. */
89 private int
gx_image2_source_size(const gs_imager_state * pis,const gs_image_common_t * pim,gs_int_point * psize)90 gx_image2_source_size(const gs_imager_state * pis, const gs_image_common_t * pim,
91 gs_int_point * psize)
92 {
93 image2_data_t idata;
94
95 image2_set_data((const gs_image2_t *)pim, &idata);
96 psize->x = idata.image.Width;
97 psize->y = idata.image.Height;
98 return 0;
99 }
100
101 /* Begin an ImageType 2 image. */
102 /* Note that since ImageType 2 images don't have any source data, */
103 /* this procedure does all the work. */
104 private int
gx_begin_image2(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)105 gx_begin_image2(gx_device * dev,
106 const gs_imager_state * pis, const gs_matrix * pmat,
107 const gs_image_common_t * pic, const gs_int_rect * prect,
108 const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
109 gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
110 {
111 const gs_image2_t *pim = (const gs_image2_t *)pic;
112 gs_state *pgs = pim->DataSource;
113 gx_device *sdev = gs_currentdevice(pgs);
114 int depth = sdev->color_info.depth;
115 bool pixel_copy = pim->PixelCopy;
116 bool has_alpha;
117 bool direct_copy = false;
118 image2_data_t idata;
119 byte *row;
120 uint row_size, source_size;
121 gx_image_enum_common_t *info;
122 gs_matrix smat, dmat;
123 int code;
124
125 /* verify that color models are the same for PixelCopy */
126 if ( pixel_copy &&
127 memcmp( &dev->color_info,
128 &sdev->color_info,
129 sizeof(dev->color_info) ) != 0 )
130 return_error(gs_error_typecheck);
131
132 /****** ONLY HANDLE depth <= 8 FOR PixelCopy ******/
133 if (pixel_copy && depth <= 8)
134 return_error(gs_error_unregistered);
135
136 gs_image_t_init(&idata.image, gs_currentcolorspace((const gs_state *)pis));
137
138 /* Add Decode entries for K and alpha */
139 idata.image.Decode[6] = idata.image.Decode[8] = 0.0;
140 idata.image.Decode[7] = idata.image.Decode[9] = 1.0;
141 if (pmat == 0) {
142 gs_currentmatrix((const gs_state *)pis, &dmat);
143 pmat = &dmat;
144 } else
145 dmat = *pmat;
146 gs_currentmatrix(pgs, &smat);
147 code = image2_set_data(pim, &idata);
148 if (code < 0)
149 return code;
150 /****** ONLY HANDLE SIMPLE CASES FOR NOW ******/
151 if (idata.bbox.p.x != floor(idata.origin.x))
152 return_error(gs_error_rangecheck);
153 if (!(idata.bbox.p.y == floor(idata.origin.y) ||
154 idata.bbox.q.y == ceil(idata.origin.y))
155 )
156 return_error(gs_error_rangecheck);
157 source_size = (idata.image.Width * depth + 7) >> 3;
158 row_size = max(3 * idata.image.Width, source_size);
159 row = gs_alloc_bytes(mem, row_size, "gx_begin_image2");
160 if (row == 0)
161 return_error(gs_error_VMerror);
162 if (pixel_copy) {
163 idata.image.BitsPerComponent = depth;
164 has_alpha = false; /* no separate alpha channel */
165
166 if ( pcpath == NULL ||
167 gx_cpath_includes_rectangle(pcpath,
168 int2fixed(idata.bbox.p.x),
169 int2fixed(idata.bbox.p.y),
170 int2fixed(idata.bbox.q.x),
171 int2fixed(idata.bbox.q.y)) ) {
172 gs_matrix mat;
173
174
175 /*
176 * Figure 7.2 of the Adobe 3010 Supplement says that we should
177 * compute CTM x ImageMatrix here, but I'm almost certain it
178 * should be the other way around. Also see gdevx.c.
179 */
180 gs_matrix_multiply(&idata.image.ImageMatrix, &smat, &mat);
181 direct_copy =
182 (is_xxyy(&dmat) || is_xyyx(&dmat)) &&
183 #define eqe(e) mat.e == dmat.e
184 eqe(xx) && eqe(xy) && eqe(yx) && eqe(yy);
185 #undef eqe
186 }
187 } else {
188 idata.image.BitsPerComponent = 8;
189
190 /* Always use RGB source color for now.
191 *
192 * The source device has alpha if the same RGB values with
193 * different alphas map to different pixel values.
194 ****** THIS IS NOT GOOD ENOUGH: WE WANT TO SKIP TRANSFERRING
195 ****** ALPHA IF THE SOURCE IS CAPABLE OF HAVING ALPHA BUT
196 ****** DOESN'T CURRENTLY HAVE ANY ACTUAL ALPHA VALUES DIFFERENT
197 ****** FROM 1.
198 */
199 /*
200 * Since the default implementation of map_rgb_alpha_color
201 * premultiplies the color towards white, we can't just test
202 * whether changing alpha has an effect on the color.
203 */
204 {
205 gx_color_index trans_black =
206 (*dev_proc(sdev, map_rgb_alpha_color))
207 (sdev, (gx_color_value) 0, (gx_color_value) 0,
208 (gx_color_value) 0, (gx_color_value) 0);
209
210 has_alpha =
211 trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
212 (sdev, (gx_color_value) 0, (gx_color_value) 0,
213 (gx_color_value) 0, gx_max_color_value) &&
214 trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
215 (sdev, gx_max_color_value, gx_max_color_value,
216 gx_max_color_value, gx_max_color_value);
217 }
218 }
219 idata.image.Alpha =
220 (has_alpha ? gs_image_alpha_last : gs_image_alpha_none);
221 if (smat.yy < 0) {
222 /*
223 * The source Y axis is reflected. Reflect the mapping from
224 * user space to source data.
225 */
226 idata.image.ImageMatrix.ty += idata.image.Height *
227 idata.image.ImageMatrix.yy;
228 idata.image.ImageMatrix.xy = -idata.image.ImageMatrix.xy;
229 idata.image.ImageMatrix.yy = -idata.image.ImageMatrix.yy;
230 }
231 if (!direct_copy)
232 code = (*dev_proc(dev, begin_typed_image))
233 (dev, pis, pmat, (const gs_image_common_t *)&idata.image, NULL,
234 pdcolor, pcpath, mem, &info);
235 if (code >= 0) {
236 int y;
237 gs_int_rect rect;
238 gs_get_bits_params_t params;
239 const byte *data;
240 uint offset = row_size - source_size;
241
242 rect = idata.bbox;
243 for (y = 0; code >= 0 && y < idata.image.Height; ++y) {
244 gs_int_rect *unread = 0;
245 int num_unread;
246
247 /****** y COMPUTATION IS ROUNDED -- WRONG ******/
248 rect.q.y = rect.p.y + 1;
249 /* Insist on x_offset = 0 to simplify the conversion loop. */
250 params.options =
251 GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) |
252 GB_OFFSET_0 | (GB_RASTER_STANDARD | GB_RASTER_ANY) |
253 GB_PACKING_CHUNKY;
254 if (pixel_copy) {
255 params.options |= GB_COLORS_NATIVE;
256 params.data[0] = row + offset;
257 code = (*dev_proc(sdev, get_bits_rectangle))
258 (sdev, &rect, ¶ms, &unread);
259 if (code < 0)
260 break;
261 num_unread = code;
262 data = params.data[0];
263 if (direct_copy) {
264 /*
265 * Copy the pixels directly to the destination.
266 * We know that the transformation is only a translation,
267 * but we must handle an inverted destination Y axis.
268 */
269 code = (*dev_proc(dev, copy_color))
270 (dev, data, 0, row_size, gx_no_bitmap_id,
271 (int)(dmat.tx - idata.image.ImageMatrix.tx),
272 (int)(dmat.ty - idata.image.ImageMatrix.ty +
273 (dmat.yy < 0 ? ~y : y)),
274 idata.image.Width, 1);
275 continue;
276 }
277 } else {
278 /*
279 * Convert the pixels to pure colors. This may be very
280 * slow and painful. Eventually we will use indexed color for
281 * narrow pixels.
282 */
283 /* Always use RGB source color for now. */
284 params.options |=
285 GB_COLORS_RGB | GB_DEPTH_8 |
286 (has_alpha ? GB_ALPHA_LAST : GB_ALPHA_NONE);
287 params.data[0] = row;
288 code = (*dev_proc(sdev, get_bits_rectangle))
289 (sdev, &rect, ¶ms, &unread);
290 if (code < 0)
291 break;
292 num_unread = code;
293 data = params.data[0];
294 }
295 if (num_unread > 0 && pim->UnpaintedPath) {
296 /* Add the rectangle(s) to the unpainted path. */
297 int i;
298
299 for (i = 0; code >= 0 && i < num_unread; ++i)
300 code = gx_path_add_rectangle(pim->UnpaintedPath,
301 int2fixed(unread[i].p.x),
302 int2fixed(unread[i].p.y),
303 int2fixed(unread[i].q.x),
304 int2fixed(unread[i].q.y));
305 gs_free_object(dev->memory, unread, "UnpaintedPath unread");
306 }
307 code = gx_image_data(info, &data, 0, row_size, 1);
308 rect.p.y = rect.q.y;
309 }
310 if (!direct_copy) {
311 if (code >= 0)
312 code = gx_image_end(info, true);
313 else
314 discard(gx_image_end(info, false));
315 }
316 }
317 gs_free_object(mem, row, "gx_begin_image2");
318 return (code < 0 ? code : 1);
319 }
320