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 #include "gxdownscale.h"
18 #include "gserrors.h"
19 #include "string_.h"
20 #include "gdevprn.h"
21 #include "assert_.h"
22
23 #ifdef WITH_CAL
24 #include "cal_ets.h"
25 #else
26 #include "ets.h"
27 #endif
28
29 /* Nasty inline declaration, as gxht_thresh.h requires penum */
30 void gx_ht_threshold_row_bit_sub(byte *contone, byte *threshold_strip,
31 int contone_stride, byte *halftone,
32 int dithered_stride, int width, int num_rows,
33 int offset_bits);
34
35 enum
36 {
37 MAX_ETS_PLANES = 8
38 };
39
40 /* Error diffusion data is stored in errors block.
41 * We have 1 empty entry at each end to avoid overflow. When
42 * moving left to right we read from entries 2->width+1 (inclusive), and
43 * write to 1->width. When moving right to left we read from width->1 and
44 * write to width+1->2.
45 *
46 * Minimum feature size data is stored in the mfs_data block.
47 * We have 1 extra entry at the end to avoid overflow. When moving left to
48 * right we read from entries 1->width (inclusive), and write to 0->width-1.
49 * When moving right to left we read from width-1->0 and write to width->1.
50 */
51
52 enum {
53 mfs_clear = 0,
54 mfs_force_off = 1,
55 mfs_above_is_0 = 2,
56 mfs_above_left_is_0 = 4,
57 };
58
59 /* Mono downscale/error diffusion/min feature size code */
60
61 /* Subsidiary function to pack the data from 8 bits to 1 */
pack_8to1(byte * outp,byte * inp,int w)62 static void pack_8to1(byte *outp, byte *inp, int w)
63 {
64 int mask = 128;
65 int value = 0;
66 for (; w > 0; w--)
67 {
68 if (*inp++)
69 value |= mask;
70 mask >>= 1;
71 if (mask == 0) {
72 mask = 128;
73 *outp++= value;
74 value = 0;
75 }
76 }
77 if (mask != 128) {
78 *outp++ = value;
79 }
80 }
81
down_core(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)82 static void down_core(gx_downscaler_t *ds,
83 byte *out_buffer,
84 byte *in_buffer,
85 int row,
86 int plane,
87 int span)
88 {
89 int x, xx, y, value;
90 int e_downleft, e_down, e_forward = 0;
91 int pad_white;
92 byte *inp, *outp;
93 int width = ds->width;
94 int awidth = ds->awidth;
95 int factor = ds->factor;
96 int *errors = ds->errors + (awidth+3)*plane;
97 const int threshold = factor*factor*128;
98 const int max_value = factor*factor*255;
99
100 pad_white = (awidth - width) * factor;
101 if (pad_white < 0)
102 pad_white = 0;
103
104 if (pad_white)
105 {
106 inp = in_buffer + width*factor;
107 for (y = factor; y > 0; y--)
108 {
109 memset(inp, 0xFF, pad_white);
110 inp += span;
111 }
112 }
113
114 inp = in_buffer;
115 if ((row & 1) == 0)
116 {
117 /* Left to Right pass (no min feature size) */
118 const int back = span * factor - 1;
119 errors += 2;
120 outp = inp;
121 for (x = awidth; x > 0; x--)
122 {
123 value = e_forward + *errors;
124 for (xx = factor; xx > 0; xx--)
125 {
126 for (y = factor; y > 0; y--)
127 {
128 value += *inp;
129 inp += span;
130 }
131 inp -= back;
132 }
133 if (value >= threshold)
134 {
135 *outp++ = 1;
136 value -= max_value;
137 }
138 else
139 {
140 *outp++ = 0;
141 }
142 e_forward = value * 7/16;
143 e_downleft = value * 3/16;
144 e_down = value * 5/16;
145 value -= e_forward + e_downleft + e_down;
146 errors[-2] += e_downleft;
147 errors[-1] += e_down;
148 *errors++ = value;
149 }
150 outp -= awidth;
151 }
152 else
153 {
154 /* Right to Left pass (no min feature size) */
155 const int back = span * factor + 1;
156 errors += awidth;
157 inp += awidth*factor-1;
158 outp = inp;
159 for (x = awidth; x > 0; x--)
160 {
161 value = e_forward + *errors;
162 for (xx = factor; xx > 0; xx--)
163 {
164 for (y = factor; y > 0; y--)
165 {
166 value += *inp;
167 inp += span;
168 }
169 inp -= back;
170 }
171 if (value >= threshold)
172 {
173 *outp-- = 1;
174 value -= max_value;
175 }
176 else
177 {
178 *outp-- = 0;
179 }
180 e_forward = value * 7/16;
181 e_downleft = value * 3/16;
182 e_down = value * 5/16;
183 value -= e_forward + e_downleft + e_down;
184 errors[2] += e_downleft;
185 errors[1] += e_down;
186 *errors-- = value;
187 }
188 outp++;
189 }
190 pack_8to1(out_buffer, outp, awidth);
191 }
192
down_core_ets_1(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)193 static void down_core_ets_1(gx_downscaler_t *ds,
194 byte *out_buffer,
195 byte *in_buffer,
196 int row,
197 int plane,
198 int span)
199 {
200 unsigned char *dest[MAX_ETS_PLANES];
201 ETS_SrcPixel *src[MAX_ETS_PLANES];
202 int pad_white, y;
203 int factor = ds->factor;
204
205 pad_white = (ds->awidth - ds->width) * factor * 4;
206 if (pad_white < 0)
207 pad_white = 0;
208
209 if (pad_white)
210 {
211 unsigned char *inp = in_buffer + ds->width * factor * 4;
212 for (y = factor; y > 0; y--)
213 {
214 memset(inp, 0xFF, pad_white);
215 inp += span;
216 }
217 }
218
219 if (ds->ets_downscale)
220 ds->ets_downscale(ds, in_buffer, in_buffer, row, plane, span);
221
222 src[0] = in_buffer;
223 dest[0] = in_buffer;
224 ets_line((ETS_Ctx *)ds->ets_config, dest, (const ETS_SrcPixel * const *)src);
225
226 pack_8to1(out_buffer, in_buffer, ds->awidth);
227 }
228
down_core_1(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)229 static void down_core_1(gx_downscaler_t *ds,
230 byte *out_buffer,
231 byte *in_buffer,
232 int row,
233 int plane,
234 int span)
235 {
236 int x, value;
237 int e_downleft, e_down, e_forward = 0;
238 int pad_white;
239 byte *inp, *outp;
240 int width = ds->width;
241 int awidth = ds->awidth;
242 int *errors = ds->errors + (awidth+3)*plane;
243 const int threshold = 128;
244 const int max_value = 255;
245
246 pad_white = (awidth - width);
247 if (pad_white < 0)
248 pad_white = 0;
249
250 if (pad_white)
251 {
252 memset(in_buffer + width, 0xFF, pad_white);
253 }
254
255 inp = in_buffer;
256 if ((row & 1) == 0)
257 {
258 /* Left to Right pass (no min feature size) */
259 errors += 2;
260 outp = inp;
261 for (x = awidth; x > 0; x--)
262 {
263 value = e_forward + *errors + *inp++;
264 if (value >= threshold)
265 {
266 *outp++ = 1;
267 value -= max_value;
268 }
269 else
270 {
271 *outp++ = 0;
272 }
273 e_forward = value * 7/16;
274 e_downleft = value * 3/16;
275 e_down = value * 5/16;
276 value -= e_forward + e_downleft + e_down;
277 errors[-2] += e_downleft;
278 errors[-1] += e_down;
279 *errors++ = value;
280 }
281 outp -= awidth;
282 }
283 else
284 {
285 /* Right to Left pass (no min feature size) */
286 errors += awidth;
287 inp += awidth-1;
288 outp = inp;
289 for (x = awidth; x > 0; x--)
290 {
291 value = e_forward + *errors + *inp--;
292 if (value >= threshold)
293 {
294 *outp-- = 1;
295 value -= max_value;
296 }
297 else
298 {
299 *outp-- = 0;
300 }
301 e_forward = value * 7/16;
302 e_downleft = value * 3/16;
303 e_down = value * 5/16;
304 value -= e_forward + e_downleft + e_down;
305 errors[2] += e_downleft;
306 errors[1] += e_down;
307 *errors-- = value;
308 }
309 outp++;
310 }
311 pack_8to1(out_buffer, outp, awidth);
312 }
313
down_core_2(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)314 static void down_core_2(gx_downscaler_t *ds,
315 byte *out_buffer,
316 byte *in_buffer,
317 int row,
318 int plane,
319 int span)
320 {
321 int x, value;
322 int e_downleft, e_down, e_forward = 0;
323 int pad_white;
324 byte *inp, *outp;
325 int width = ds->width;
326 int awidth = ds->awidth;
327 int *errors = ds->errors + (awidth+3)*plane;
328 const int threshold = 2*2*128;
329 const int max_value = 2*2*255;
330
331 pad_white = (awidth - width) * 2;
332 if (pad_white < 0)
333 pad_white = 0;
334
335 if (pad_white)
336 {
337 inp = in_buffer + width*2;
338 for (x = 2; x > 0; x--)
339 {
340 memset(inp, 0xFF, pad_white);
341 inp += span;
342 }
343 }
344
345 inp = in_buffer;
346 if ((row & 1) == 0)
347 {
348 /* Left to Right pass (no min feature size) */
349 errors += 2;
350 outp = inp;
351 for (x = awidth; x > 0; x--)
352 {
353 value = e_forward + *errors + inp[0] + inp[1] + inp[span] + inp[span+1];
354 inp += 2;
355 if (value >= threshold)
356 {
357 *outp++ = 1;
358 value -= max_value;
359 }
360 else
361 {
362 *outp++ = 0;
363 }
364 e_forward = value * 7/16;
365 e_downleft = value * 3/16;
366 e_down = value * 5/16;
367 value -= e_forward + e_downleft + e_down;
368 errors[-2] += e_downleft;
369 errors[-1] += e_down;
370 *errors++ = value;
371 }
372 outp -= awidth;
373 }
374 else
375 {
376 /* Right to Left pass (no min feature size) */
377 errors += awidth;
378 inp += (awidth-1)*2;
379 outp = inp;
380 for (x = awidth; x > 0; x--)
381 {
382 value = e_forward + *errors + inp[0] + inp[1] + inp[span] + inp[span+1];
383 inp -= 2;
384 if (value >= threshold)
385 {
386 *outp-- = 1;
387 value -= max_value;
388 }
389 else
390 {
391 *outp-- = 0;
392 }
393 e_forward = value * 7/16;
394 e_downleft = value * 3/16;
395 e_down = value * 5/16;
396 value -= e_forward + e_downleft + e_down;
397 errors[2] += e_downleft;
398 errors[1] += e_down;
399 *errors-- = value;
400 }
401 outp++;
402 }
403 pack_8to1(out_buffer, outp, awidth);
404 }
405
down_core_3(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)406 static void down_core_3(gx_downscaler_t *ds,
407 byte *out_buffer,
408 byte *in_buffer,
409 int row,
410 int plane,
411 int span)
412 {
413 int x, value;
414 int e_downleft, e_down, e_forward = 0;
415 int pad_white;
416 byte *inp, *outp;
417 int width = ds->width;
418 int awidth = ds->awidth;
419 int *errors = ds->errors + (awidth+3)*plane;
420 const int threshold = 3*3*128;
421 const int max_value = 3*3*255;
422
423 pad_white = (awidth - width) * 3;
424 if (pad_white < 0)
425 pad_white = 0;
426
427 if (pad_white)
428 {
429 inp = in_buffer + width*3;
430 for (x = 3; x > 0; x--)
431 {
432 memset(inp, 0xFF, pad_white);
433 inp += span;
434 }
435 }
436
437 inp = in_buffer;
438 if ((row & 1) == 0)
439 {
440 /* Left to Right pass (no min feature size) */
441 errors += 2;
442 outp = inp;
443 for (x = awidth; x > 0; x--)
444 {
445 value = e_forward + *errors +
446 inp[ 0] + inp[ 1] + inp[ 2] +
447 inp[span ] + inp[span +1] + inp[span +2] +
448 inp[span*2] + inp[span*2+1] + inp[span*2+2];
449 inp += 3;
450 if (value >= threshold)
451 {
452 *outp++ = 1;
453 value -= max_value;
454 }
455 else
456 {
457 *outp++ = 0;
458 }
459 e_forward = value * 7/16;
460 e_downleft = value * 3/16;
461 e_down = value * 5/16;
462 value -= e_forward + e_downleft + e_down;
463 errors[-2] += e_downleft;
464 errors[-1] += e_down;
465 *errors++ = value;
466 }
467 outp -= awidth;
468 }
469 else
470 {
471 /* Right to Left pass (no min feature size) */
472 errors += awidth;
473 inp += (awidth-1)*3;
474 outp = inp;
475 for (x = awidth; x > 0; x--)
476 {
477 value = e_forward + *errors +
478 inp[ 0] + inp[ 1] + inp[ 2] +
479 inp[span ] + inp[span +1] + inp[span +2] +
480 inp[span*2] + inp[span*2+1] + inp[span*2+2];
481 inp -= 3;
482 if (value >= threshold)
483 {
484 *outp-- = 1;
485 value -= max_value;
486 }
487 else
488 {
489 *outp-- = 0;
490 }
491 e_forward = value * 7/16;
492 e_downleft = value * 3/16;
493 e_down = value * 5/16;
494 value -= e_forward + e_downleft + e_down;
495 errors[2] += e_downleft;
496 errors[1] += e_down;
497 *errors-- = value;
498 }
499 outp++;
500 }
501 pack_8to1(out_buffer, outp, awidth);
502 }
503
down_core_4(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)504 static void down_core_4(gx_downscaler_t *ds,
505 byte *out_buffer,
506 byte *in_buffer,
507 int row,
508 int plane,
509 int span)
510 {
511 int x, value;
512 int e_downleft, e_down, e_forward = 0;
513 int pad_white;
514 byte *inp, *outp;
515 int width = ds->width;
516 int awidth = ds->awidth;
517 int *errors = ds->errors + (awidth+3)*plane;
518 const int threshold = 4*4*128;
519 const int max_value = 4*4*255;
520
521 pad_white = (awidth - width) * 4;
522 if (pad_white < 0)
523 pad_white = 0;
524
525 if (pad_white)
526 {
527 inp = in_buffer + width*4;
528 for (x = 4; x > 0; x--)
529 {
530 memset(inp, 0xFF, pad_white);
531 inp += span;
532 }
533 }
534
535 inp = in_buffer;
536 if ((row & 1) == 0)
537 {
538 /* Left to Right pass (no min feature size) */
539 errors += 2;
540 outp = inp;
541 for (x = awidth; x > 0; x--)
542 {
543 value = e_forward + *errors +
544 inp[ 0] + inp[ 1] + inp[ 2] + inp[3 ] +
545 inp[span ] + inp[span +1] + inp[span +2] + inp[span +3] +
546 inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
547 inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3];
548 inp += 4;
549 if (value >= threshold)
550 {
551 *outp++ = 1;
552 value -= max_value;
553 }
554 else
555 {
556 *outp++ = 0;
557 }
558 e_forward = value * 7/16;
559 e_downleft = value * 3/16;
560 e_down = value * 5/16;
561 value -= e_forward + e_downleft + e_down;
562 errors[-2] += e_downleft;
563 errors[-1] += e_down;
564 *errors++ = value;
565 }
566 outp -= awidth;
567 }
568 else
569 {
570 /* Right to Left pass (no min feature size) */
571 errors += awidth;
572 inp += (awidth-1)*4;
573 outp = inp;
574 for (x = awidth; x > 0; x--)
575 {
576 value = e_forward + *errors +
577 inp[ 0] + inp[ 1] + inp[ 2] + inp[3 ] +
578 inp[span ] + inp[span +1] + inp[span +2] + inp[span +3] +
579 inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
580 inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3];
581 inp -= 4;
582 if (value >= threshold)
583 {
584 *outp-- = 1;
585 value -= max_value;
586 }
587 else
588 {
589 *outp-- = 0;
590 }
591 e_forward = value * 7/16;
592 e_downleft = value * 3/16;
593 e_down = value * 5/16;
594 value -= e_forward + e_downleft + e_down;
595 errors[2] += e_downleft;
596 errors[1] += e_down;
597 *errors-- = value;
598 }
599 outp++;
600 }
601 pack_8to1(out_buffer, outp, awidth);
602 }
603
down_core_mfs(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)604 static void down_core_mfs(gx_downscaler_t *ds,
605 byte *out_buffer,
606 byte *in_buffer,
607 int row,
608 int plane,
609 int span)
610 {
611 int x, xx, y, value;
612 int e_downleft, e_down, e_forward = 0;
613 int pad_white;
614 byte *inp, *outp;
615 int width = ds->width;
616 int awidth = ds->awidth;
617 int factor = ds->factor;
618 int *errors = ds->errors + (awidth+3)*plane;
619 byte *mfs_data = ds->mfs_data + (awidth+1)*plane;
620 const int threshold = factor*factor*128;
621 const int max_value = factor*factor*255;
622
623 pad_white = (awidth - width) * factor;
624 if (pad_white < 0)
625 pad_white = 0;
626
627 if (pad_white)
628 {
629 inp = in_buffer + width*factor;
630 for (y = factor; y > 0; y--)
631 {
632 memset(inp, 0xFF, pad_white);
633 inp += span;
634 }
635 }
636
637 inp = in_buffer;
638 if ((row & 1) == 0)
639 {
640 /* Left to Right pass (with min feature size = 2) */
641 const int back = span * factor -1;
642 byte mfs, force_forward = 0;
643 errors += 2;
644 outp = inp;
645 *mfs_data++ = mfs_clear;
646 for (x = awidth; x > 0; x--)
647 {
648 value = e_forward + *errors;
649 for (xx = factor; xx > 0; xx--)
650 {
651 for (y = factor; y > 0; y--)
652 {
653 value += *inp;
654 inp += span;
655 }
656 inp -= back;
657 }
658 mfs = *mfs_data;
659 *mfs_data++ = mfs_clear;
660 if ((mfs & mfs_force_off) || force_forward)
661 {
662 /* We are being forced to be 0 */
663 *outp++ = 0;
664 force_forward = 0;
665 }
666 else if (value < threshold)
667 {
668 /* We want to be 0 anyway */
669 *outp++ = 0;
670 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
671 != (mfs_above_is_0 | mfs_above_left_is_0))
672 {
673 /* We aren't in a group anyway, so must force other
674 * pixels. */
675 mfs_data[-2] |= mfs_force_off;
676 mfs_data[-1] |= mfs_force_off;
677 force_forward = 1;
678 }
679 else
680 {
681 /* No forcing, but we need to tell other pixels that
682 * we were 0. */
683 mfs_data[-2] |= mfs_above_is_0;
684 mfs_data[-1] |= mfs_above_left_is_0;
685 }
686 }
687 else
688 {
689 *outp++ = 1;
690 value -= max_value;
691 }
692 e_forward = value * 7/16;
693 e_downleft = value * 3/16;
694 e_down = value * 5/16;
695 value -= e_forward + e_downleft + e_down;
696 errors[-2] += e_downleft;
697 errors[-1] += e_down;
698 *errors++ = value;
699 }
700 outp -= awidth;
701 }
702 else
703 {
704 /* Right to Left pass (with min feature size = 2) */
705 const int back = span * factor + 1;
706 byte mfs, force_forward = 0;
707 errors += awidth;
708 mfs_data += awidth;
709 inp += awidth*factor-1;
710 outp = inp;
711 *mfs_data-- = mfs_clear;
712 for (x = awidth; x > 0; x--)
713 {
714 value = e_forward + *errors;
715 for (xx = factor; xx > 0; xx--)
716 {
717 for (y = factor; y > 0; y--)
718 {
719 value += *inp;
720 inp += span;
721 }
722 inp -= back;
723 }
724 mfs = *mfs_data;
725 *mfs_data-- = mfs_clear;
726 if ((mfs & mfs_force_off) || force_forward)
727 {
728 /* We are being forced to be 0 */
729 *outp-- = 0;
730 force_forward = 0;
731 }
732 else if (value < threshold)
733 {
734 *outp-- = 0;
735 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
736 != (mfs_above_is_0 | mfs_above_left_is_0))
737 {
738 /* We aren't in a group anyway, so must force other
739 * pixels. */
740 mfs_data[1] |= mfs_force_off;
741 mfs_data[2] |= mfs_force_off;
742 force_forward = 1;
743 }
744 else
745 {
746 /* No forcing, but we need to tell other pixels that
747 * we were 0. */
748 mfs_data[1] |= mfs_above_is_0;
749 mfs_data[2] |= mfs_above_left_is_0;
750 }
751 }
752 else
753 {
754 *outp-- = 1;
755 value -= max_value;
756 }
757 e_forward = value * 7/16;
758 e_downleft = value * 3/16;
759 e_down = value * 5/16;
760 value -= e_forward + e_downleft + e_down;
761 errors[2] += e_downleft;
762 errors[1] += e_down;
763 *errors-- = value;
764 }
765 outp++;
766 }
767 pack_8to1(out_buffer, outp, awidth);
768 }
769
770 /* CMYK 32 -> 4bit core */
down_core4(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)771 static void down_core4(gx_downscaler_t *ds,
772 byte *out_buffer,
773 byte *in_buffer,
774 int row,
775 int plane /* unused */,
776 int span)
777 {
778 int x, xx, y, value, comp;
779 int e_downleft, e_down, e_forward = 0;
780 int pad_white;
781 byte *inp, *outp;
782 int width = ds->width;
783 int awidth = ds->awidth;
784 int factor = ds->factor;
785 int *errors = ds->errors;
786 const int threshold = factor*factor*128;
787 const int max_value = factor*factor*255;
788
789 pad_white = (awidth - width) * factor * 4;
790 if (pad_white < 0)
791 pad_white = 0;
792
793 if (pad_white)
794 {
795 inp = in_buffer + width*factor * 4;
796 for (y = factor; y > 0; y--)
797 {
798 memset(inp, 0xFF, pad_white);
799 inp += span;
800 }
801 }
802
803 if ((row & 1) == 0)
804 {
805 /* Left to Right pass (no min feature size) */
806 const int back = span * factor - 4;
807 for (comp = 0; comp < 4; comp++)
808 {
809 errors = ds->errors + (awidth+3)*comp + 2;
810 inp = in_buffer + comp;
811 outp = inp;
812 for (x = awidth; x > 0; x--)
813 {
814 value = e_forward + *errors;
815 for (xx = factor; xx > 0; xx--)
816 {
817 for (y = factor; y > 0; y--)
818 {
819 value += *inp;
820 inp += span;
821 }
822 inp -= back;
823 }
824 if (value >= threshold)
825 {
826 *outp = 1; outp += 4;
827 value -= max_value;
828 }
829 else
830 {
831 *outp = 0; outp += 4;
832 }
833 e_forward = value * 7/16;
834 e_downleft = value * 3/16;
835 e_down = value * 5/16;
836 value -= e_forward + e_downleft + e_down;
837 errors[-2] += e_downleft;
838 errors[-1] += e_down;
839 *errors++ = value;
840 }
841 }
842 outp = in_buffer;
843 }
844 else
845 {
846 /* Right to Left pass (no min feature size) */
847 const int back = span * factor + 4;
848 for (comp = 0; comp < 4; comp++)
849 {
850 errors = ds->errors + (awidth+3)*comp + awidth;
851 inp = in_buffer + awidth*factor*4 - 4 + comp;
852 outp = inp;
853 for (x = awidth; x > 0; x--)
854 {
855 value = e_forward + *errors;
856 for (xx = factor; xx > 0; xx--)
857 {
858 for (y = factor; y > 0; y--)
859 {
860 value += *inp;
861 inp += span;
862 }
863 inp -= back;
864 }
865 if (value >= threshold)
866 {
867 *outp = 1; outp -= 4;
868 value -= max_value;
869 }
870 else
871 {
872 *outp = 0; outp -= 4;
873 }
874 e_forward = value * 7/16;
875 e_downleft = value * 3/16;
876 e_down = value * 5/16;
877 value -= e_forward + e_downleft + e_down;
878 errors[2] += e_downleft;
879 errors[1] += e_down;
880 *errors-- = value;
881 }
882 }
883 outp = in_buffer + awidth*factor*4 - (awidth*4);
884 }
885 pack_8to1(out_buffer, outp, awidth*4);
886 }
887
down_core4_ht(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)888 static void down_core4_ht(gx_downscaler_t *ds,
889 byte *out_buffer, /* Guaranteed aligned */
890 byte *in_buffer, /* Not guaranteed aligned */
891 int row,
892 int plane /* unused */,
893 int span)
894 {
895 int pad_white, y;
896 int factor = ds->factor;
897 int i;
898 int nc = ds->early_cm ? ds->post_cm_num_comps : ds->num_comps;
899 byte *downscaled_data = ds->inbuf;
900
901 pad_white = (ds->awidth - ds->width) * factor * 4;
902 if (pad_white < 0)
903 pad_white = 0;
904
905 if (pad_white)
906 {
907 unsigned char *inp = in_buffer + ds->width * factor * 4;
908 for (y = factor; y > 0; y--)
909 {
910 memset(inp, 0xFF, pad_white);
911 inp += span;
912 }
913 }
914
915 /* Color conversion has already happened. Do any downscale required. */
916 if (ds->ets_downscale)
917 ds->ets_downscale(ds, downscaled_data, in_buffer, row, plane, span);
918 else if ((31 & (intptr_t)in_buffer) == 0)
919 downscaled_data = in_buffer; /* Already aligned! Yay! */
920 else
921 memcpy(downscaled_data, in_buffer, nc*ds->width); /* Copy to align */
922
923 /* Do the halftone */
924 for (i = 0; i < nc; i++)
925 {
926 /* Make the expanded threshold row */
927 byte *d = ds->htrow + i;
928 int len = ds->width;
929 const byte *srow = ds->ht[i].data + ds->ht[i].stride * ((row + ds->ht[i].y_phase) % ds->ht[i].h);
930 {
931 int o = ds->ht[i].x_phase;
932 int run = ds->ht[i].w - o;
933 const byte *s = &srow[o];
934 if (run > len)
935 run = len;
936 len -= run;
937 do {
938 *d = *s++;
939 d += nc;
940 } while (--run);
941 }
942 while (len)
943 {
944 const byte *s = srow;
945 int run = ds->ht[i].w;
946 if (run > len)
947 run = len;
948 len -= run;
949 do {
950 *d = *s++;
951 d += nc;
952 }
953 while (--run);
954 }
955 }
956
957 /* Do the halftone */
958 gx_ht_threshold_row_bit_sub(downscaled_data, ds->htrow, 0,
959 out_buffer, 0,
960 ds->width * nc, 1, 0);
961 }
962
down_core4_ets(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)963 static void down_core4_ets(gx_downscaler_t *ds,
964 byte *out_buffer,
965 byte *in_buffer,
966 int row,
967 int plane /* unused */,
968 int span)
969 {
970 unsigned char *dest[MAX_ETS_PLANES];
971 ETS_SrcPixel *src[MAX_ETS_PLANES];
972 int pad_white, y;
973 int factor = ds->factor;
974
975 pad_white = (ds->awidth - ds->width) * factor * 4;
976 if (pad_white < 0)
977 pad_white = 0;
978
979 if (pad_white)
980 {
981 unsigned char *inp = in_buffer + ds->width * factor * 4;
982 for (y = factor; y > 0; y--)
983 {
984 memset(inp, 0xFF, pad_white);
985 inp += span;
986 }
987 }
988
989 if (ds->ets_downscale)
990 ds->ets_downscale(ds, in_buffer, in_buffer, row, plane, span);
991
992 src[0] = in_buffer+3;
993 dest[0] = in_buffer+3;
994 src[1] = in_buffer+1;
995 dest[1] = in_buffer+1;
996 src[2] = in_buffer+0;
997 dest[2] = in_buffer+0;
998 src[3] = in_buffer+2;
999 dest[3] = in_buffer+2;
1000 ets_line((ETS_Ctx *)ds->ets_config, dest, (const ETS_SrcPixel * const *)src);
1001
1002 pack_8to1(out_buffer, in_buffer, ds->awidth * 4);
1003 }
1004
down_core4_mfs(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)1005 static void down_core4_mfs(gx_downscaler_t *ds,
1006 byte *out_buffer,
1007 byte *in_buffer,
1008 int row,
1009 int plane /* unused */,
1010 int span)
1011 {
1012 int x, xx, y, value, comp;
1013 int e_downleft, e_down, e_forward = 0;
1014 int pad_white;
1015 byte *inp, *outp;
1016 int width = ds->width;
1017 int awidth = ds->awidth;
1018 int factor = ds->factor;
1019 int *errors;
1020 const int threshold = factor*factor*128;
1021 const int max_value = factor*factor*255;
1022 byte *mfs_data;
1023
1024 pad_white = (awidth - width) * factor * 4;
1025 if (pad_white < 0)
1026 pad_white = 0;
1027
1028 if (pad_white)
1029 {
1030 inp = in_buffer + width*factor*4;
1031 for (y = factor*4; y > 0; y--)
1032 {
1033 memset(inp, 0xFF, pad_white);
1034 inp += span;
1035 }
1036 }
1037
1038 if ((row & 1) == 0)
1039 {
1040 /* Left to Right pass (with min feature size = 2) */
1041 const int back = span * factor - 4;
1042 for (comp = 0; comp < 4; comp++)
1043 {
1044 byte mfs, force_forward = 0;
1045 errors = ds->errors + (awidth+3)*comp + 2;
1046 inp = in_buffer + comp;
1047 outp = inp;
1048 mfs_data = ds->mfs_data + (awidth+1)*comp;
1049 *mfs_data++ = mfs_clear;
1050 for (x = awidth; x > 0; x--)
1051 {
1052 value = e_forward + *errors;
1053 for (xx = factor; xx > 0; xx--)
1054 {
1055 for (y = factor; y > 0; y--)
1056 {
1057 value += *inp;
1058 inp += span;
1059 }
1060 inp -= back;
1061 }
1062 mfs = *mfs_data;
1063 *mfs_data++ = mfs_clear;
1064 if ((mfs & mfs_force_off) || force_forward)
1065 {
1066 /* We are being forced to be 0 */
1067 *outp = 1; outp += 4;
1068 value -= max_value;
1069 force_forward = 0;
1070 }
1071 else if (value >= threshold)
1072 {
1073 /* We want to be 1 anyway */
1074 *outp = 1; outp += 4;
1075 value -= max_value;
1076 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
1077 != (mfs_above_is_0 | mfs_above_left_is_0))
1078 {
1079 /* We aren't in a group anyway, so must force other
1080 * pixels. */
1081 mfs_data[-2] |= mfs_force_off;
1082 mfs_data[-1] |= mfs_force_off;
1083 force_forward = 1;
1084 }
1085 else
1086 {
1087 /* No forcing, but we need to tell other pixels that
1088 * we were 1. */
1089 mfs_data[-2] |= mfs_above_is_0;
1090 mfs_data[-1] |= mfs_above_left_is_0;
1091 }
1092 }
1093 else
1094 {
1095 *outp = 0; outp += 4;
1096 }
1097 e_forward = value * 7/16;
1098 e_downleft = value * 3/16;
1099 e_down = value * 5/16;
1100 value -= e_forward + e_downleft + e_down;
1101 errors[-2] += e_downleft;
1102 errors[-1] += e_down;
1103 *errors++ = value;
1104 }
1105 }
1106 outp = in_buffer;
1107 }
1108 else
1109 {
1110 /* Right to Left pass (with min feature size = 2) */
1111 const int back = span * factor + 4;
1112 for (comp = 0; comp < 4; comp++)
1113 {
1114 byte mfs, force_forward = 0;
1115 errors = ds->errors + (awidth+3)*comp + awidth;
1116 inp = in_buffer + awidth*factor*4 - 4 + comp;
1117 outp = inp;
1118 mfs_data = ds->mfs_data + (awidth+1)*comp + awidth;
1119 *mfs_data-- = mfs_clear;
1120 for (x = awidth; x > 0; x--)
1121 {
1122 value = e_forward + *errors;
1123 for (xx = factor; xx > 0; xx--)
1124 {
1125 for (y = factor; y > 0; y--)
1126 {
1127 value += *inp;
1128 inp += span;
1129 }
1130 inp -= back;
1131 }
1132 mfs = *mfs_data;
1133 *mfs_data-- = mfs_clear;
1134 if ((mfs & mfs_force_off) || force_forward)
1135 {
1136 /* We are being forced to be 0 */
1137 *outp = 1; outp -= 4;
1138 value -= max_value;
1139 force_forward = 0;
1140 }
1141 else if (value >= threshold)
1142 {
1143 *outp = 1; outp -= 4;
1144 value -= max_value;
1145 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
1146 != (mfs_above_is_0 | mfs_above_left_is_0))
1147 {
1148 /* We aren't in a group anyway, so must force other
1149 * pixels. */
1150 mfs_data[1] |= mfs_force_off;
1151 mfs_data[2] |= mfs_force_off;
1152 force_forward = 1;
1153 }
1154 else
1155 {
1156 /* No forcing, but we need to tell other pixels that
1157 * we were 1. */
1158 mfs_data[1] |= mfs_above_is_0;
1159 mfs_data[2] |= mfs_above_left_is_0;
1160 }
1161 }
1162 else
1163 {
1164 *outp = 0; outp -= 4;
1165 }
1166 e_forward = value * 7/16;
1167 e_downleft = value * 3/16;
1168 e_down = value * 5/16;
1169 value -= e_forward + e_downleft + e_down;
1170 errors[2] += e_downleft;
1171 errors[1] += e_down;
1172 *errors-- = value;
1173 }
1174 }
1175 outp = in_buffer + awidth*factor*4 - (awidth*4);
1176 }
1177 pack_8to1(out_buffer, outp, awidth*4);
1178 }
1179
1180 /* Grey (or planar) downscale code */
down_core16(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1181 static void down_core16(gx_downscaler_t *ds,
1182 byte *outp,
1183 byte *in_buffer,
1184 int row,
1185 int plane,
1186 int span)
1187 {
1188 int x, xx, y, value;
1189 int pad_white;
1190 byte *inp;
1191 int width = ds->width;
1192 int awidth = ds->awidth;
1193 int factor = ds->factor;
1194 int div = factor*factor;
1195
1196 pad_white = (awidth - width) * factor;
1197 if (pad_white < 0)
1198 pad_white = 0;
1199
1200 if (pad_white)
1201 {
1202 inp = in_buffer + width*2*factor;
1203 for (y = factor; y > 0; y--)
1204 {
1205 memset(inp, 0xFF, pad_white*2);
1206 inp += span;
1207 }
1208 }
1209
1210 inp = in_buffer;
1211 {
1212 /* Left to Right pass (no min feature size) */
1213 const int back = span * factor -2;
1214 for (x = awidth; x > 0; x--)
1215 {
1216 value = 0;
1217 for (xx = factor; xx > 0; xx--)
1218 {
1219 for (y = factor; y > 0; y--)
1220 {
1221 value += inp[0]<<8;
1222 value += inp[1];
1223 inp += span;
1224 }
1225 inp -= back;
1226 }
1227 value = (value + (div>>1))/div;
1228 outp[0] = value>>8;
1229 outp[1] = value;
1230 outp += 2;
1231 }
1232 }
1233 }
1234
down_core8(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1235 static void down_core8(gx_downscaler_t *ds,
1236 byte *outp,
1237 byte *in_buffer,
1238 int row,
1239 int plane,
1240 int span)
1241 {
1242 int x, xx, y, value;
1243 int pad_white;
1244 byte *inp;
1245 int width = ds->width;
1246 int awidth = ds->awidth;
1247 int factor = ds->factor;
1248 int div = factor*factor;
1249
1250 pad_white = (awidth - width) * factor;
1251 if (pad_white < 0)
1252 pad_white = 0;
1253
1254 if (pad_white)
1255 {
1256 inp = in_buffer + width*factor;
1257 for (y = factor; y > 0; y--)
1258 {
1259 memset(inp, 0xFF, pad_white);
1260 inp += span;
1261 }
1262 }
1263
1264 inp = in_buffer;
1265 {
1266 /* Left to Right pass (no min feature size) */
1267 const int back = span * factor -1;
1268 for (x = awidth; x > 0; x--)
1269 {
1270 value = 0;
1271 for (xx = factor; xx > 0; xx--)
1272 {
1273 for (y = factor; y > 0; y--)
1274 {
1275 value += *inp;
1276 inp += span;
1277 }
1278 inp -= back;
1279 }
1280 *outp++ = (value+(div>>1))/div;
1281 }
1282 }
1283 }
1284
down_core8_2(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1285 static void down_core8_2(gx_downscaler_t *ds,
1286 byte *outp,
1287 byte *in_buffer,
1288 int row,
1289 int plane,
1290 int span)
1291 {
1292 int x;
1293 int pad_white;
1294 byte *inp;
1295 int width = ds->width;
1296 int awidth = ds->awidth;
1297
1298 pad_white = (awidth - width) * 2;
1299 if (pad_white < 0)
1300 pad_white = 0;
1301
1302 if (pad_white)
1303 {
1304 inp = in_buffer + width*2;
1305 for (x = 2; x > 0; x--)
1306 {
1307 memset(inp, 0xFF, pad_white);
1308 inp += span;
1309 }
1310 }
1311
1312 inp = in_buffer;
1313
1314 /* Left to Right pass (no min feature size) */
1315 for (x = awidth; x > 0; x--)
1316 {
1317 *outp++ = (inp[0] + inp[1] + inp[span] + inp[span+1] + 2)>>2;
1318 inp += 2;
1319 }
1320 }
1321
down_core8_3(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1322 static void down_core8_3(gx_downscaler_t *ds,
1323 byte *outp,
1324 byte *in_buffer,
1325 int row,
1326 int plane,
1327 int span)
1328 {
1329 int x;
1330 int pad_white;
1331 byte *inp;
1332 int width = ds->width;
1333 int awidth = ds->awidth;
1334
1335 pad_white = (awidth - width) * 3;
1336 if (pad_white < 0)
1337 pad_white = 0;
1338
1339 if (pad_white)
1340 {
1341 inp = in_buffer + width*3;
1342 for (x = 3; x > 0; x--)
1343 {
1344 memset(inp, 0xFF, pad_white);
1345 inp += span;
1346 }
1347 }
1348
1349 inp = in_buffer;
1350
1351 /* Left to Right pass (no min feature size) */
1352 for (x = awidth; x > 0; x--)
1353 {
1354 *outp++ = (inp[0 ] + inp[ 1] + inp[ 2] +
1355 inp[span ] + inp[span +1] + inp[span +2] +
1356 inp[span*2] + inp[span*2+1] + inp[span*2+2] + 4)/9;
1357 inp += 3;
1358 }
1359 }
1360
down_core8_4(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1361 static void down_core8_4(gx_downscaler_t *ds,
1362 byte *outp,
1363 byte *in_buffer,
1364 int row,
1365 int plane,
1366 int span)
1367 {
1368 int x;
1369 int pad_white;
1370 byte *inp;
1371 int width = ds->width;
1372 int awidth = ds->awidth;
1373
1374 pad_white = (awidth - width) * 4;
1375 if (pad_white < 0)
1376 pad_white = 0;
1377
1378 if (pad_white)
1379 {
1380 inp = in_buffer + width*4;
1381 for (x = 4; x > 0; x--)
1382 {
1383 memset(inp, 0xFF, pad_white);
1384 inp += span;
1385 }
1386 }
1387
1388 inp = in_buffer;
1389
1390 /* Left to Right pass (no min feature size) */
1391 for (x = awidth; x > 0; x--)
1392 {
1393 *outp++ = (inp[0 ] + inp[ 1] + inp[ 2] + inp[ 3] +
1394 inp[span ] + inp[span +1] + inp[span +2] + inp[span +3] +
1395 inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
1396 inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3] +
1397 8)>>4;
1398 inp += 4;
1399 }
1400 }
1401
down_core8_3_2(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1402 static void down_core8_3_2(gx_downscaler_t *ds,
1403 byte *outp,
1404 byte *in_buffer,
1405 int row,
1406 int plane,
1407 int span)
1408 {
1409 int x;
1410 int pad_white;
1411 byte *inp;
1412 int width = ds->width;
1413 int awidth = ds->awidth;
1414 int dspan = ds->scaled_span;
1415
1416 pad_white = (awidth - width) * 3 / 2;
1417 if (pad_white < 0)
1418 pad_white = 0;
1419
1420 if (pad_white)
1421 {
1422 inp = in_buffer + width*3/2;
1423 for (x = 2; x > 0; x--)
1424 {
1425 memset(inp, 0xFF, pad_white);
1426 inp += span;
1427 }
1428 }
1429
1430 inp = in_buffer;
1431
1432 /* Left to Right pass (no min feature size) */
1433 for (x = awidth/2; x > 0; x--)
1434 {
1435 int a = inp[ 0];
1436 int b = inp[ 1];
1437 int c = inp[ 2];
1438 int d = inp[ span+0];
1439 int e = inp[ span+1];
1440 int f = inp[ span+2];
1441 int g = inp[2*span+0];
1442 int h = inp[2*span+1];
1443 int i = inp[2*span+2];
1444 outp[0 ] = (4*a+2*b+2*d+e+4)/9;
1445 outp[1 ] = (4*c+2*b+2*f+e+4)/9;
1446 outp[dspan+0] = (4*g+2*h+2*d+e+4)/9;
1447 outp[dspan+1] = (4*i+2*h+2*f+e+4)/9;
1448 outp += 2;
1449 inp += 3;
1450 }
1451 }
1452
down_core8_3_4(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1453 static void down_core8_3_4(gx_downscaler_t *ds,
1454 byte *outp,
1455 byte *in_buffer,
1456 int row,
1457 int plane,
1458 int span)
1459 {
1460 int x;
1461 int pad_white;
1462 byte *inp;
1463 int width = ds->width;
1464 int awidth = ds->awidth;
1465 int dspan = ds->scaled_span;
1466
1467 pad_white = (awidth - width) * 3 / 4;
1468 if (pad_white < 0)
1469 pad_white = 0;
1470
1471 if (pad_white)
1472 {
1473 inp = in_buffer + width*3/4;
1474 for (x = 4; x > 0; x--)
1475 {
1476 memset(inp, 0xFF, pad_white);
1477 inp += span;
1478 }
1479 }
1480
1481 inp = in_buffer;
1482
1483 /* Left to Right pass (no min feature size) */
1484 for (x = awidth/4; x > 0; x--)
1485 {
1486 int a = inp[ 0];
1487 int b = inp[ 1];
1488 int c = inp[ 2];
1489 int d = inp[ span+0];
1490 int e = inp[ span+1];
1491 int f = inp[ span+2];
1492 int g = inp[2*span+0];
1493 int h = inp[2*span+1];
1494 int i = inp[2*span+2];
1495 outp[ 0] = a;
1496 outp[ 1] = (a+2*b+1)/3;
1497 outp[ 2] = (c+2*b+1)/3;
1498 outp[ 3] = c;
1499 outp[ dspan+0] = (a+2*d+1)/3;
1500 outp[ dspan+1] = (a+2*b+2*d+4*e+3)/9;
1501 outp[ dspan+2] = (c+2*b+2*f+4*e+3)/9;
1502 outp[ dspan+3] = (c+2*f+1)/3;
1503 outp[2*dspan+0] = (g+2*d+1)/3;
1504 outp[2*dspan+1] = (g+2*h+2*d+4*e+3)/9;
1505 outp[2*dspan+2] = (i+2*h+2*f+4*e+3)/9;
1506 outp[2*dspan+3] = (i+2*f+1)/3;
1507 outp[3*dspan+0] = g;
1508 outp[3*dspan+1] = (g+2*h+1)/3;
1509 outp[3*dspan+2] = (i+2*h+1)/3;
1510 outp[3*dspan+3] = i;
1511 outp += 4;
1512 inp += 3;
1513 }
1514 }
1515
1516 /* RGB downscale (no error diffusion) code */
1517
down_core24(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1518 static void down_core24(gx_downscaler_t *ds,
1519 byte *outp,
1520 byte *in_buffer,
1521 int row,
1522 int plane,
1523 int span)
1524 {
1525 int x, xx, y, value;
1526 int pad_white;
1527 byte *inp;
1528 int width = ds->width;
1529 int awidth = ds->awidth;
1530 int factor = ds->factor;
1531 int div = factor*factor;
1532
1533 pad_white = (awidth - width) * factor * 3;
1534 if (pad_white < 0)
1535 pad_white = 0;
1536
1537 if (pad_white)
1538 {
1539 inp = in_buffer + width*factor*3;
1540 for (y = factor; y > 0; y--)
1541 {
1542 memset(inp, 0xFF, pad_white);
1543 inp += span;
1544 }
1545 }
1546
1547 inp = in_buffer;
1548 {
1549 /* Left to Right pass (no min feature size) */
1550 const int back = span * factor - 3;
1551 const int back2 = factor * 3 - 1;
1552 for (x = awidth; x > 0; x--)
1553 {
1554 /* R */
1555 value = 0;
1556 for (xx = factor; xx > 0; xx--)
1557 {
1558 for (y = factor; y > 0; y--)
1559 {
1560 value += *inp;
1561 inp += span;
1562 }
1563 inp -= back;
1564 }
1565 inp -= back2;
1566 *outp++ = (value+(div>>1))/div;
1567 /* G */
1568 value = 0;
1569 for (xx = factor; xx > 0; xx--)
1570 {
1571 for (y = factor; y > 0; y--)
1572 {
1573 value += *inp;
1574 inp += span;
1575 }
1576 inp -= back;
1577 }
1578 inp -= back2;
1579 *outp++ = (value+(div>>1))/div;
1580 /* B */
1581 value = 0;
1582 for (xx = factor; xx > 0; xx--)
1583 {
1584 for (y = factor; y > 0; y--)
1585 {
1586 value += *inp;
1587 inp += span;
1588 }
1589 inp -= back;
1590 }
1591 inp -= 2;
1592 *outp++ = (value+(div>>1))/div;
1593 }
1594 }
1595 }
1596
1597 /* CMYK downscale (no error diffusion) code */
1598
down_core32(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1599 static void down_core32(gx_downscaler_t *ds,
1600 byte *outp,
1601 byte *in_buffer,
1602 int row,
1603 int plane,
1604 int span)
1605 {
1606 int x, xx, y, value;
1607 int pad_white;
1608 byte *inp;
1609 int width = ds->width;
1610 int awidth = ds->awidth;
1611 int factor = ds->factor;
1612 int div = factor*factor;
1613
1614 pad_white = (awidth - width) * factor * 4;
1615 if (pad_white < 0)
1616 pad_white = 0;
1617
1618 if (pad_white)
1619 {
1620 inp = in_buffer + width*factor*4;
1621 for (y = factor; y > 0; y--)
1622 {
1623 memset(inp, 0xFF, pad_white);
1624 inp += span;
1625 }
1626 }
1627
1628 inp = in_buffer;
1629 {
1630 /* Left to Right pass (no min feature size) */
1631 const int back = span * factor - 4;
1632 const int back2 = factor * 4 - 1;
1633 for (x = awidth; x > 0; x--)
1634 {
1635 /* C */
1636 value = 0;
1637 for (xx = factor; xx > 0; xx--)
1638 {
1639 for (y = factor; y > 0; y--)
1640 {
1641 value += *inp;
1642 inp += span;
1643 }
1644 inp -= back;
1645 }
1646 inp -= back2;
1647 *outp++ = (value+(div>>1))/div;
1648 /* M */
1649 value = 0;
1650 for (xx = factor; xx > 0; xx--)
1651 {
1652 for (y = factor; y > 0; y--)
1653 {
1654 value += *inp;
1655 inp += span;
1656 }
1657 inp -= back;
1658 }
1659 inp -= back2;
1660 *outp++ = (value+(div>>1))/div;
1661 /* Y */
1662 value = 0;
1663 for (xx = factor; xx > 0; xx--)
1664 {
1665 for (y = factor; y > 0; y--)
1666 {
1667 value += *inp;
1668 inp += span;
1669 }
1670 inp -= back;
1671 }
1672 inp -= back2;
1673 *outp++ = (value+(div>>1))/div;
1674 /* K */
1675 value = 0;
1676 for (xx = factor; xx > 0; xx--)
1677 {
1678 for (y = factor; y > 0; y--)
1679 {
1680 value += *inp;
1681 inp += span;
1682 }
1683 inp -= back;
1684 }
1685 inp -= 3;
1686 *outp++ = (value+(div>>1))/div;
1687 }
1688 }
1689 }
1690
decode_factor(int factor,int * up,int * down)1691 static void decode_factor(int factor, int *up, int *down)
1692 {
1693 if (factor == 32)
1694 *down = 3, *up = 2;
1695 else if (factor == 34)
1696 *down = 3, *up = 4;
1697 else
1698 *down = factor, *up = 1;
1699 }
1700
1701 int
gx_downscaler_scale(int width,int factor)1702 gx_downscaler_scale(int width, int factor)
1703 {
1704 int up, down;
1705
1706 decode_factor(factor, &up, &down);
1707 return (width*up)/down;
1708 }
1709
gx_downscaler_adjust_bandheight(int factor,int band_height)1710 int gx_downscaler_adjust_bandheight(int factor, int band_height)
1711 {
1712 int up, down;
1713
1714 decode_factor(factor, &up, &down);
1715 return (band_height/down)*down;
1716 }
1717
1718 int
gx_downscaler_scale_rounded(int width,int factor)1719 gx_downscaler_scale_rounded(int width, int factor)
1720 {
1721 int up, down;
1722
1723 decode_factor(factor, &up, &down);
1724 return (width*up + down-1)/down;
1725 }
1726
get_planar_line_for_trap(void * arg,unsigned char * buf)1727 static int get_planar_line_for_trap(void *arg, unsigned char *buf)
1728 {
1729 gx_downscaler_t *ds = (gx_downscaler_t *)arg;
1730 gs_int_rect rect;
1731 gs_get_bits_params_t params; /* params (if trapping) */
1732 int nc = ds->num_planes;
1733 int i, code;
1734 unsigned char *buf2;
1735
1736 rect.p.x = 0;
1737 rect.p.y = ds->claptrap_y++;
1738 rect.q.x = ds->dev->width;
1739 rect.q.y = rect.p.y+1;
1740 /* Allow for devices (like psdcmyk) that make several passes through
1741 * the image. */
1742 if (ds->claptrap_y == ds->dev->height)
1743 ds->claptrap_y = 0;
1744
1745 params = *ds->claptrap_params;
1746 buf2 = buf;
1747 for (i = 0; i < nc; i++)
1748 {
1749 params.data[i] = buf2;
1750 buf2 += ds->width;
1751 }
1752
1753 code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, ¶ms, NULL);
1754 if (code < 0)
1755 return code;
1756
1757 /* Now cope with the fact we might have been returned pointers */
1758 for (i = 0; i < nc; i++)
1759 {
1760 if (params.data[i] != buf)
1761 memcpy(buf, params.data[i], ds->width);
1762 buf += ds->width;
1763 }
1764
1765 return code;
1766 }
1767
check_trapping(gs_memory_t * memory,int trap_w,int trap_h,int num_comps,const int * comp_order)1768 static int check_trapping(gs_memory_t *memory, int trap_w, int trap_h,
1769 int num_comps, const int *comp_order)
1770 {
1771 if (trap_w < 0 || trap_h < 0)
1772 {
1773 dmprintf(memory, "Trapping range must be >= 0");
1774 return_error(gs_error_rangecheck);
1775 }
1776
1777 if (trap_w > 0 || trap_h > 0)
1778 {
1779 if (comp_order == NULL)
1780 {
1781 emprintf(memory, "Trapping cannot be used without comp_order being defined");
1782 return_error(gs_error_rangecheck);
1783 }
1784
1785 /* Check that the comp_order we have been passed is sane */
1786 {
1787 char comps[GS_CLIENT_COLOR_MAX_COMPONENTS] = { 0 };
1788 int i;
1789
1790 for (i = 0; i < num_comps; i++)
1791 {
1792 int n = comp_order[i];
1793 if (n < 0 || n >= num_comps || comps[n] != 0)
1794 break;
1795 comps[n] = 1;
1796 }
1797 if (i != num_comps)
1798 {
1799 emprintf(memory, "Illegal component order passed to trapping");
1800 return_error(gs_error_rangecheck);
1801 }
1802 }
1803 }
1804 return 0;
1805 }
1806
1807 static void
find_aspect_ratio(float * res,int * a,int * b)1808 find_aspect_ratio(float *res, int *a, int *b)
1809 {
1810 float xres = res[0];
1811 float yres = res[1];
1812 float f;
1813
1814 if (xres == yres) {
1815 *a = *b = 1;
1816 return;
1817 }
1818 else if (xres > yres)
1819 {
1820 xres /= yres;
1821 f = xres - (int)xres;
1822 if (f >= 0.2 && f < 0.3)
1823 xres *= 4, yres = 4;
1824 else if (f >= 0.3 && f < 0.4)
1825 xres *= 3, yres = 3;
1826 else if (f >= 0.4 && f < 0.6)
1827 xres *= 2, yres = 2;
1828 else if (f >= 0.6 && f < 0.7)
1829 xres *= 3, yres = 3;
1830 else if (f >= 0.7 && f < 0.8)
1831 xres *= 4, yres = 4;
1832 else
1833 yres = 1;
1834 *a = (int)(xres + 0.5);
1835 *b = (int)yres;
1836 }
1837 else
1838 {
1839 yres /= xres;
1840 f = yres - (int)yres;
1841 if (f >= 0.2 && f < 0.3)
1842 yres *= 4, xres = 4;
1843 else if (f >= 0.3 && f < 0.4)
1844 yres *= 3, xres = 3;
1845 else if (f >= 0.4 && f < 0.6)
1846 yres *= 2, xres = 2;
1847 else if (f >= 0.6 && f < 0.7)
1848 yres *= 3, xres = 3;
1849 else if (f >= 0.7 && f < 0.8)
1850 yres *= 4, xres = 4;
1851 else
1852 xres = 1;
1853 *a = (int)xres;
1854 *b = (int)(yres + 0.5);
1855 }
1856 }
1857
init_ets(gx_downscaler_t * ds,int num_planes,gx_downscale_core * downscale_core)1858 static int init_ets(gx_downscaler_t *ds, int num_planes, gx_downscale_core *downscale_core)
1859 {
1860 ETS_Params params = { 0 };
1861 int strengths[MAX_ETS_PLANES] = { 128, 51, 51, 13, 13, 13, 13, 13 };
1862 int lut[ETS_SRC_MAX+1];
1863 int *luts[MAX_ETS_PLANES];
1864 int rs_lut[ETS_SRC_MAX+1];
1865 int *rs_luts[MAX_ETS_PLANES];
1866 int i;
1867 int c1_scale[MAX_ETS_PLANES] = { 1, 1, 1, 1, 1, 1, 1, 1 };
1868 ETS_POLARITY polarity = ETS_BLACK_IS_ONE;
1869
1870 polarity = ETS_BLACK_IS_ONE;
1871
1872 if (num_planes > MAX_ETS_PLANES)
1873 return gs_error_rangecheck;
1874
1875 ds->ets_downscale = downscale_core;
1876
1877 /* Setup a simple gamma scale */
1878 {
1879 double scale = ETS_SRC_MAX;
1880 for (i = 0; i < (ETS_SRC_MAX+1); i++)
1881 lut[i] = (int)((1 << 24) * (pow (i / scale, 1.0)));
1882 }
1883 for (i = 0; i < (ETS_SRC_MAX+1); i++)
1884 rs_lut[i] = 2 << 16;
1885 for (i = 0; i < num_planes; i++)
1886 luts[i] = lut;
1887 for (i = 0; i < num_planes; i++)
1888 rs_luts[i] = rs_lut;
1889
1890 #ifdef WITH_CAL
1891 params.context = ds->dev->memory->gs_lib_ctx->core->cal_ctx;
1892 #endif
1893 params.width = ds->width;
1894 params.n_planes = num_planes;
1895 params.levels = 2;
1896 params.luts = luts;
1897 params.distscale = 0;
1898 find_aspect_ratio(ds->dev->HWResolution, ¶ms.aspect_x, ¶ms.aspect_y);
1899 params.strengths = strengths;
1900 params.rand_scale = 0;
1901 params.c1_scale = c1_scale;
1902 params.ets_bias = ETS_BIAS_REDUCE_POSITIVE;
1903 params.r_style = ETS_RSTYLE_THRESHOLD;
1904 params.dump_file = NULL;
1905 params.dump_level = 0;
1906 params.rand_scale_luts = rs_luts;
1907 params.polarity = polarity;
1908
1909 ds->ets_config = ets_create(ds->dev->memory, ¶ms);
1910 if (ds->ets_config == NULL)
1911 return gs_note_error(gs_error_VMerror);
1912
1913 return 0;
1914 }
1915
init_ht(gx_downscaler_t * ds,int num_planes,gx_downscale_core * downscale_core)1916 static int init_ht(gx_downscaler_t *ds, int num_planes, gx_downscale_core *downscale_core)
1917 {
1918 int nc = ds->early_cm ? ds->post_cm_num_comps : ds->num_comps;
1919
1920 ds->ets_downscale = downscale_core;
1921
1922 /* Allocate us a row (with padding for alignment) so we can hold the
1923 * expanded threshold array. */
1924 ds->htrow_alloc = gs_alloc_bytes(ds->dev->memory, ds->width * nc + 64,
1925 "gx_downscaler(htrow)");
1926 if (ds->htrow_alloc == NULL)
1927 return gs_error_VMerror;
1928 /* Make an aligned version */
1929 ds->htrow = ds->htrow_alloc + ((32-(intptr_t)ds->htrow_alloc) & 31);
1930
1931 /* Allocate us a row (with padding for alignment) for the downscaled data. */
1932 ds->inbuf_alloc = gs_alloc_bytes(ds->dev->memory, ds->width * nc + 64,
1933 "gx_downscaler(inbuf)");
1934 if (ds->inbuf_alloc == NULL)
1935 {
1936 gs_free_object(ds->dev->memory, ds->htrow_alloc, "gx_downscaler(htrow)");
1937 ds->htrow_alloc = ds->htrow = NULL;
1938 return gs_error_VMerror;
1939 }
1940 /* Make an aligned version */
1941 ds->inbuf = ds->inbuf_alloc + ((32-(intptr_t)ds->inbuf_alloc) & 31);
1942
1943 return 0;
1944 }
1945
gx_downscaler_init_planar(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc)1946 int gx_downscaler_init_planar(gx_downscaler_t *ds,
1947 gx_device *dev,
1948 gs_get_bits_params_t *params,
1949 int num_comps,
1950 int factor,
1951 int mfs,
1952 int src_bpc,
1953 int dst_bpc)
1954 {
1955 return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
1956 factor, mfs, src_bpc, dst_bpc, 0, 0, NULL, NULL, NULL, num_comps);
1957 }
1958
gx_downscaler_init_planar_trapped(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc,int trap_w,int trap_h,const int * comp_order)1959 int gx_downscaler_init_planar_trapped(gx_downscaler_t *ds,
1960 gx_device *dev,
1961 gs_get_bits_params_t *params,
1962 int num_comps,
1963 int factor,
1964 int mfs,
1965 int src_bpc,
1966 int dst_bpc,
1967 int trap_w,
1968 int trap_h,
1969 const int *comp_order)
1970 {
1971 return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
1972 factor, mfs, src_bpc, dst_bpc,
1973 trap_w, trap_h, comp_order,
1974 NULL, NULL, num_comps);
1975 }
1976
gx_downscaler_init_planar_trapped_cm(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)1977 int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
1978 gx_device *dev,
1979 gs_get_bits_params_t *params,
1980 int num_comps,
1981 int factor,
1982 int mfs,
1983 int src_bpc,
1984 int dst_bpc,
1985 int trap_w,
1986 int trap_h,
1987 const int *comp_order,
1988 gx_downscale_cm_fn *apply_cm,
1989 void *apply_cm_arg,
1990 int post_cm_num_comps)
1991 {
1992 int span = bitmap_raster(dev->width * src_bpc);
1993 int post_span = bitmap_raster(dev->width * src_bpc);
1994 int width;
1995 int code;
1996 gx_downscale_core *core;
1997 int i;
1998 int upfactor, downfactor;
1999
2000 decode_factor(factor, &upfactor, &downfactor);
2001
2002 /* width = scaled width */
2003 width = (dev->width*upfactor)/downfactor;
2004 memset(ds, 0, sizeof(*ds));
2005 ds->dev = dev;
2006 ds->width = width;
2007 ds->awidth = width;
2008 ds->span = span;
2009 ds->factor = factor;
2010 ds->num_planes = num_comps;
2011 ds->src_bpc = src_bpc;
2012 ds->scaled_data = NULL;
2013 ds->scaled_span = bitmap_raster((dst_bpc*dev->width*upfactor + downfactor-1)/downfactor);
2014 ds->apply_cm = apply_cm;
2015 ds->apply_cm_arg = apply_cm_arg;
2016 ds->early_cm = dst_bpc < src_bpc;
2017 ds->post_cm_num_comps = post_cm_num_comps;
2018
2019 if (apply_cm) {
2020 for (i = 0; i < post_cm_num_comps; i++) {
2021 ds->post_cm[i] = gs_alloc_bytes(dev->memory, post_span * downfactor,
2022 "gx_downscaler(planar_data)");
2023 if (ds->post_cm[i] == NULL) {
2024 code = gs_note_error(gs_error_VMerror);
2025 goto cleanup;
2026 }
2027 }
2028 }
2029
2030 code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
2031 if (code < 0)
2032 return code;
2033
2034 if (trap_w > 0 || trap_h > 0) {
2035 ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_planar_line_for_trap, ds);
2036 if (ds->claptrap == NULL) {
2037 emprintf(dev->memory, "Trapping initialisation failed");
2038 code = gs_note_error(gs_error_VMerror);
2039 goto cleanup;
2040 }
2041 }
2042 else
2043 ds->claptrap = NULL;
2044
2045 memcpy(&ds->params, params, sizeof(*params));
2046 ds->params.raster = span;
2047 for (i = 0; i < num_comps; i++) {
2048 ds->pre_cm[i] = gs_alloc_bytes(dev->memory, span * downfactor,
2049 "gx_downscaler(planar_data)");
2050 if (ds->pre_cm[i] == NULL) {
2051 code = gs_note_error(gs_error_VMerror);
2052 goto cleanup;
2053 }
2054 }
2055 if (upfactor > 1) {
2056 ds->scaled_data = gs_alloc_bytes(dev->memory, ds->scaled_span * upfactor * num_comps,
2057 "gx_downscaler(scaled_data)");
2058 if (ds->scaled_data == NULL) {
2059 code = gs_note_error(gs_error_VMerror);
2060 goto cleanup;
2061 }
2062 }
2063
2064 if ((src_bpc == 8) && (dst_bpc == 8) && (factor == 32)) {
2065 core = &down_core8_3_2;
2066 } else if ((src_bpc == 8) && (dst_bpc == 8) && (factor == 34)) {
2067 core = &down_core8_3_4;
2068 } else if (factor > 8) {
2069 code = gs_note_error(gs_error_rangecheck);
2070 goto cleanup;
2071 } else if (dst_bpc == 1) {
2072 if (mfs > 1)
2073 core = &down_core_mfs;
2074 else if (factor == 4)
2075 core = &down_core_4;
2076 else if (factor == 3)
2077 core = &down_core_3;
2078 else if (factor == 2)
2079 core = &down_core_2;
2080 else if (factor == 1)
2081 core = &down_core_1;
2082 else
2083 core = &down_core;
2084 } else if (factor == 1)
2085 core = NULL;
2086 else if (src_bpc == 16)
2087 core = &down_core16;
2088 else if (factor == 4)
2089 core = &down_core8_4;
2090 else if (factor == 3)
2091 core = &down_core8_3;
2092 else if (factor == 2)
2093 core = &down_core8_2;
2094 else
2095 core = &down_core8;
2096 ds->down_core = core;
2097
2098 if (mfs > 1) {
2099 ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
2100 (width+1) * num_comps,
2101 "gx_downscaler(mfs)");
2102 if (ds->mfs_data == NULL) {
2103 code = gs_note_error(gs_error_VMerror);
2104 goto cleanup;
2105 }
2106 memset(ds->mfs_data, 0, (width+1) * num_comps);
2107 }
2108 if (dst_bpc == 1) {
2109 ds->errors = (int *)gs_alloc_bytes(dev->memory,
2110 num_comps*(width+3)*sizeof(int),
2111 "gx_downscaler(errors)");
2112 if (ds->errors == NULL) {
2113 code = gs_note_error(gs_error_VMerror);
2114 goto cleanup;
2115 }
2116 memset(ds->errors, 0, num_comps * (width+3) * sizeof(int));
2117 }
2118
2119 return 0;
2120
2121 cleanup:
2122 gx_downscaler_fin(ds);
2123 return code;
2124 }
2125
get_line_for_trap(void * arg,unsigned char * buf)2126 static int get_line_for_trap(void *arg, unsigned char *buf)
2127 {
2128 gx_downscaler_t *ds = (gx_downscaler_t *)arg;
2129
2130 /* Allow for devices (like psdcmyk) that make several passes through
2131 * the image. */
2132 if (ds->claptrap_y == ds->dev->height)
2133 ds->claptrap_y = 0;
2134
2135 return (*dev_proc(ds->dev, get_bits))(ds->dev, ds->claptrap_y++, buf, NULL);
2136 }
2137
gx_downscaler_init(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width)2138 int gx_downscaler_init(gx_downscaler_t *ds,
2139 gx_device *dev,
2140 int src_bpc,
2141 int dst_bpc,
2142 int num_comps,
2143 int factor,
2144 int mfs,
2145 int (*adjust_width_proc)(int, int),
2146 int adjust_width)
2147 {
2148 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
2149 factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, 0);
2150 }
2151
2152
gx_downscaler_init_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int ets)2153 int gx_downscaler_init_ets(gx_downscaler_t *ds,
2154 gx_device *dev,
2155 int src_bpc,
2156 int dst_bpc,
2157 int num_comps,
2158 int factor,
2159 int mfs,
2160 int (*adjust_width_proc)(int, int),
2161 int adjust_width,
2162 int ets)
2163 {
2164 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
2165 factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, ets);
2166 }
2167
gx_downscaler_init_trapped(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order)2168 int gx_downscaler_init_trapped(gx_downscaler_t *ds,
2169 gx_device *dev,
2170 int src_bpc,
2171 int dst_bpc,
2172 int num_comps,
2173 int factor,
2174 int mfs,
2175 int (*adjust_width_proc)(int, int),
2176 int adjust_width,
2177 int trap_w,
2178 int trap_h,
2179 const int *comp_order)
2180 {
2181 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2182 num_comps, factor, mfs,
2183 adjust_width_proc, adjust_width,
2184 trap_w, trap_h, comp_order,
2185 NULL, NULL, 0, 0);
2186 }
2187
gx_downscaler_init_trapped_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,int ets)2188 int gx_downscaler_init_trapped_ets(gx_downscaler_t *ds,
2189 gx_device *dev,
2190 int src_bpc,
2191 int dst_bpc,
2192 int num_comps,
2193 int factor,
2194 int mfs,
2195 int (*adjust_width_proc)(int, int),
2196 int adjust_width,
2197 int trap_w,
2198 int trap_h,
2199 const int *comp_order,
2200 int ets)
2201 {
2202 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2203 num_comps, factor, mfs,
2204 adjust_width_proc, adjust_width,
2205 trap_w, trap_h, comp_order,
2206 NULL, NULL, 0, ets);
2207 }
gx_downscaler_init_cm(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)2208 int gx_downscaler_init_cm(gx_downscaler_t *ds,
2209 gx_device *dev,
2210 int src_bpc,
2211 int dst_bpc,
2212 int num_comps,
2213 int factor,
2214 int mfs,
2215 int (*adjust_width_proc)(int, int),
2216 int adjust_width,
2217 gx_downscale_cm_fn *apply_cm,
2218 void *apply_cm_arg,
2219 int post_cm_num_comps)
2220 {
2221 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2222 num_comps, factor, mfs,
2223 adjust_width_proc, adjust_width,
2224 0, 0, NULL,
2225 apply_cm, apply_cm_arg, post_cm_num_comps, 0);
2226 }
2227
gx_downscaler_init_cm_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,int ets)2228 int gx_downscaler_init_cm_ets(gx_downscaler_t *ds,
2229 gx_device *dev,
2230 int src_bpc,
2231 int dst_bpc,
2232 int num_comps,
2233 int factor,
2234 int mfs,
2235 int (*adjust_width_proc)(int, int),
2236 int adjust_width,
2237 gx_downscale_cm_fn *apply_cm,
2238 void *apply_cm_arg,
2239 int post_cm_num_comps,
2240 int ets)
2241 {
2242 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2243 num_comps, factor, mfs,
2244 adjust_width_proc, adjust_width,
2245 0, 0, NULL,
2246 apply_cm, apply_cm_arg, post_cm_num_comps, ets);
2247 }
2248
gx_downscaler_init_trapped_cm(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)2249 int gx_downscaler_init_trapped_cm(gx_downscaler_t *ds,
2250 gx_device *dev,
2251 int src_bpc,
2252 int dst_bpc,
2253 int num_comps,
2254 int factor,
2255 int mfs,
2256 int (*adjust_width_proc)(int, int),
2257 int adjust_width,
2258 int trap_w,
2259 int trap_h,
2260 const int *comp_order,
2261 gx_downscale_cm_fn *apply_cm,
2262 void *apply_cm_arg,
2263 int post_cm_num_comps)
2264 {
2265 return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2266 num_comps, factor, mfs,
2267 adjust_width_proc, adjust_width,
2268 trap_w, trap_h, comp_order,
2269 apply_cm, apply_cm_arg, post_cm_num_comps,
2270 0);
2271 }
2272
2273 static gx_downscaler_ht_t bogus_ets_halftone;
2274
gx_downscaler_init_trapped_cm_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,int ets)2275 int gx_downscaler_init_trapped_cm_ets(gx_downscaler_t *ds,
2276 gx_device *dev,
2277 int src_bpc,
2278 int dst_bpc,
2279 int num_comps,
2280 int factor,
2281 int mfs,
2282 int (*adjust_width_proc)(int, int),
2283 int adjust_width,
2284 int trap_w,
2285 int trap_h,
2286 const int *comp_order,
2287 gx_downscale_cm_fn *apply_cm,
2288 void *apply_cm_arg,
2289 int post_cm_num_comps,
2290 int ets)
2291 {
2292 return gx_downscaler_init_trapped_cm_halftone(ds,
2293 dev,
2294 src_bpc,
2295 dst_bpc,
2296 num_comps,
2297 factor,
2298 mfs,
2299 adjust_width_proc,
2300 adjust_width,
2301 trap_w,
2302 trap_h,
2303 comp_order,
2304 apply_cm,
2305 apply_cm_arg,
2306 post_cm_num_comps,
2307 ets ? &bogus_ets_halftone : NULL);
2308 }
2309
2310
2311 static gx_downscale_core *
select_8_to_8_core(int nc,int factor)2312 select_8_to_8_core(int nc, int factor)
2313 {
2314 if (factor == 1)
2315 return NULL; /* No sense doing anything */
2316 if (nc == 1)
2317 {
2318 if (factor == 4)
2319 return &down_core8_4;
2320 else if (factor == 3)
2321 return &down_core8_3;
2322 else if (factor == 2)
2323 return &down_core8_2;
2324 else
2325 return &down_core8;
2326 }
2327 else if (nc == 3)
2328 return &down_core24;
2329 else if (nc == 4)
2330 return &down_core32;
2331
2332 return NULL;
2333 }
2334
2335 int
gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,gx_downscaler_ht_t * ht)2336 gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
2337 gx_device *dev,
2338 int src_bpc,
2339 int dst_bpc,
2340 int num_comps,
2341 int factor,
2342 int mfs,
2343 int (*adjust_width_proc)(int, int),
2344 int adjust_width,
2345 int trap_w,
2346 int trap_h,
2347 const int *comp_order,
2348 gx_downscale_cm_fn *apply_cm,
2349 void *apply_cm_arg,
2350 int post_cm_num_comps,
2351 gx_downscaler_ht_t *ht)
2352 {
2353 int size;
2354 int post_size;
2355 int span;
2356 int width;
2357 int awidth;
2358 int pad_white;
2359 int code;
2360 gx_downscale_core *core;
2361 int upfactor;
2362 int downfactor;
2363 int nc;
2364
2365 size = gdev_mem_bytes_per_scan_line((gx_device *)dev);
2366 post_size = bitmap_raster(dev->width * src_bpc * post_cm_num_comps);
2367
2368 decode_factor(factor, &upfactor, &downfactor);
2369
2370 /* width = scaled width */
2371 width = (dev->width * upfactor)/downfactor;
2372 awidth = width;
2373 if (adjust_width_proc != NULL)
2374 awidth = (*adjust_width_proc)(width, adjust_width);
2375 pad_white = awidth - width;
2376 if (pad_white < 0)
2377 pad_white = 0;
2378
2379 /* size = unscaled size. span = unscaled size + padding */
2380 span = size + pad_white*downfactor*num_comps/upfactor + downfactor-1;
2381 memset(ds, 0, sizeof(*ds));
2382 ds->dev = dev;
2383 ds->width = width;
2384 ds->awidth = awidth;
2385 ds->span = span;
2386 ds->factor = factor;
2387 ds->num_planes = 0;
2388 ds->src_bpc = src_bpc;
2389 ds->apply_cm = apply_cm;
2390 ds->apply_cm_arg = apply_cm_arg;
2391 ds->early_cm = dst_bpc < src_bpc;
2392 ds->post_cm_num_comps = post_cm_num_comps;
2393 ds->ht = ht;
2394 ds->dst_bpc = dst_bpc;
2395 ds->num_comps = num_comps;
2396
2397 code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
2398 if (code < 0)
2399 return code;
2400
2401 if (trap_w > 0 || trap_h > 0) {
2402 ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_line_for_trap, ds);
2403 if (ds->claptrap == NULL) {
2404 emprintf(dev->memory, "Trapping initialisation failed");
2405 code = gs_note_error(gs_error_VMerror);
2406 goto cleanup;
2407 }
2408 } else
2409 ds->claptrap = NULL;
2410
2411 /* Choose an appropriate core. Try to honour our early_cm
2412 * choice, and fallback to late cm if we can't. */
2413 core = NULL;
2414 while (1)
2415 {
2416 nc = ds->early_cm ? post_cm_num_comps : num_comps;
2417
2418 if (factor > 8) {
2419 code = gs_note_error(gs_error_rangecheck);
2420 goto cleanup;
2421 }
2422 else if ((src_bpc == 16) && (dst_bpc == 16) && (nc == 1))
2423 {
2424 core = &down_core16;
2425 }
2426 else if ((src_bpc == 8) && (dst_bpc == 1) && (nc == 4))
2427 {
2428 if (mfs > 1)
2429 core = &down_core4_mfs;
2430 else if (ht == &bogus_ets_halftone)
2431 {
2432 code = init_ets(ds, 4, select_8_to_8_core(nc, factor));
2433 if (code)
2434 goto cleanup;
2435 core = &down_core4_ets;
2436 }
2437 else if (ht != NULL)
2438 {
2439 code = init_ht(ds, 4, select_8_to_8_core(nc, factor));
2440 if (code)
2441 goto cleanup;
2442 core = &down_core4_ht;
2443 }
2444 else
2445 core = &down_core4;
2446 }
2447 else if ((src_bpc == 8) && (dst_bpc == 1) && (nc == 1))
2448 {
2449 if (mfs > 1)
2450 core = &down_core_mfs;
2451 else if (ht == &bogus_ets_halftone)
2452 {
2453 code = init_ets(ds, 1, select_8_to_8_core(nc, factor));
2454 if (code)
2455 goto cleanup;
2456 core = &down_core_ets_1;
2457 }
2458 else if (factor == 4)
2459 core = &down_core_4;
2460 else if (factor == 3)
2461 core = &down_core_3;
2462 else if (factor == 2)
2463 core = &down_core_2;
2464 else if (factor == 1)
2465 core = &down_core_1;
2466 else
2467 core = &down_core;
2468 }
2469 else if ((factor == 1) && (src_bpc == dst_bpc))
2470 break;
2471 else if (src_bpc == 8 && dst_bpc == 8)
2472 core = select_8_to_8_core(nc, factor);
2473
2474 /* If we found one, or we have nothing to fallback to, exit */
2475 if (core || !ds->early_cm)
2476 break;
2477
2478 /* Fallback */
2479 ds->early_cm = false;
2480 }
2481 if (factor == 1 && src_bpc == dst_bpc) {
2482 /* core can permissibly be NULL */
2483 } else if (core == NULL) {
2484 code = gs_note_error(gs_error_rangecheck);
2485 goto cleanup;
2486 }
2487 ds->down_core = core;
2488
2489 if (apply_cm) {
2490 ds->post_cm[0] = gs_alloc_bytes(dev->memory,
2491 post_size * downfactor,
2492 "gx_downscaler(data)");
2493 if (ds->post_cm[0] == NULL) {
2494 code = gs_note_error(gs_error_VMerror);
2495 goto cleanup;
2496 }
2497 }
2498
2499 if (core != NULL || apply_cm) {
2500 ds->pre_cm[0] = gs_alloc_bytes(dev->memory,
2501 span * downfactor,
2502 "gx_downscaler(data)");
2503 if (ds->pre_cm[0] == NULL) {
2504 code = gs_note_error(gs_error_VMerror);
2505 goto cleanup;
2506 }
2507 }
2508 if (core != NULL) {
2509 if (mfs > 1) {
2510 ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
2511 (awidth+1)*nc,
2512 "gx_downscaler(mfs)");
2513 if (ds->mfs_data == NULL) {
2514 code = gs_note_error(gs_error_VMerror);
2515 goto cleanup;
2516 }
2517 memset(ds->mfs_data, 0, (awidth+1)*nc);
2518 }
2519 if (dst_bpc == 1) {
2520 ds->errors = (int *)gs_alloc_bytes(dev->memory,
2521 nc*(awidth+3)*sizeof(int),
2522 "gx_downscaler(errors)");
2523 if (ds->errors == NULL) {
2524 code = gs_note_error(gs_error_VMerror);
2525 goto cleanup;
2526 }
2527 memset(ds->errors, 0, nc * (awidth+3) * sizeof(int));
2528 }
2529 }
2530
2531 return 0;
2532
2533 cleanup:
2534 gx_downscaler_fin(ds);
2535 return code;
2536 }
2537
gx_downscaler_fin(gx_downscaler_t * ds)2538 void gx_downscaler_fin(gx_downscaler_t *ds)
2539 {
2540 int plane;
2541 for (plane=0; plane < GS_CLIENT_COLOR_MAX_COMPONENTS; plane++) {
2542 gs_free_object(ds->dev->memory, ds->pre_cm[plane],
2543 "gx_downscaler(planar_data)");
2544 gs_free_object(ds->dev->memory, ds->post_cm[plane],
2545 "gx_downscaler(planar_data)");
2546 }
2547 ds->num_planes = 0;
2548
2549 gs_free_object(ds->dev->memory, ds->mfs_data, "gx_downscaler(mfs)");
2550 ds->mfs_data = NULL;
2551 gs_free_object(ds->dev->memory, ds->errors, "gx_downscaler(errors)");
2552 ds->errors = NULL;
2553 gs_free_object(ds->dev->memory, ds->scaled_data, "gx_downscaler(scaled_data)");
2554 ds->scaled_data = NULL;
2555 gs_free_object(ds->dev->memory, ds->htrow_alloc, "gx_downscaler(htrow)");
2556 ds->htrow = NULL;
2557 ds->htrow_alloc = NULL;
2558
2559 if (ds->claptrap)
2560 ClapTrap_Fin(ds->dev->memory, ds->claptrap);
2561
2562 if (ds->ets_config)
2563 ets_destroy(ds->dev->memory, ds->ets_config);
2564 }
2565
2566 /* Chunky case */
gx_downscaler_getbits(gx_downscaler_t * ds,byte * out_data,int row)2567 int gx_downscaler_getbits(gx_downscaler_t *ds,
2568 byte *out_data,
2569 int row)
2570 {
2571 int code = 0;
2572 int y, y_end;
2573 byte *data_ptr;
2574 int upfactor, downfactor;
2575
2576 decode_factor(ds->factor, &upfactor, &downfactor);
2577
2578 /* Check for the simple case */
2579 if (ds->down_core == NULL) {
2580 if (ds->claptrap)
2581 code = ClapTrap_GetLine(ds->claptrap, ds->apply_cm ? ds->pre_cm[0] : out_data);
2582 else
2583 code = (*dev_proc(ds->dev, get_bits))(ds->dev, row, ds->apply_cm ? ds->pre_cm[0] : out_data, NULL);
2584 if (code < 0)
2585 return code;
2586 if (ds->apply_cm) {
2587 data_ptr = out_data;
2588 return ds->apply_cm(ds->apply_cm_arg, &data_ptr, ds->pre_cm, ds->width, 1, 0);
2589 }
2590 return 0;
2591 }
2592
2593 /* Get factor rows worth of data */
2594 y = row * downfactor;
2595 y_end = y + downfactor;
2596 data_ptr = ds->pre_cm[0];
2597 if (ds->claptrap) {
2598 do {
2599 code = ClapTrap_GetLine(ds->claptrap, data_ptr);
2600 if (code < 0)
2601 return code;
2602 data_ptr += ds->span;
2603 y++;
2604 } while (y < y_end);
2605 } else {
2606 do {
2607 code = (*dev_proc(ds->dev, get_bits))(ds->dev, y, data_ptr, NULL);
2608 if (code < 0)
2609 return code;
2610 data_ptr += ds->span;
2611 y++;
2612 } while (y < y_end);
2613 }
2614
2615 if (ds->apply_cm) {
2616 if (ds->early_cm) {
2617 code = ds->apply_cm(ds->apply_cm_arg, ds->post_cm, ds->pre_cm, ds->dev->width, 1, 0);
2618 if (code < 0)
2619 return code;
2620 (ds->down_core)(ds, out_data, ds->post_cm[0], row, 0, ds->span);
2621 } else {
2622 data_ptr = out_data;
2623 (ds->down_core)(ds, ds->post_cm[0], ds->pre_cm[0], row, 0, ds->span);
2624 code = ds->apply_cm(ds->apply_cm_arg, &out_data, ds->post_cm, ds->width, 1, 0);
2625 if (code < 0)
2626 return code;
2627 }
2628 } else
2629 (ds->down_core)(ds, out_data, ds->pre_cm[0], row, 0, ds->span);
2630
2631 return code;
2632 }
2633
2634 /* Planar case */
gx_downscaler_get_bits_rectangle(gx_downscaler_t * ds,gs_get_bits_params_t * params,int row)2635 int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
2636 gs_get_bits_params_t *params,
2637 int row)
2638 {
2639 int code;
2640 gs_int_rect rect;
2641 int plane;
2642 int factor = ds->factor;
2643 gs_get_bits_params_t params2;
2644 int upfactor, downfactor;
2645 int subrow;
2646 int copy = (ds->dev->width * ds->src_bpc + 7)>>3;
2647 int i, j;
2648
2649 decode_factor(factor, &upfactor, &downfactor);
2650
2651 subrow = row % upfactor;
2652 if (subrow) {
2653 /* Just copy a previous row from our stored buffer */
2654 for (plane=0; plane < ds->num_planes; plane++)
2655 params->data[plane] = ds->scaled_data + (upfactor * plane + subrow) * ds->scaled_span;
2656 return 0;
2657 }
2658
2659 rect.p.x = 0;
2660 rect.p.y = (row/upfactor) * downfactor;
2661 rect.q.x = ds->dev->width;
2662 rect.q.y = ((row/upfactor) + 1) * downfactor;
2663
2664 /* Check for the simple case */
2665 if (ds->down_core == NULL && ds->claptrap == NULL) {
2666 gs_get_bits_params_t saved;
2667 if (ds->apply_cm) {
2668 /* Always do the request giving our own workspace,
2669 * and be prepared to accept a pointer */
2670 saved = *params;
2671 for (i = 0; i < ds->num_planes; i++)
2672 params->data[i] = ds->pre_cm[i];
2673 params->options |= GB_RETURN_POINTER;
2674 }
2675 code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, params, NULL);
2676 if (code < 0)
2677 return code;
2678 if (ds->apply_cm) {
2679 byte **buffer;
2680 if (saved.options & GB_RETURN_COPY) {
2681 /* They will accept a copy. Let's use the buffer they supplied */
2682 params->options &= ~GB_RETURN_POINTER;
2683 buffer = saved.data;
2684 } else
2685 buffer = ds->pre_cm;
2686 code = ds->apply_cm(ds->apply_cm_arg, params->data, buffer, ds->dev->width, rect.q.y - rect.p.y, params->raster);
2687 if ((saved.options & GB_RETURN_COPY) == 0)
2688 for (i = 0; i < ds->num_planes; i++)
2689 params->data[i] = buffer[i];
2690 }
2691 return code;
2692 }
2693
2694 /* Copy the params, because get_bits_rectangle can helpfully overwrite
2695 * them. */
2696 memcpy(¶ms2, &ds->params, sizeof(params2));
2697 for (i = 0; i < ds->num_planes; i++)
2698 params2.data[i] = ds->pre_cm[i];
2699
2700 /* Get downfactor rows worth of data */
2701 if (ds->claptrap)
2702 code = gs_error_rangecheck; /* Always work a line at a time with claptrap */
2703 else
2704 code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, ¶ms2, NULL);
2705 if (code == gs_error_rangecheck) {
2706 /* At the bottom of a band, the get_bits_rectangle call can fail to be
2707 * able to return us enough lines of data at the same time. We therefore
2708 * drop back to reading them one at a time, and copying them into our
2709 * own buffer. */
2710 for (i = 0; i < downfactor; i++) {
2711 rect.q.y = rect.p.y+1;
2712 if (rect.q.y > ds->dev->height)
2713 break;
2714 memcpy(¶ms2, &ds->params, sizeof(params2));
2715 for (j = 0; j < ds->num_planes; j++)
2716 params2.data[j] = ds->pre_cm[j] + i * ds->span;
2717 if (ds->claptrap) {
2718 ds->claptrap_params = ¶ms2;
2719 code = ClapTrap_GetLinePlanar(ds->claptrap, ¶ms2.data[0]);
2720 } else {
2721 /* We always want a copy */
2722 params2.options &= ~GB_RETURN_POINTER;
2723 params2.options |= GB_RETURN_COPY;
2724 code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, ¶ms2, NULL);
2725 }
2726 if (code < 0)
2727 break;
2728 rect.p.y++;
2729 }
2730 if (i == 0)
2731 return code;
2732 /* If we still haven't got enough, we've hit the end of the page; just
2733 * duplicate the last line we did get. */
2734 for (;i < downfactor; i++)
2735 for (j = 0; j < ds->num_planes; j++)
2736 memcpy(ds->pre_cm[j] + i*ds->span, ds->pre_cm[j] + (i-1)*ds->span, copy);
2737 }
2738 if (code < 0)
2739 return code;
2740
2741 if (ds->early_cm && ds->apply_cm) {
2742 code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, ds->post_cm, ds->dev->width, downfactor, params->raster);
2743 if (code < 0)
2744 return code;
2745 for (j = 0; j < ds->num_planes; j++)
2746 params2.data[j] = ds->post_cm[j];
2747 }
2748
2749 if (upfactor > 1) {
2750 /* Downscale the block of lines into our output buffer */
2751 for (plane=0; plane < ds->num_planes; plane++) {
2752 byte *scaled = ds->scaled_data + upfactor * plane * ds->scaled_span;
2753 (ds->down_core)(ds, scaled, params2.data[plane], row, plane, params2.raster);
2754 params->data[plane] = scaled;
2755 }
2756 } else if (ds->down_core != NULL) {
2757 /* Downscale direct into output buffer */
2758 for (plane=0; plane < ds->num_planes; plane++)
2759 (ds->down_core)(ds, params->data[plane], params2.data[plane], row, plane, params2.raster);
2760 } else {
2761 /* Copy into output buffer */
2762 /* No color management can be required here */
2763 assert(!ds->early_cm || ds->apply_cm == NULL);
2764 for (plane=0; plane < ds->num_planes; plane++)
2765 memcpy(params->data[plane], params2.data[plane], params2.raster);
2766 }
2767
2768 if (!ds->early_cm && ds->apply_cm) {
2769 code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, params2.data, ds->width, 1, params->raster);
2770 if (code < 0)
2771 return code;
2772 }
2773
2774 return code;
2775 }
2776
2777 typedef struct downscaler_process_page_arg_s
2778 {
2779 gx_process_page_options_t *orig_options;
2780 int upfactor;
2781 int downfactor;
2782 gx_downscaler_t ds;
2783 }
2784 downscaler_process_page_arg_t;
2785
2786 typedef struct downscaler_process_page_buffer_s
2787 {
2788 gx_device *bdev;
2789 void *orig_buffer;
2790 }
2791 downscaler_process_page_buffer_t;
2792
downscaler_init_fn(void * arg_,gx_device * dev,gs_memory_t * memory,int w,int h,void ** pbuffer)2793 static int downscaler_init_fn(void *arg_, gx_device *dev, gs_memory_t *memory, int w, int h, void **pbuffer)
2794 {
2795 downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2796 downscaler_process_page_buffer_t *buffer;
2797 int code = 0;
2798
2799 buffer = (downscaler_process_page_buffer_t *)gs_alloc_bytes(memory, sizeof(*buffer), "downscaler process_page buffer");
2800 if (buffer == NULL)
2801 return_error(gs_error_VMerror);
2802 memset(buffer, 0, sizeof(*buffer));
2803
2804 if (arg->upfactor > arg->downfactor) {
2805 code = gx_default_create_buf_device(&buffer->bdev, dev,
2806 (h*arg->upfactor + arg->downfactor-1)/arg->downfactor,
2807 NULL, memory, NULL);
2808 if (code < 0) {
2809 gs_free_object(memory, buffer, "downscaler process_page buffer");
2810 return code;
2811 }
2812 }
2813
2814 if (arg->orig_options && arg->orig_options->init_buffer_fn) {
2815 code = arg->orig_options->init_buffer_fn(arg->orig_options->arg, dev, memory,
2816 (w * arg->upfactor + arg->downfactor-1)/arg->downfactor,
2817 (h * arg->upfactor + arg->downfactor-1)/arg->downfactor,
2818 &buffer->orig_buffer);
2819 if (code < 0) {
2820 if (buffer->bdev)
2821 dev_proc(dev, close_device)(dev);
2822 gs_free_object(memory, buffer, "downscaler process_page buffer");
2823 return code;
2824 }
2825 }
2826
2827 *pbuffer = (void *)buffer;
2828 return code;
2829 }
2830
downscaler_process_fn(void * arg_,gx_device * dev,gx_device * bdev,const gs_int_rect * rect,void * buffer_)2831 static int downscaler_process_fn(void *arg_, gx_device *dev, gx_device *bdev, const gs_int_rect *rect, void *buffer_)
2832 {
2833 downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2834 downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2835 int code, raster_in, raster_out;
2836 gs_get_bits_params_t params;
2837 gs_int_rect in_rect, out_rect;
2838 byte *in_ptr, *out_ptr;
2839
2840 in_rect.p.x = 0;
2841 in_rect.p.y = 0;
2842 in_rect.q.x = rect->q.x - rect->p.x;
2843 in_rect.q.y = rect->q.y - rect->p.y;
2844 out_rect.p.x = 0;
2845 out_rect.p.y = 0;
2846 out_rect.q.x = (in_rect.q.x * arg->upfactor + arg->downfactor-1) / arg->downfactor;
2847 out_rect.q.y = (in_rect.q.y * arg->upfactor + arg->downfactor-1) / arg->downfactor;
2848
2849 /* Where do we get the data from? */
2850 params.options = GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_PACKING_CHUNKY | GB_RETURN_POINTER | GB_ALIGN_ANY | GB_OFFSET_0 | GB_RASTER_ANY;
2851 code = dev_proc(bdev, get_bits_rectangle)(bdev, &in_rect, ¶ms, NULL);
2852 if (code < 0)
2853 return code;
2854 raster_in = params.raster;
2855 in_ptr = params.data[0];
2856
2857 /* Where do we write it to? */
2858 if (buffer->bdev) {
2859 code = dev_proc(bdev, get_bits_rectangle)(buffer->bdev, &out_rect, ¶ms, NULL);
2860 if (code < 0)
2861 return code;
2862 raster_out = params.raster;
2863 out_ptr = params.data[0];
2864 } else {
2865 raster_out = raster_in;
2866 out_ptr = params.data[0];
2867 }
2868
2869 /* Do the downscale */
2870 if (arg->ds.down_core) {
2871 int y;
2872 for (y = rect->p.y; y < rect->q.y; y += arg->downfactor)
2873 {
2874 arg->ds.down_core(&arg->ds, out_ptr, in_ptr, y, 0, arg->ds.span);
2875 in_ptr += arg->ds.span * arg->downfactor;
2876 out_ptr += raster_out * arg->upfactor;
2877 }
2878 }
2879
2880 /* Pass on to further processing */
2881 if (code >= 0 && arg->orig_options && arg->orig_options->process_fn) {
2882 out_rect.p.y = rect->p.y*arg->upfactor/arg->downfactor;
2883 out_rect.q.y += out_rect.p.y;
2884 code = arg->orig_options->process_fn(arg->orig_options->arg, dev,
2885 (buffer->bdev ? buffer->bdev : bdev),
2886 &out_rect, buffer->orig_buffer);
2887 }
2888 return code;
2889 }
2890
2891 static void
downscaler_free_fn(void * arg_,gx_device * dev,gs_memory_t * memory,void * buffer_)2892 downscaler_free_fn(void *arg_, gx_device *dev, gs_memory_t *memory, void *buffer_)
2893 {
2894 downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2895 downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2896
2897 arg->orig_options->free_buffer_fn(arg->orig_options->arg, dev, memory,
2898 buffer->orig_buffer);
2899 if (buffer->bdev)
2900 dev_proc(dev, close_device)(dev);
2901 gs_free_object(memory, buffer, "downscaler process_page buffer");
2902 }
2903
2904 static int
downscaler_output_fn(void * arg_,gx_device * dev,void * buffer_)2905 downscaler_output_fn(void *arg_, gx_device *dev, void *buffer_)
2906 {
2907 downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2908 downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2909
2910 return arg->orig_options->output_fn(arg->orig_options->arg, dev,
2911 buffer->orig_buffer);
2912 }
2913
2914 /* No error diffusion with process_page as bands need to be handled
2915 * separately. */
gx_downscaler_process_page(gx_device * dev,gx_process_page_options_t * options,int factor)2916 int gx_downscaler_process_page(gx_device *dev,
2917 gx_process_page_options_t *options,
2918 int factor)
2919 {
2920 downscaler_process_page_arg_t arg = { 0 };
2921 gx_process_page_options_t my_options = { 0 };
2922 int num_comps = dev->color_info.num_components;
2923 int src_bpc = dev->color_info.comp_bits[0];
2924 int scaled_w;
2925 gx_downscale_core *core;
2926
2927 arg.orig_options = options;
2928 decode_factor(factor, &arg.upfactor, &arg.downfactor);
2929 arg.ds.dev = dev;
2930 arg.ds.width = (dev->width * arg.upfactor + arg.downfactor-1)/arg.downfactor;
2931 arg.ds.awidth = arg.ds.width;
2932 arg.ds.span = bitmap_raster(dev->width * num_comps * src_bpc);
2933 scaled_w = (dev->width * arg.upfactor + arg.downfactor-1)/arg.downfactor;
2934 arg.ds.factor = factor;
2935 arg.ds.src_bpc = src_bpc;
2936 arg.ds.scaled_span = bitmap_raster(scaled_w * num_comps * src_bpc);
2937 arg.ds.num_planes = 0;
2938
2939 /* Choose an appropriate core */
2940 if (factor > 8)
2941 {
2942 return gs_note_error(gs_error_rangecheck);
2943 }
2944 else if ((src_bpc == 16) && (num_comps == 1))
2945 {
2946 core = &down_core16;
2947 }
2948 else if (factor == 1)
2949 core = NULL;
2950 else if ((src_bpc == 8) && (num_comps == 1))
2951 {
2952 if (factor == 4)
2953 core = &down_core8_4;
2954 else if (factor == 3)
2955 core = &down_core8_3;
2956 else if (factor == 2)
2957 core = &down_core8_2;
2958 else
2959 core = &down_core8;
2960 }
2961 else if ((src_bpc == 8) && (num_comps == 3))
2962 core = &down_core24;
2963 else if ((src_bpc == 8) && (num_comps == 4))
2964 core = &down_core32;
2965 else {
2966 return gs_note_error(gs_error_rangecheck);
2967 }
2968 arg.ds.down_core = core;
2969
2970 my_options.init_buffer_fn = downscaler_init_fn;
2971 my_options.process_fn = downscaler_process_fn;
2972 my_options.output_fn = downscaler_output_fn;
2973 my_options.free_buffer_fn = downscaler_free_fn;
2974 my_options.arg = &arg;
2975
2976 return dev_proc(dev, process_page)(dev, &my_options);
2977 }
2978
gx_downscaler_read_params(gs_param_list * plist,gx_downscaler_params * params,int features)2979 int gx_downscaler_read_params(gs_param_list *plist,
2980 gx_downscaler_params *params,
2981 int features)
2982 {
2983 int code;
2984 int downscale, mfs, ets;
2985 int trap_w, trap_h;
2986 const char *param_name;
2987 gs_param_int_array trap_order;
2988
2989 trap_order.data = NULL;
2990
2991 switch (code = param_read_int(plist,
2992 (param_name = "DownScaleFactor"),
2993 &downscale)) {
2994 case 1:
2995 break;
2996 case 0:
2997 if (downscale >= 1) {
2998 params->downscale_factor = downscale;
2999 break;
3000 }
3001 code = gs_error_rangecheck;
3002 default:
3003 param_signal_error(plist, param_name, code);
3004 return code;
3005 }
3006
3007 if (features & GX_DOWNSCALER_PARAMS_MFS)
3008 {
3009 switch (code = param_read_int(plist, (param_name = "MinFeatureSize"), &mfs)) {
3010 case 1:
3011 break;
3012 case 0:
3013 if ((mfs >= 0) && (mfs <= 4)) {
3014 params->min_feature_size = mfs;
3015 break;
3016 }
3017 code = gs_error_rangecheck;
3018 default:
3019 param_signal_error(plist, param_name, code);
3020 return code;
3021 }
3022 }
3023
3024 if (features & GX_DOWNSCALER_PARAMS_TRAP)
3025 {
3026 switch (code = param_read_int(plist,
3027 (param_name = "TrapX"),
3028 &trap_w)) {
3029 case 1:
3030 break;
3031 case 0:
3032 if (trap_w >= 0)
3033 {
3034 params->trap_w = trap_w;
3035 break;
3036 }
3037 code = gs_error_rangecheck;
3038 default:
3039 param_signal_error(plist, param_name, code);
3040 return code;
3041 }
3042 switch (code = param_read_int(plist,
3043 (param_name = "TrapY"),
3044 &trap_h)) {
3045 case 1:
3046 break;
3047 case 0:
3048 if (trap_h >= 0)
3049 {
3050 params->trap_h = trap_h;
3051 break;
3052 }
3053 code = gs_error_rangecheck;
3054 default:
3055 param_signal_error(plist, param_name, code);
3056 return code;
3057 }
3058 switch (code = param_read_int_array(plist, (param_name = "TrapOrder"), &trap_order)) {
3059 case 0:
3060 break;
3061 case 1:
3062 trap_order.data = 0; /* mark as not filled */
3063 break;
3064 default:
3065 param_signal_error(plist, param_name, code);
3066 return code;
3067 }
3068
3069 if (trap_order.data != NULL)
3070 {
3071 int i;
3072 int n = trap_order.size;
3073
3074 if (n > GS_CLIENT_COLOR_MAX_COMPONENTS)
3075 n = GS_CLIENT_COLOR_MAX_COMPONENTS;
3076
3077 for (i = 0; i < n; i++)
3078 {
3079 params->trap_order[i] = trap_order.data[i];
3080 }
3081 for (; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++)
3082 {
3083 params->trap_order[i] = i;
3084 }
3085 }
3086 else
3087 {
3088 /* Set some sane defaults */
3089 int i;
3090
3091 params->trap_order[0] = 3; /* K */
3092 params->trap_order[1] = 1; /* M */
3093 params->trap_order[2] = 0; /* C */
3094 params->trap_order[3] = 2; /* Y */
3095
3096 for (i = 4; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++)
3097 {
3098 params->trap_order[i] = i;
3099 }
3100 }
3101 }
3102 if (features & GX_DOWNSCALER_PARAMS_ETS)
3103 {
3104 switch (code = param_read_int(plist,
3105 (param_name = "DownScaleETS"),
3106 &ets)) {
3107 case 1:
3108 break;
3109 case 0:
3110 if (ets >= 0)
3111 {
3112 params->ets = ets;
3113 break;
3114 }
3115 code = gs_error_rangecheck;
3116 default:
3117 param_signal_error(plist, param_name, code);
3118 return code;
3119 }
3120 }
3121
3122 return 0;
3123 }
3124
gx_downscaler_write_params(gs_param_list * plist,gx_downscaler_params * params,int features)3125 int gx_downscaler_write_params(gs_param_list *plist,
3126 gx_downscaler_params *params,
3127 int features)
3128 {
3129 int code;
3130 int ecode = 0;
3131 gs_param_int_array trap_order;
3132
3133 trap_order.data = params->trap_order;
3134 trap_order.size = GS_CLIENT_COLOR_MAX_COMPONENTS;
3135 trap_order.persistent = false;
3136
3137 if ((code = param_write_int(plist, "DownScaleFactor", ¶ms->downscale_factor)) < 0)
3138 ecode = code;
3139 if (features & GX_DOWNSCALER_PARAMS_MFS)
3140 {
3141 if ((code = param_write_int(plist, "MinFeatureSize", ¶ms->min_feature_size)) < 0)
3142 ecode = code;
3143 }
3144 if (features & GX_DOWNSCALER_PARAMS_TRAP)
3145 {
3146 if ((code = param_write_int(plist, "TrapX", ¶ms->trap_w)) < 0)
3147 ecode = code;
3148 if ((code = param_write_int(plist, "TrapY", ¶ms->trap_h)) < 0)
3149 ecode = code;
3150 if ((code = param_write_int_array(plist, "TrapOrder", &trap_order)) < 0)
3151 ecode = code;
3152 }
3153 if (features & GX_DOWNSCALER_PARAMS_ETS)
3154 {
3155 if ((code = param_write_int(plist, "DownScaleETS", ¶ms->ets)) < 0)
3156 ecode = code;
3157 }
3158
3159 return ecode;
3160 }
3161
3162 /* ETS relies on some malloc wrappers */
ets_malloc(void * malloc_arg,int size)3163 void *ets_malloc(void *malloc_arg, int size)
3164 {
3165 return gs_alloc_bytes((gs_memory_t *)malloc_arg, size, "ets_malloc");
3166 }
3167
ets_calloc(void * malloc_arg,int count,int size)3168 void *ets_calloc(void *malloc_arg, int count, int size)
3169 {
3170 void *p = ets_malloc(malloc_arg, count * size);
3171 if (p)
3172 memset(p, 0, count * size);
3173 return p;
3174 }
3175
ets_free(void * malloc_arg,void * p)3176 void ets_free(void *malloc_arg, void *p)
3177 {
3178 if (!p)
3179 return;
3180
3181 gs_free_object((gs_memory_t *)malloc_arg, p, "ets_malloc");
3182 }
3183