1 /* Copyright (C) 1994, 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: gxi16bit.c,v 1.2 2005/06/08 14:00:32 igor Exp $ */
18 /* 16-bit image procedures */
19 #include "gx.h"
20 #include "memory_.h"
21 #include "gpcheck.h"
22 #include "gserrors.h"
23 #include "gxfixed.h"
24 #include "gxfrac.h"
25 #include "gxarith.h"
26 #include "gxmatrix.h"
27 #include "gsccolor.h"
28 #include "gspaint.h"
29 #include "gxdevice.h"
30 #include "gxcmap.h"
31 #include "gxdcolor.h"
32 #include "gxistate.h"
33 #include "gxdevmem.h"
34 #include "gxcpath.h"
35 #include "gximage.h"
36
37 /* ---------------- Unpacking procedures ---------------- */
38
39 private const byte *
sample_unpack_16(byte * bptr,int * pdata_x,const byte * data,int data_x,uint dsize,const sample_map * ignore_smap,int spread,int ignore_num_components_per_plane)40 sample_unpack_16(byte * bptr, int *pdata_x, const byte * data,
41 int data_x, uint dsize, const sample_map *ignore_smap, int spread,
42 int ignore_num_components_per_plane)
43 {
44 /* Assuming an identity map for all components. */
45 register frac *bufp = (frac *) bptr;
46 uint dskip = data_x << 1;
47 const byte *psrc = data + dskip;
48 #define inc_bufp(bp, n) bp = (frac *)((byte *)(bp) + (n))
49 uint sample;
50 int left = dsize - dskip;
51
52 while (left > 2) {
53 sample = ((uint) psrc[0] << 8) + psrc[1];
54 *bufp = (frac)((frac_1 * (sample + 1)) >> 16);
55 inc_bufp(bufp, spread);
56 psrc += 2;
57 left -= 2;
58 }
59 *pdata_x = 0;
60 return bptr;
61 }
62
63 const sample_unpack_proc_t sample_unpack_16_proc = sample_unpack_16;
64
65 /* ---------------- Rendering procedures ---------------- */
66
67 /* ------ Rendering for 16-bit samples ------ */
68
69 #define FRACS_PER_LONG (arch_sizeof_long / arch_sizeof_frac)
70 typedef union {
71 frac v[GS_IMAGE_MAX_COLOR_COMPONENTS];
72 #define LONGS_PER_COLOR_FRACS\
73 ((GS_IMAGE_MAX_COLOR_COMPONENTS + FRACS_PER_LONG - 1) / FRACS_PER_LONG)
74 long all[LONGS_PER_COLOR_FRACS]; /* for fast comparison */
75 } color_fracs;
76
77 #define LONGS_PER_4_FRACS ((FRACS_PER_LONG + 3) / 4)
78 #if LONGS_PER_4_FRACS == 1
79 # define COLOR_FRACS_4_EQ(f1, f2)\
80 ((f1).all[0] == (f2).all[0])
81 #else
82 #if LONGS_PER_4_FRACS == 2
83 # define COLOR_FRACS_4_EQ(f1, f2)\
84 ((f1).all[0] == (f2).all[0] && (f1).all[1] == (f2).all[1])
85 #endif
86 #endif
87
88 /* Test whether a color is transparent. */
89 private bool
mask_color16_matches(const frac * v,const gx_image_enum * penum,int num_components)90 mask_color16_matches(const frac *v, const gx_image_enum *penum,
91 int num_components)
92 {
93 int i;
94
95 for (i = num_components * 2, v += num_components - 1; (i -= 2) >= 0; --v)
96 if (*v < penum->mask_color.values[i] ||
97 *v > penum->mask_color.values[i + 1]
98 )
99 return false;
100 return true;
101 }
102
103 /* Render an image with more than 8 bits per sample. */
104 /* The samples have been expanded into fracs. */
105 private int
image_render_frac(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)106 image_render_frac(gx_image_enum * penum, const byte * buffer, int data_x,
107 uint w, int h, gx_device * dev)
108 {
109 const gs_imager_state *pis = penum->pis;
110 gs_logical_operation_t lop = penum->log_op;
111 gx_dda_fixed_point pnext;
112 image_posture posture = penum->posture;
113 fixed xl, ytf;
114 fixed pdyx, pdyy; /* edge of parallelogram */
115 int yt = penum->yci, iht = penum->hci;
116 const gs_color_space *pcs = penum->pcs;
117 cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
118 gs_client_color cc;
119 bool device_color = penum->device_color;
120 const gx_color_map_procs *cmap_procs = gx_get_cmap_procs(pis, dev);
121 cmap_proc_rgb((*map_rgb)) = cmap_procs->map_rgb;
122 cmap_proc_cmyk((*map_cmyk)) = cmap_procs->map_cmyk;
123 bool use_mask_color = penum->use_mask_color;
124 gx_device_color devc1, devc2;
125 gx_device_color *pdevc = &devc1;
126 gx_device_color *pdevc_next = &devc2;
127 int spp = penum->spp;
128 const frac *psrc_initial = (const frac *)buffer + data_x * spp;
129 const frac *psrc = psrc_initial;
130 const frac *rsrc = psrc + spp; /* psrc + spp at start of run */
131 fixed xrun; /* x at start of run */
132 int irun; /* int xrun */
133 fixed yrun; /* y ditto */
134 color_fracs run; /* run value */
135 color_fracs next; /* next sample value */
136 const frac *bufend = psrc + w;
137 int code = 0, mcode = 0;
138
139 if (h == 0)
140 return 0;
141 pnext = penum->dda.pixel0;
142 xrun = xl = dda_current(pnext.x);
143 irun = fixed2int_var_rounded(xrun);
144 yrun = ytf = dda_current(pnext.y);
145 pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
146 pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
147 if_debug5('b', "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
148 penum->y, data_x, w, fixed2float(xl), fixed2float(ytf));
149 memset(&run, 0, sizeof(run));
150 memset(&next, 0, sizeof(next));
151 /* Ensure that we don't get any false dev_color_eq hits. */
152 set_nonclient_dev_color(&devc1, gx_no_color_index);
153 set_nonclient_dev_color(&devc2, gx_no_color_index);
154 cs_full_init_color(&cc, pcs);
155 run.v[0] = ~psrc[0]; /* force remap */
156
157 while (psrc < bufend) {
158 next.v[0] = psrc[0];
159 switch (spp) {
160 case 4: /* may be CMYK */
161 next.v[1] = psrc[1];
162 next.v[2] = psrc[2];
163 next.v[3] = psrc[3];
164 psrc += 4;
165 if (COLOR_FRACS_4_EQ(next, run))
166 goto inc;
167 if (use_mask_color && mask_color16_matches(next.v, penum, 4)) {
168 color_set_null(pdevc_next);
169 goto f;
170 }
171 if (device_color) {
172 (*map_cmyk) (next.v[0], next.v[1],
173 next.v[2], next.v[3],
174 pdevc_next, pis, dev,
175 gs_color_select_source);
176 goto f;
177 }
178 decode_frac(next.v[0], cc, 0);
179 decode_frac(next.v[1], cc, 1);
180 decode_frac(next.v[2], cc, 2);
181 decode_frac(next.v[3], cc, 3);
182 if_debug4('B', "[B]cc[0..3]=%g,%g,%g,%g\n",
183 cc.paint.values[0], cc.paint.values[1],
184 cc.paint.values[2], cc.paint.values[3]);
185 if_debug1('B', "[B]cc[3]=%g\n",
186 cc.paint.values[3]);
187 break;
188 case 3: /* may be RGB */
189 next.v[1] = psrc[1];
190 next.v[2] = psrc[2];
191 psrc += 3;
192 if (COLOR_FRACS_4_EQ(next, run))
193 goto inc;
194 if (use_mask_color && mask_color16_matches(next.v, penum, 3)) {
195 color_set_null(pdevc_next);
196 goto f;
197 }
198 if (device_color) {
199 (*map_rgb) (next.v[0], next.v[1],
200 next.v[2], pdevc_next, pis, dev,
201 gs_color_select_source);
202 goto f;
203 }
204 decode_frac(next.v[0], cc, 0);
205 decode_frac(next.v[1], cc, 1);
206 decode_frac(next.v[2], cc, 2);
207 if_debug3('B', "[B]cc[0..2]=%g,%g,%g\n",
208 cc.paint.values[0], cc.paint.values[1],
209 cc.paint.values[2]);
210 break;
211 case 1: /* may be Gray */
212 psrc++;
213 if (next.v[0] == run.v[0])
214 goto inc;
215 if (use_mask_color && mask_color16_matches(next.v, penum, 1)) {
216 color_set_null(pdevc_next);
217 goto f;
218 }
219 if (device_color) {
220 (*map_rgb) (next.v[0], next.v[0],
221 next.v[0], pdevc_next, pis, dev,
222 gs_color_select_source);
223 goto f;
224 }
225 decode_frac(next.v[0], cc, 0);
226 if_debug1('B', "[B]cc[0]=%g\n",
227 cc.paint.values[0]);
228 break;
229 default: /* DeviceN */
230 {
231 int i;
232
233 for (i = 1; i < spp; ++i)
234 next.v[i] = psrc[i];
235 psrc += spp;
236 if (!memcmp(next.v, run.v, spp * sizeof(next.v[0])))
237 goto inc;
238 if (use_mask_color &&
239 mask_color16_matches(next.v, penum, spp)
240 ) {
241 color_set_null(pdevc_next);
242 goto f;
243 }
244 for (i = 0; i < spp; ++i)
245 decode_frac(next.v[i], cc, i);
246 #ifdef DEBUG
247 if (gs_debug_c('B')) {
248 dprintf2("[B]cc[0..%d]=%g", spp - 1,
249 cc.paint.values[0]);
250 for (i = 1; i < spp; ++i)
251 dprintf1(",%g", cc.paint.values[i]);
252 dputs("\n");
253 }
254 #endif
255 }
256 break;
257 }
258 mcode = remap_color(&cc, pcs, pdevc_next, pis, dev,
259 gs_color_select_source);
260 if (mcode < 0)
261 goto fill;
262 f:
263 if_debug7('B', "[B]0x%x,0x%x,0x%x,0x%x -> %ld,%ld,0x%lx\n",
264 next.v[0], next.v[1], next.v[2], next.v[3],
265 pdevc_next->colors.binary.color[0],
266 pdevc_next->colors.binary.color[1],
267 (ulong) pdevc_next->type);
268 /* Even though the supplied colors don't match, */
269 /* the device colors might. */
270 if (!dev_color_eq(devc1, devc2)) {
271 /* Fill the region between xrun/irun and xl */
272 gx_device_color *ptemp;
273
274 fill:
275 if (posture != image_portrait) { /* Parallelogram */
276 code = (*dev_proc(dev, fill_parallelogram))
277 (dev, xrun, yrun,
278 xl - xrun, ytf - yrun, pdyx, pdyy,
279 pdevc, lop);
280 } else { /* Rectangle */
281 int xi = irun;
282 int wi = (irun = fixed2int_var_rounded(xl)) - xi;
283
284 if (wi < 0)
285 xi += wi, wi = -wi;
286 code = gx_fill_rectangle_device_rop(xi, yt,
287 wi, iht, pdevc, dev, lop);
288 }
289 if (code < 0)
290 goto err;
291 rsrc = psrc;
292 if ((code = mcode) < 0)
293 goto err;
294 ptemp = pdevc;
295 pdevc = pdevc_next;
296 pdevc_next = ptemp;
297 xrun = xl;
298 yrun = ytf;
299 }
300 run = next;
301 inc:
302 xl = dda_next(pnext.x);
303 ytf = dda_next(pnext.y);
304 }
305 /* Fill the final run. */
306 code = (*dev_proc(dev, fill_parallelogram))
307 (dev, xrun, yrun, xl - xrun, ytf - yrun, pdyx, pdyy, pdevc, lop);
308 return (code < 0 ? code : 1);
309
310 /* Save position if error, in case we resume. */
311 err:
312 penum->used.x = (rsrc - spp - psrc_initial) / spp;
313 penum->used.y = 0;
314 return code;
315 }
316