1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* 12-bit image procedures */
18 #include "gx.h"
19 #include "memory_.h"
20 #include "gpcheck.h"
21 #include "gserrors.h"
22 #include "gxfixed.h"
23 #include "gxfrac.h"
24 #include "gxarith.h"
25 #include "gxmatrix.h"
26 #include "gsccolor.h"
27 #include "gspaint.h"
28 #include "gxdevice.h"
29 #include "gxcmap.h"
30 #include "gxdcolor.h"
31 #include "gxgstate.h"
32 #include "gxdevmem.h"
33 #include "gxcpath.h"
34 #include "gximage.h"
35 #include "gsicc.h"
36 #include "gsicc_cache.h"
37 #include "gsicc_cms.h"
38 #include "gxcie.h"
39 #include "gscie.h"
40 #include "gxdevsop.h"
41
42 /* ---------------- Unpacking procedures ---------------- */
43
44 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)45 sample_unpack_12(byte * bptr, int *pdata_x, const byte * data,
46 int data_x, uint dsize, const sample_map *ignore_smap, int spread,
47 int ignore_num_components_per_plane)
48 {
49 /* Assuming an identity map for all components. */
50 register frac *bufp = (frac *) bptr;
51 uint dskip = (data_x >> 1) * 3;
52 const byte *psrc = data + dskip;
53 #define inc_bufp(bp, n) bp = (frac *)((byte *)(bp) + (n))
54 uint sample;
55 int left = dsize - dskip;
56
57 if ((data_x & 1) && left > 0)
58 switch (left) {
59 default:
60 sample = ((uint) (psrc[1] & 0xf) << 8) + psrc[2];
61 *bufp = bits2frac(sample, 12);
62 inc_bufp(bufp, spread);
63 psrc += 3;
64 left -= 3;
65 break;
66 case 2: /* xxxxxxxx xxxxdddd */
67 *bufp = (psrc[1] & 0xf) * (frac_1 / 15);
68 case 1: /* xxxxxxxx */
69 left = 0;
70 }
71 while (left >= 3) {
72 sample = ((uint) * psrc << 4) + (psrc[1] >> 4);
73 *bufp = bits2frac(sample, 12);
74 inc_bufp(bufp, spread);
75 sample = ((uint) (psrc[1] & 0xf) << 8) + psrc[2];
76 *bufp = bits2frac(sample, 12);
77 inc_bufp(bufp, spread);
78 psrc += 3;
79 left -= 3;
80 }
81 /* Handle trailing bytes. */
82 switch (left) {
83 case 2: /* dddddddd ddddxxxx */
84 sample = ((uint) * psrc << 4) + (psrc[1] >> 4);
85 *bufp = bits2frac(sample, 12);
86 inc_bufp(bufp, spread);
87 *bufp = (psrc[1] & 0xf) * (frac_1 / 15);
88 break;
89 case 1: /* dddddddd */
90 sample = (uint) * psrc << 4;
91 *bufp = bits2frac(sample, 12);
92 break;
93 case 0: /* Nothing more to do. */
94 ;
95 }
96 *pdata_x = 0;
97 return bptr;
98 }
99
100 /* ------ Strategy procedure ------ */
101
102 /* Check the prototype. */
103 iclass_proc(gs_image_class_2_fracs);
104
105 /* Use special (slow) logic for 12-bit source values. */
106 static irender_proc(image_render_frac);
107 static irender_proc(image_render_icc16); /* icc 16bit case */
108
109 int
gs_image_class_2_fracs(gx_image_enum * penum,irender_proc_t * render_fn)110 gs_image_class_2_fracs(gx_image_enum * penum, irender_proc_t *render_fn)
111 {
112 bool std_cmap_procs;
113
114 if (penum->bps > 8) {
115 if (penum->use_mask_color) {
116 /* Convert color mask values to fracs. */
117 int i;
118
119 for (i = 0; i < penum->spp * 2; ++i)
120 penum->mask_color.values[i] =
121 bits2frac(penum->mask_color.values[i], 12);
122 }
123 /* If the device has some unique color mapping procs due to its color space,
124 then we will need to use those and go through pixel by pixel instead
125 of blasting through buffers. This is true for example with many of
126 the color spaces for CUPs */
127 std_cmap_procs = gx_device_uses_std_cmap_procs(penum->dev, penum->pgs);
128 if ( (gs_color_space_get_index(penum->pcs) == gs_color_space_index_DeviceN &&
129 penum->pcs->cmm_icc_profile_data == NULL) || penum->use_mask_color ||
130 penum->bps != 16 || !std_cmap_procs ||
131 gs_color_space_get_index(penum->pcs) == gs_color_space_index_DevicePixel ||
132 gs_color_space_get_index(penum->pcs) == gs_color_space_index_Indexed) {
133 /* DevicePixel color space used in mask from 3x type. Basically
134 a simple color space that just is scaled to the device bit
135 depth when remapped. No CM needed */
136 if_debug0m('b', penum->memory, "[b]render=frac\n");
137 *render_fn = &image_render_frac;
138 return 0;
139 } else {
140 /* Set up the link now */
141 const gs_color_space *pcs;
142 gsicc_rendering_param_t rendering_params;
143 int k;
144 int src_num_comp = cs_num_components(penum->pcs);
145 int num_des_comps;
146 int code;
147 cmm_dev_profile_t *dev_profile;
148
149 code = dev_proc(penum->dev, get_profile)(penum->dev, &dev_profile);
150 if (code < 0)
151 return 0;
152 num_des_comps = gsicc_get_device_profile_comps(dev_profile);
153 penum->icc_setup.need_decode = false;
154 /* Check if we need to do any decoding. If yes, then that will slow us down */
155 for (k = 0; k < src_num_comp; k++) {
156 if ( penum->map[k].decoding != sd_none ) {
157 penum->icc_setup.need_decode = true;
158 break;
159 }
160 }
161 /* Define the rendering intents */
162 rendering_params.black_point_comp = penum->pgs->blackptcomp;
163 rendering_params.graphics_type_tag = GS_IMAGE_TAG;
164 rendering_params.override_icc = false;
165 rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
166 rendering_params.rendering_intent = penum->pgs->renderingintent;
167 rendering_params.cmm = gsCMM_DEFAULT;
168 if (gs_color_space_is_PSCIE(penum->pcs) && penum->pcs->icc_equivalent != NULL) {
169 pcs = penum->pcs->icc_equivalent;
170 } else {
171 pcs = penum->pcs;
172 }
173 penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
174 penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
175 penum->icc_setup.has_transfer =
176 gx_has_transfer(penum->pgs, num_des_comps);
177 if (penum->icc_setup.is_lab) penum->icc_setup.need_decode = false;
178 if (penum->icc_link == NULL) {
179 penum->icc_link = gsicc_get_link(penum->pgs, penum->dev, pcs, NULL,
180 &rendering_params, penum->memory);
181 }
182 /* Use the direct unpacking proc */
183 penum->unpack = sample_unpackicc_16;
184 if_debug0m('b', penum->memory, "[b]render=icc16\n");
185 *render_fn = &image_render_icc16;
186 return 0;
187 }
188 }
189 return 0;
190 }
191
192 /* ---------------- Rendering procedures ---------------- */
193
194 /* ------ Rendering for 12-bit samples ------ */
195
196 #define FRACS_PER_LONG (ARCH_SIZEOF_LONG / arch_sizeof_frac)
197 typedef union {
198 frac v[GS_IMAGE_MAX_COLOR_COMPONENTS];
199 #define LONGS_PER_COLOR_FRACS\
200 ((GS_IMAGE_MAX_COLOR_COMPONENTS + FRACS_PER_LONG - 1) / FRACS_PER_LONG)
201 long all[LONGS_PER_COLOR_FRACS]; /* for fast comparison */
202 } color_fracs;
203
204 #define LONGS_PER_4_FRACS ((arch_sizeof_frac * 4 + ARCH_SIZEOF_LONG - 1) / ARCH_SIZEOF_LONG)
205 #if LONGS_PER_4_FRACS == 1
206 # define COLOR_FRACS_4_EQ(f1, f2)\
207 ((f1).all[0] == (f2).all[0])
208 #else
209 #if LONGS_PER_4_FRACS == 2
210 # define COLOR_FRACS_4_EQ(f1, f2)\
211 ((f1).all[0] == (f2).all[0] && (f1).all[1] == (f2).all[1])
212 #endif
213 #endif
214
215 /* Test whether a color is transparent. */
216 static bool
mask_color12_matches(const frac * v,const gx_image_enum * penum,int num_components)217 mask_color12_matches(const frac *v, const gx_image_enum *penum,
218 int num_components)
219 {
220 int i;
221
222 for (i = num_components * 2, v += num_components - 1; (i -= 2) >= 0; --v)
223 if (*v < penum->mask_color.values[i] ||
224 *v > penum->mask_color.values[i + 1]
225 )
226 return false;
227 return true;
228 }
229
230 /* Render an image with more than 8 bits per sample. */
231 /* The samples have been expanded into fracs. */
232 static int
image_render_frac(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)233 image_render_frac(gx_image_enum * penum, const byte * buffer, int data_x,
234 uint w, int h, gx_device * dev)
235 {
236 const gs_gstate *pgs = penum->pgs;
237 gs_logical_operation_t lop = penum->log_op;
238 gx_dda_fixed_point pnext;
239 image_posture posture = penum->posture;
240 fixed xl, ytf;
241 fixed pdyx, pdyy; /* edge of parallelogram */
242 int yt = penum->yci, iht = penum->hci;
243 const gs_color_space *pcs = penum->pcs;
244 cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
245 gs_client_color cc;
246 bool device_color = penum->device_color;
247 const gx_color_map_procs *cmap_procs = gx_get_cmap_procs(pgs, dev);
248 cmap_proc_rgb((*map_rgb)) = cmap_procs->map_rgb;
249 cmap_proc_cmyk((*map_cmyk)) = cmap_procs->map_cmyk;
250 bool use_mask_color = penum->use_mask_color;
251 gx_device_color devc1, devc2;
252 gx_device_color *pdevc = &devc1;
253 gx_device_color *pdevc_next = &devc2;
254 int spp = penum->spp;
255 const frac *psrc_initial = (const frac *)buffer + data_x * spp;
256 const frac *psrc = psrc_initial;
257 const frac *rsrc = psrc + spp; /* psrc + spp at start of run */
258 fixed xrun; /* x at start of run */
259 int irun; /* int xrun */
260 fixed yrun; /* y ditto */
261 color_fracs run; /* run value */
262 color_fracs next; /* next sample value */
263 const frac *bufend = psrc + w;
264 int code = 0, mcode = 0;
265 int i;
266 bool is_devn = false;
267 bool is_sep = (gs_color_space_get_index(penum->pcs) ==
268 gs_color_space_index_Separation);
269
270 if (h == 0)
271 return 0;
272 pnext = penum->dda.pixel0;
273 xrun = xl = dda_current(pnext.x);
274 irun = fixed2int_var_rounded(xrun);
275 yrun = ytf = dda_current(pnext.y);
276 pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
277 pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
278 if_debug5m('b', penum->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
279 penum->y, data_x, w, fixed2float(xl), fixed2float(ytf));
280 memset(&run, 0, sizeof(run));
281 memset(&next, 0, sizeof(next));
282 /* Ensure that we don't get any false dev_color_eq hits. */
283 set_nonclient_dev_color(&devc1, gx_no_color_index);
284 set_nonclient_dev_color(&devc2, gx_no_color_index);
285 cs_full_init_color(&cc, pcs);
286 run.v[0] = ~psrc[0]; /* force remap */
287
288 if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) {
289 for (i = 0; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++) {
290 pdevc->colors.devn.values[i] = 0;
291 pdevc_next->colors.devn.values[i] = 0;
292 }
293 is_devn = true;
294 }
295 while (psrc < bufend) {
296 next.v[0] = psrc[0];
297 switch (spp) {
298 case 4: /* may be CMYK */
299 next.v[1] = psrc[1];
300 next.v[2] = psrc[2];
301 next.v[3] = psrc[3];
302 psrc += 4;
303 if (COLOR_FRACS_4_EQ(next, run))
304 goto inc;
305 if (use_mask_color && mask_color12_matches(next.v, penum, 4)) {
306 color_set_null(pdevc_next);
307 goto f;
308 }
309 if (device_color) {
310 (*map_cmyk) (next.v[0], next.v[1],
311 next.v[2], next.v[3],
312 pdevc_next, pgs, dev,
313 gs_color_select_source, NULL);
314 goto f;
315 }
316 decode_frac(next.v[0], cc, 0);
317 decode_frac(next.v[1], cc, 1);
318 decode_frac(next.v[2], cc, 2);
319 decode_frac(next.v[3], cc, 3);
320 if_debug4m('B', penum->memory, "[B]cc[0..3]=%g,%g,%g,%g\n",
321 cc.paint.values[0], cc.paint.values[1],
322 cc.paint.values[2], cc.paint.values[3]);
323 break;
324 case 3: /* may be RGB */
325 next.v[1] = psrc[1];
326 next.v[2] = psrc[2];
327 psrc += 3;
328 if (COLOR_FRACS_4_EQ(next, run))
329 goto inc;
330 if (use_mask_color && mask_color12_matches(next.v, penum, 3)) {
331 color_set_null(pdevc_next);
332 goto f;
333 }
334 if (device_color) {
335 (*map_rgb) (next.v[0], next.v[1],
336 next.v[2], pdevc_next, pgs, dev,
337 gs_color_select_source);
338 goto f;
339 }
340 decode_frac(next.v[0], cc, 0);
341 decode_frac(next.v[1], cc, 1);
342 decode_frac(next.v[2], cc, 2);
343 if_debug3m('B', penum->memory, "[B]cc[0..2]=%g,%g,%g\n",
344 cc.paint.values[0], cc.paint.values[1],
345 cc.paint.values[2]);
346 break;
347 case 1: /* may be Gray, but could be a separation */
348 if (is_devn && is_sep) {
349 psrc++;
350 if (next.v[0] == run.v[0])
351 goto inc;
352 if (use_mask_color && mask_color12_matches(next.v, penum, 1)) {
353 color_set_null(pdevc_next);
354 goto f;
355 }
356 decode_frac(next.v[0], cc, 0);
357 if_debug1m('B', penum->memory, "[B]cc[0]=%g\n",
358 cc.paint.values[0]);
359 break;
360 } else {
361 psrc++;
362 if (next.v[0] == run.v[0])
363 goto inc;
364 if (use_mask_color && mask_color12_matches(next.v, penum, 1)) {
365 color_set_null(pdevc_next);
366 goto f;
367 }
368 if (device_color) {
369 (*map_rgb) (next.v[0], next.v[0],
370 next.v[0], pdevc_next, pgs, dev,
371 gs_color_select_source);
372 goto f;
373 }
374 decode_frac(next.v[0], cc, 0);
375 if_debug1('B', "[B]cc[0]=%g\n",
376 cc.paint.values[0]);
377 break;
378 }
379 default: /* DeviceN */
380 {
381 int i;
382
383 for (i = 1; i < spp; ++i)
384 next.v[i] = psrc[i];
385 psrc += spp;
386 if (!memcmp(next.v, run.v, spp * sizeof(next.v[0])))
387 goto inc;
388 if (use_mask_color &&
389 mask_color12_matches(next.v, penum, spp)
390 ) {
391 color_set_null(pdevc_next);
392 goto f;
393 }
394 for (i = 0; i < spp; ++i)
395 decode_frac(next.v[i], cc, i);
396 #ifdef DEBUG
397 if (gs_debug_c('B')) {
398 dmprintf2(dev->memory, "[B]cc[0..%d]=%g", spp - 1,
399 cc.paint.values[0]);
400 for (i = 1; i < spp; ++i)
401 dmprintf1(dev->memory, ",%g", cc.paint.values[i]);
402 dmputs(dev->memory, "\n");
403 }
404 #endif
405 }
406 break;
407 }
408 mcode = remap_color(&cc, pcs, pdevc_next, pgs, dev,
409 gs_color_select_source);
410 if (mcode < 0)
411 goto fill;
412 f:
413 if (sizeof(pdevc_next->colors.binary.color[0]) <= sizeof(ulong))
414 if_debug7m('B', penum->memory,
415 "[B]0x%x,0x%x,0x%x,0x%x -> 0x%lx,0x%lx,0x%lx\n",
416 next.v[0], next.v[1], next.v[2], next.v[3],
417 (ulong)pdevc_next->colors.binary.color[0],
418 (ulong)pdevc_next->colors.binary.color[1],
419 (ulong)pdevc_next->type);
420 else
421 if_debug9m('B', penum->memory,
422 "[B]0x%x,0x%x,0x%x,0x%x -> 0x%08lx%08lx,0x%08lx%08lx,0x%lx\n",
423 next.v[0], next.v[1], next.v[2], next.v[3],
424 (ulong)(pdevc_next->colors.binary.color[0] >>
425 8 * (sizeof(pdevc_next->colors.binary.color[0]) - sizeof(ulong))),
426 (ulong)pdevc_next->colors.binary.color[0],
427 (ulong)(pdevc_next->colors.binary.color[1] >>
428 8 * (sizeof(pdevc_next->colors.binary.color[1]) - sizeof(ulong))),
429 (ulong)pdevc_next->colors.binary.color[1],
430 (ulong)pdevc_next->type);
431 /* NB: sizeof gx_color_index is 4 or 8 bytes! */
432
433 /* Even though the supplied colors don't match, */
434 /* the device colors might. */
435 if (!dev_color_eq(devc1, devc2)) {
436 /* Fill the region between xrun/irun and xl */
437 gx_device_color *ptemp;
438
439 fill:
440 if (posture != image_portrait) { /* Parallelogram */
441 code = (*dev_proc(dev, fill_parallelogram))
442 (dev, xrun, yrun,
443 xl - xrun, ytf - yrun, pdyx, pdyy,
444 pdevc, lop);
445 } else { /* Rectangle */
446 int xi = irun;
447 int wi = (irun = fixed2int_var_rounded(xl)) - xi;
448
449 if (wi < 0)
450 xi += wi, wi = -wi;
451 code = gx_fill_rectangle_device_rop(xi, yt,
452 wi, iht, pdevc, dev, lop);
453 }
454 if (code < 0)
455 goto err;
456 rsrc = psrc;
457 if ((code = mcode) < 0)
458 goto err;
459 ptemp = pdevc;
460 pdevc = pdevc_next;
461 pdevc_next = ptemp;
462 xrun = xl;
463 yrun = ytf;
464 }
465 run = next;
466 inc:
467 dda_next_assign(pnext.x, xl);
468 dda_next_assign(pnext.y, ytf);
469 }
470 /* Fill the final run. */
471 if (posture != image_portrait) {
472 code = (*dev_proc(dev, fill_parallelogram))
473 (dev, xrun, yrun, xl - xrun, ytf - yrun, pdyx, pdyy, pdevc, lop);
474 } else {
475 /* Same code as above near 'fill:' : */
476 int xi = irun;
477 int wi = (irun = fixed2int_var_rounded(xl)) - xi;
478
479 if (wi < 0)
480 xi += wi, wi = -wi;
481 code = gx_fill_rectangle_device_rop(xi, yt,
482 wi, iht, pdevc, dev, lop);
483 }
484 return (code < 0 ? code : 1);
485
486 /* Save position if error, in case we resume. */
487 err:
488 penum->used.x = (rsrc - spp - psrc_initial) / spp;
489 penum->used.y = 0;
490 return code;
491 }
492
493 static inline float
rescale_input_color(gs_range range,float input)494 rescale_input_color(gs_range range, float input)
495 {
496 return((input-range.rmin)/(range.rmax-range.rmin));
497 }
498
499 /* This one includes an extra adjustment for the CIE PS color space
500 non standard range */
501 static void
decode_row_cie16(const gx_image_enum * penum,const unsigned short * psrc,int spp,unsigned short * pdes,const unsigned short * bufend,gs_range range_array[])502 decode_row_cie16(const gx_image_enum *penum, const unsigned short *psrc,
503 int spp, unsigned short *pdes,
504 const unsigned short *bufend, gs_range range_array[])
505 {
506 unsigned short *curr_pos = pdes;
507 int k;
508 float temp;
509
510 while ( curr_pos < bufend ) {
511 for ( k = 0; k < spp; k ++ ) {
512 switch ( penum->map[k].decoding ) {
513 case sd_none:
514 *curr_pos = *psrc;
515 break;
516 case sd_lookup:
517 temp = penum->map[k].decode_lookup[(*psrc) >> 4]*65535.0;
518 temp = rescale_input_color(range_array[k], temp);
519 temp = temp*65535;
520 if (temp > 65535.0) temp = 65535.0;
521 if (temp < 0 ) temp = 0;
522 *curr_pos = (unsigned short) temp;
523 break;
524 case sd_compute:
525 temp = penum->map[k].decode_base +
526 (*psrc) * penum->map[k].decode_factor;
527 temp = rescale_input_color(range_array[k], temp);
528 temp = temp*65535;
529 if (temp > 65535) temp = 65535;
530 if (temp < 0 ) temp = 0;
531 *curr_pos = (unsigned short) temp;
532 default:
533 break;
534 }
535 curr_pos++;
536 psrc++;
537 }
538 }
539 }
540
541 static void
decode_row16(const gx_image_enum * penum,const unsigned short * psrc,int spp,unsigned short * pdes,const unsigned short * bufend)542 decode_row16(const gx_image_enum *penum, const unsigned short *psrc, int spp,
543 unsigned short *pdes,const unsigned short *bufend)
544 {
545 unsigned short *curr_pos = pdes;
546 int k;
547 float temp;
548
549 while ( curr_pos < bufend ) {
550 for ( k = 0; k < spp; k ++ ) {
551 switch ( penum->map[k].decoding ) {
552 case sd_none:
553 *curr_pos = *psrc;
554 break;
555 case sd_lookup:
556 temp = penum->map[k].decode_lookup[(*psrc) >> 4]*65535;
557 if (temp > 65535) temp = 65535;
558 if (temp < 0 ) temp = 0;
559 *curr_pos = (unsigned short) temp;
560 break;
561 case sd_compute:
562 temp = penum->map[k].decode_base +
563 (*psrc) * penum->map[k].decode_factor;
564 temp *= 65535;
565 if (temp > 65535) temp = 65535;
566 if (temp < 0 ) temp = 0;
567 *curr_pos = (unsigned short) temp;
568 default:
569 break;
570 }
571 curr_pos++;
572 psrc++;
573 }
574 }
575 }
576
577 /* Render an image with more than 8 bits per sample where we keep the data
578 in 16 bit form and hand directly to the CMM */
579 static int
image_render_icc16(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)580 image_render_icc16(gx_image_enum * penum, const byte * buffer, int data_x,
581 uint w, int h, gx_device * dev)
582 {
583 const gs_gstate *pgs = penum->pgs;
584 gs_logical_operation_t lop = penum->log_op;
585 gx_dda_fixed_point pnext;
586 image_posture posture = penum->posture;
587 fixed pdyx, pdyy; /* edge of parallelogram */
588 int vci, vdi;
589 int spp = penum->spp;
590 const unsigned short *psrc = (const unsigned short *)buffer + data_x * spp;
591 fixed xrun; /* x at start of run */
592 int irun; /* int xrun */
593 fixed yrun; /* y ditto */
594 const unsigned short *bufend = psrc + w;
595 unsigned short *run;
596 int code = 0;
597 gsicc_bufferdesc_t input_buff_desc;
598 gsicc_bufferdesc_t output_buff_desc;
599 unsigned short *psrc_cm, *psrc_cm_start, *psrc_decode, *psrc_cm_initial;
600 int k;
601 int spp_cm, num_pixels;
602 bool need_decode = penum->icc_setup.need_decode;
603 bool must_halftone = penum->icc_setup.must_halftone;
604 bool has_transfer = penum->icc_setup.has_transfer;
605 int num_des_comps;
606 cmm_dev_profile_t *dev_profile;
607 gx_cmapper_t data;
608 gx_cmapper_fn *mapper;
609 gx_color_value *conc = &data.conc[0];
610 int first = 1;
611
612 if (h == 0)
613 return 0;
614
615 if (penum->icc_link == NULL) {
616 return gs_rethrow(-1, "ICC Link not created during image render icc16");
617 }
618 gx_get_cmapper(&data, pgs, dev, has_transfer, must_halftone, gs_color_select_source);
619 mapper = data.set_color;
620 /* Needed for device N */
621 code = dev_proc(dev, get_profile)(dev, &dev_profile);
622 num_des_comps = gsicc_get_device_profile_comps(dev_profile);
623 /* If the link is the identity, then we don't need to do any color
624 conversions except for potentially a decode. */
625 if (penum->icc_link->is_identity && !need_decode) {
626 /* Fastest case. No decode or CM needed */
627 psrc_cm = (unsigned short *) psrc;
628 spp_cm = spp;
629 bufend = psrc_cm + w;
630 psrc_cm_start = NULL;
631 } else {
632 spp_cm = num_des_comps;
633 psrc_cm = (unsigned short*) gs_alloc_bytes(pgs->memory,
634 sizeof(unsigned short) * w * spp_cm/spp,
635 "image_render_icc16");
636 psrc_cm_start = psrc_cm;
637 bufend = psrc_cm + w * spp_cm/spp;
638 if (penum->icc_link->is_identity) {
639 /* decode only. no CM. This is slow but does not happen that often */
640 decode_row16(penum, psrc, spp, psrc_cm, bufend);
641 } else {
642 /* Set up the buffer descriptors. */
643 num_pixels = w/spp;
644 gsicc_init_buffer(&input_buff_desc, spp, 2,
645 false, false, false, 0, w * 2,
646 1, num_pixels);
647 gsicc_init_buffer(&output_buff_desc, spp_cm, 2,
648 false, false, false, 0, num_pixels * spp_cm * 2,
649 1, num_pixels);
650 /* For now, just blast it all through the link. If we had a significant reduction
651 we will want to repack the data first and then do this. That will be
652 an optimization shortly. For now just allocate a new output
653 buffer. We can reuse the old one if the number of channels in the output is
654 less than or equal to the new one. */
655 if (need_decode) {
656 /* Need decode and CM. This is slow but does not happen that often */
657 psrc_decode = (unsigned short*) gs_alloc_bytes(pgs->memory,
658 sizeof(unsigned short) * w * spp_cm/spp,
659 "image_render_icc16");
660 if (!penum->use_cie_range) {
661 decode_row16(penum, psrc, spp, psrc_decode,
662 (const unsigned short*) (psrc_decode+w));
663 } else {
664 /* Decode needs to include adjustment for CIE range */
665 decode_row_cie16(penum, psrc, spp, psrc_decode,
666 (const unsigned short*) (psrc_decode+w),
667 get_cie_range(penum->pcs));
668 }
669 (penum->icc_link->procs.map_buffer)(dev, penum->icc_link,
670 &input_buff_desc,
671 &output_buff_desc,
672 (void*) psrc_decode,
673 (void*) psrc_cm);
674 gs_free_object(pgs->memory, (byte *)psrc_decode, "image_render_color_icc");
675 } else {
676 /* CM only. No decode */
677 (penum->icc_link->procs.map_buffer)(dev, penum->icc_link,
678 &input_buff_desc,
679 &output_buff_desc,
680 (void*) psrc,
681 (void*) psrc_cm);
682 }
683 }
684 }
685 psrc_cm_initial = psrc_cm;
686
687 pnext = penum->dda.pixel0;
688 xrun = dda_current(pnext.x);
689 yrun = dda_current(pnext.y);
690 pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
691 pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
692 switch (posture) {
693 case image_portrait:
694 vci = penum->yci, vdi = penum->hci;
695 irun = fixed2int_var_rounded(xrun);
696 break;
697 case image_landscape:
698 default: /* we don't handle skew -- treat as landscape */
699 vci = penum->xci, vdi = penum->wci;
700 irun = fixed2int_var_rounded(yrun);
701 break;
702 }
703 if_debug5m('b', penum->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
704 penum->y, data_x, w, fixed2float(xrun), fixed2float(yrun));
705 while (psrc_cm < bufend) {
706 /* Find the length of the next run. It will either end when we hit
707 * the end of the source data, or when the pixel data differs. */
708 run = psrc_cm + spp_cm;
709 while (1)
710 {
711 dda_next(pnext.x);
712 dda_next(pnext.y);
713 if (run >= bufend)
714 break;
715 if (memcmp(run, psrc_cm, spp_cm * 2))
716 break;
717 if (posture == image_skewed) {
718 if (first) /* We always need to map the first pixel on a line */
719 break;
720 /* The color doesn't need remapping, but we can't handle a run */
721 goto skewed_but_same;
722 }
723 run += spp_cm;
724 }
725 first = 0;
726 /* So we have a run of pixels from psrc_cm to run that are all the same. */
727 /* This needs to be sped up */
728 for ( k = 0; k < spp_cm; k++ ) {
729 conc[k] = psrc_cm[k];
730 }
731 mapper(&data);
732 /* Fill the region between */
733 /* xrun/irun and pnext.x/pnext.y */
734 switch(posture)
735 {
736 default: /* skew */
737 skewed_but_same:
738 {
739 fixed xprev = dda_current(pnext.x);
740 fixed yprev = dda_current(pnext.y);
741 code = (*dev_proc(dev, fill_parallelogram))
742 (dev, xrun, yrun, xprev - xrun, yprev - yrun, pdyx, pdyy,
743 &data.devc, lop);
744 xrun = xprev;
745 yrun = yprev;
746 break;
747 }
748 case image_portrait:
749 {
750 int xi = irun;
751 int wi = (irun = fixed2int_var_rounded(dda_current(pnext.x))) - xi;
752
753 if (wi < 0)
754 xi += wi, wi = -wi;
755 if (wi > 0)
756 code = gx_fill_rectangle_device_rop(xi, vci, wi, vdi,
757 &data.devc, dev, lop);
758 break;
759 }
760 case image_landscape:
761 {
762 int yi = irun;
763 int hi = (irun = fixed2int_var_rounded(dda_current(pnext.y))) - yi;
764
765 if (hi < 0)
766 yi += hi, hi = -hi;
767 if (hi > 0)
768 code = gx_fill_rectangle_device_rop(vci, yi, vdi, hi,
769 &data.devc, dev, lop);
770 }
771 }
772 if (code < 0)
773 goto err;
774 psrc_cm = run;
775 }
776 /* Free cm buffer, if it was used */
777 if (psrc_cm_start != NULL) {
778 gs_free_object(pgs->memory, (byte *)psrc_cm_start, "image_render_icc16");
779 }
780 return (code < 0 ? code : 1);
781
782 /* Save position if error, in case we resume. */
783 err:
784 gs_free_object(pgs->memory, (byte *)psrc_cm_start, "image_render_icc16");
785 penum->used.x = (psrc_cm - psrc_cm_initial) / spp_cm;
786 penum->used.y = 0;
787 return code;
788 }
789