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: gxi12bit.c,v 1.7 2005/06/08 14:00:32 igor Exp $ */
18 /* 12-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_12(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_12(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) * 3;
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 if ((data_x & 1) && left > 0)
53 switch (left) {
54 default:
55 sample = ((uint) (psrc[1] & 0xf) << 8) + psrc[2];
56 *bufp = bits2frac(sample, 12);
57 inc_bufp(bufp, spread);
58 psrc += 3;
59 left -= 3;
60 break;
61 case 2: /* xxxxxxxx xxxxdddd */
62 *bufp = (psrc[1] & 0xf) * (frac_1 / 15);
63 case 1: /* xxxxxxxx */
64 left = 0;
65 }
66 while (left >= 3) {
67 sample = ((uint) * psrc << 4) + (psrc[1] >> 4);
68 *bufp = bits2frac(sample, 12);
69 inc_bufp(bufp, spread);
70 sample = ((uint) (psrc[1] & 0xf) << 8) + psrc[2];
71 *bufp = bits2frac(sample, 12);
72 inc_bufp(bufp, spread);
73 psrc += 3;
74 left -= 3;
75 }
76 /* Handle trailing bytes. */
77 switch (left) {
78 case 2: /* dddddddd ddddxxxx */
79 sample = ((uint) * psrc << 4) + (psrc[1] >> 4);
80 *bufp = bits2frac(sample, 12);
81 inc_bufp(bufp, spread);
82 *bufp = (psrc[1] & 0xf) * (frac_1 / 15);
83 break;
84 case 1: /* dddddddd */
85 sample = (uint) * psrc << 4;
86 *bufp = bits2frac(sample, 12);
87 break;
88 case 0: /* Nothing more to do. */
89 ;
90 }
91 *pdata_x = 0;
92 return bptr;
93 }
94
95 const sample_unpack_proc_t sample_unpack_12_proc = sample_unpack_12;
96
97 /* ------ Strategy procedure ------ */
98
99 /* Check the prototype. */
100 iclass_proc(gs_image_class_2_fracs);
101
102 /* Use special (slow) logic for 12-bit source values. */
103 private irender_proc(image_render_frac);
104 irender_proc_t
gs_image_class_2_fracs(gx_image_enum * penum)105 gs_image_class_2_fracs(gx_image_enum * penum)
106 {
107 if (penum->bps > 8) {
108 if (penum->use_mask_color) {
109 /* Convert color mask values to fracs. */
110 int i;
111
112 for (i = 0; i < penum->spp * 2; ++i)
113 penum->mask_color.values[i] =
114 bits2frac(penum->mask_color.values[i], 12);
115 }
116 if_debug0('b', "[b]render=frac\n");
117 return &image_render_frac;
118 }
119 return 0;
120 }
121
122 /* ---------------- Rendering procedures ---------------- */
123
124 /* ------ Rendering for 12-bit samples ------ */
125
126 #define FRACS_PER_LONG (arch_sizeof_long / arch_sizeof_frac)
127 typedef union {
128 frac v[GS_IMAGE_MAX_COLOR_COMPONENTS];
129 #define LONGS_PER_COLOR_FRACS\
130 ((GS_IMAGE_MAX_COLOR_COMPONENTS + FRACS_PER_LONG - 1) / FRACS_PER_LONG)
131 long all[LONGS_PER_COLOR_FRACS]; /* for fast comparison */
132 } color_fracs;
133
134 #define LONGS_PER_4_FRACS ((FRACS_PER_LONG + 3) / 4)
135 #if LONGS_PER_4_FRACS == 1
136 # define COLOR_FRACS_4_EQ(f1, f2)\
137 ((f1).all[0] == (f2).all[0])
138 #else
139 #if LONGS_PER_4_FRACS == 2
140 # define COLOR_FRACS_4_EQ(f1, f2)\
141 ((f1).all[0] == (f2).all[0] && (f1).all[1] == (f2).all[1])
142 #endif
143 #endif
144
145 /* Test whether a color is transparent. */
146 private bool
mask_color12_matches(const frac * v,const gx_image_enum * penum,int num_components)147 mask_color12_matches(const frac *v, const gx_image_enum *penum,
148 int num_components)
149 {
150 int i;
151
152 for (i = num_components * 2, v += num_components - 1; (i -= 2) >= 0; --v)
153 if (*v < penum->mask_color.values[i] ||
154 *v > penum->mask_color.values[i + 1]
155 )
156 return false;
157 return true;
158 }
159
160 /* Render an image with more than 8 bits per sample. */
161 /* The samples have been expanded into fracs. */
162 private int
image_render_frac(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)163 image_render_frac(gx_image_enum * penum, const byte * buffer, int data_x,
164 uint w, int h, gx_device * dev)
165 {
166 const gs_imager_state *pis = penum->pis;
167 gs_logical_operation_t lop = penum->log_op;
168 gx_dda_fixed_point pnext;
169 image_posture posture = penum->posture;
170 fixed xl, ytf;
171 fixed pdyx, pdyy; /* edge of parallelogram */
172 int yt = penum->yci, iht = penum->hci;
173 const gs_color_space *pcs = penum->pcs;
174 cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
175 gs_client_color cc;
176 bool device_color = penum->device_color;
177 const gx_color_map_procs *cmap_procs = gx_get_cmap_procs(pis, dev);
178 cmap_proc_rgb((*map_rgb)) = cmap_procs->map_rgb;
179 cmap_proc_cmyk((*map_cmyk)) = cmap_procs->map_cmyk;
180 bool use_mask_color = penum->use_mask_color;
181 gx_device_color devc1, devc2;
182 gx_device_color *pdevc = &devc1;
183 gx_device_color *pdevc_next = &devc2;
184 int spp = penum->spp;
185 const frac *psrc_initial = (const frac *)buffer + data_x * spp;
186 const frac *psrc = psrc_initial;
187 const frac *rsrc = psrc + spp; /* psrc + spp at start of run */
188 fixed xrun; /* x at start of run */
189 int irun; /* int xrun */
190 fixed yrun; /* y ditto */
191 color_fracs run; /* run value */
192 color_fracs next; /* next sample value */
193 const frac *bufend = psrc + w;
194 int code = 0, mcode = 0;
195
196 if (h == 0)
197 return 0;
198 pnext = penum->dda.pixel0;
199 xrun = xl = dda_current(pnext.x);
200 irun = fixed2int_var_rounded(xrun);
201 yrun = ytf = dda_current(pnext.y);
202 pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
203 pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
204 if_debug5('b', "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
205 penum->y, data_x, w, fixed2float(xl), fixed2float(ytf));
206 memset(&run, 0, sizeof(run));
207 memset(&next, 0, sizeof(next));
208 /* Ensure that we don't get any false dev_color_eq hits. */
209 set_nonclient_dev_color(&devc1, gx_no_color_index);
210 set_nonclient_dev_color(&devc2, gx_no_color_index);
211 cs_full_init_color(&cc, pcs);
212 run.v[0] = ~psrc[0]; /* force remap */
213
214 while (psrc < bufend) {
215 next.v[0] = psrc[0];
216 switch (spp) {
217 case 4: /* may be CMYK */
218 next.v[1] = psrc[1];
219 next.v[2] = psrc[2];
220 next.v[3] = psrc[3];
221 psrc += 4;
222 if (COLOR_FRACS_4_EQ(next, run))
223 goto inc;
224 if (use_mask_color && mask_color12_matches(next.v, penum, 4)) {
225 color_set_null(pdevc_next);
226 goto f;
227 }
228 if (device_color) {
229 (*map_cmyk) (next.v[0], next.v[1],
230 next.v[2], next.v[3],
231 pdevc_next, pis, dev,
232 gs_color_select_source);
233 goto f;
234 }
235 decode_frac(next.v[0], cc, 0);
236 decode_frac(next.v[1], cc, 1);
237 decode_frac(next.v[2], cc, 2);
238 decode_frac(next.v[3], cc, 3);
239 if_debug4('B', "[B]cc[0..3]=%g,%g,%g,%g\n",
240 cc.paint.values[0], cc.paint.values[1],
241 cc.paint.values[2], cc.paint.values[3]);
242 if_debug1('B', "[B]cc[3]=%g\n",
243 cc.paint.values[3]);
244 break;
245 case 3: /* may be RGB */
246 next.v[1] = psrc[1];
247 next.v[2] = psrc[2];
248 psrc += 3;
249 if (COLOR_FRACS_4_EQ(next, run))
250 goto inc;
251 if (use_mask_color && mask_color12_matches(next.v, penum, 3)) {
252 color_set_null(pdevc_next);
253 goto f;
254 }
255 if (device_color) {
256 (*map_rgb) (next.v[0], next.v[1],
257 next.v[2], pdevc_next, pis, dev,
258 gs_color_select_source);
259 goto f;
260 }
261 decode_frac(next.v[0], cc, 0);
262 decode_frac(next.v[1], cc, 1);
263 decode_frac(next.v[2], cc, 2);
264 if_debug3('B', "[B]cc[0..2]=%g,%g,%g\n",
265 cc.paint.values[0], cc.paint.values[1],
266 cc.paint.values[2]);
267 break;
268 case 1: /* may be Gray */
269 psrc++;
270 if (next.v[0] == run.v[0])
271 goto inc;
272 if (use_mask_color && mask_color12_matches(next.v, penum, 1)) {
273 color_set_null(pdevc_next);
274 goto f;
275 }
276 if (device_color) {
277 (*map_rgb) (next.v[0], next.v[0],
278 next.v[0], pdevc_next, pis, dev,
279 gs_color_select_source);
280 goto f;
281 }
282 decode_frac(next.v[0], cc, 0);
283 if_debug1('B', "[B]cc[0]=%g\n",
284 cc.paint.values[0]);
285 break;
286 default: /* DeviceN */
287 {
288 int i;
289
290 for (i = 1; i < spp; ++i)
291 next.v[i] = psrc[i];
292 psrc += spp;
293 if (!memcmp(next.v, run.v, spp * sizeof(next.v[0])))
294 goto inc;
295 if (use_mask_color &&
296 mask_color12_matches(next.v, penum, spp)
297 ) {
298 color_set_null(pdevc_next);
299 goto f;
300 }
301 for (i = 0; i < spp; ++i)
302 decode_frac(next.v[i], cc, i);
303 #ifdef DEBUG
304 if (gs_debug_c('B')) {
305 dprintf2("[B]cc[0..%d]=%g", spp - 1,
306 cc.paint.values[0]);
307 for (i = 1; i < spp; ++i)
308 dprintf1(",%g", cc.paint.values[i]);
309 dputs("\n");
310 }
311 #endif
312 }
313 break;
314 }
315 mcode = remap_color(&cc, pcs, pdevc_next, pis, dev,
316 gs_color_select_source);
317 if (mcode < 0)
318 goto fill;
319 f:
320 if_debug7('B', "[B]0x%x,0x%x,0x%x,0x%x -> %ld,%ld,0x%lx\n",
321 next.v[0], next.v[1], next.v[2], next.v[3],
322 pdevc_next->colors.binary.color[0],
323 pdevc_next->colors.binary.color[1],
324 (ulong) pdevc_next->type);
325 /* Even though the supplied colors don't match, */
326 /* the device colors might. */
327 if (!dev_color_eq(devc1, devc2)) {
328 /* Fill the region between xrun/irun and xl */
329 gx_device_color *ptemp;
330
331 fill:
332 if (posture != image_portrait) { /* Parallelogram */
333 code = (*dev_proc(dev, fill_parallelogram))
334 (dev, xrun, yrun,
335 xl - xrun, ytf - yrun, pdyx, pdyy,
336 pdevc, lop);
337 } else { /* Rectangle */
338 int xi = irun;
339 int wi = (irun = fixed2int_var_rounded(xl)) - xi;
340
341 if (wi < 0)
342 xi += wi, wi = -wi;
343 code = gx_fill_rectangle_device_rop(xi, yt,
344 wi, iht, pdevc, dev, lop);
345 }
346 if (code < 0)
347 goto err;
348 rsrc = psrc;
349 if ((code = mcode) < 0)
350 goto err;
351 ptemp = pdevc;
352 pdevc = pdevc_next;
353 pdevc_next = ptemp;
354 xrun = xl;
355 yrun = ytf;
356 }
357 run = next;
358 inc:
359 xl = dda_next(pnext.x);
360 ytf = dda_next(pnext.y);
361 }
362 /* Fill the final run. */
363 code = (*dev_proc(dev, fill_parallelogram))
364 (dev, xrun, yrun, xl - xrun, ytf - yrun, pdyx, pdyy, pdevc, lop);
365 return (code < 0 ? code : 1);
366
367 /* Save position if error, in case we resume. */
368 err:
369 penum->used.x = (rsrc - spp - psrc_initial) / spp;
370 penum->used.y = 0;
371 return code;
372 }
373