1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: gdevpsds.c 8250 2007-09-25 13:31:24Z giles $ */
15 /* Image processing streams for PostScript and PDF writers */
16 #include "gx.h"
17 #include "memory_.h"
18 #include "gserrors.h"
19 #include "gxdcconv.h"
20 #include "gdevpsds.h"
21 #include "gxbitmap.h"
22 #include "gxcspace.h"
23 #include "gsdcolor.h"
24 #include "gscspace.h"
25 #include "gxdevcli.h"
26 
27 /* ---------------- Convert between 1/2/4/12 and 8 bits ---------------- */
28 
29 gs_private_st_simple(st_1248_state, stream_1248_state, "stream_1248_state");
30 
31 /* Initialize an expansion or reduction stream. */
32 int
s_1248_init(stream_1248_state * ss,int Columns,int samples_per_pixel)33 s_1248_init(stream_1248_state *ss, int Columns, int samples_per_pixel)
34 {
35     ss->samples_per_row = Columns * samples_per_pixel;
36     return ss->template->init((stream_state *)ss);
37 }
38 
39 /* Initialize the state. */
40 static int
s_1_init(stream_state * st)41 s_1_init(stream_state * st)
42 {
43     stream_1248_state *const ss = (stream_1248_state *) st;
44 
45     ss->left = ss->samples_per_row;
46     ss->bits_per_sample = 1;
47     return 0;
48 }
49 static int
s_2_init(stream_state * st)50 s_2_init(stream_state * st)
51 {
52     stream_1248_state *const ss = (stream_1248_state *) st;
53 
54     ss->left = ss->samples_per_row;
55     ss->bits_per_sample = 2;
56     return 0;
57 }
58 static int
s_4_init(stream_state * st)59 s_4_init(stream_state * st)
60 {
61     stream_1248_state *const ss = (stream_1248_state *) st;
62 
63     ss->left = ss->samples_per_row;
64     ss->bits_per_sample = 4;
65     return 0;
66 }
67 static int
s_12_init(stream_state * st)68 s_12_init(stream_state * st)
69 {
70     stream_1248_state *const ss = (stream_1248_state *) st;
71 
72     ss->left = ss->samples_per_row;
73     ss->bits_per_sample = 12;	/* not needed */
74     return 0;
75 }
76 
77 /* Process one buffer. */
78 #define BEGIN_1248\
79 	stream_1248_state * const ss = (stream_1248_state *)st;\
80 	const byte *p = pr->ptr;\
81 	const byte *rlimit = pr->limit;\
82 	byte *q = pw->ptr;\
83 	byte *wlimit = pw->limit;\
84 	uint left = ss->left;\
85 	int status;\
86 	int n
87 #define END_1248\
88 	pr->ptr = p;\
89 	pw->ptr = q;\
90 	ss->left = left;\
91 	return status
92 
93 /* N-to-8 expansion */
94 #define FOREACH_N_8(in, nout)\
95 	status = 0;\
96 	for ( ; p < rlimit; left -= n, q += n, ++p ) {\
97 	  byte in = p[1];\
98 	  n = min(left, nout);\
99 	  if ( wlimit - q < n ) {\
100 	    status = 1;\
101 	    break;\
102 	  }\
103 	  switch ( n ) {\
104 	    case 0: left = ss->samples_per_row; --p; continue;
105 #define END_FOREACH_N_8\
106 	  }\
107 	}
108 static int
s_N_8_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)109 s_N_8_process(stream_state * st, stream_cursor_read * pr,
110 	      stream_cursor_write * pw, bool last)
111 {
112     BEGIN_1248;
113 
114     switch (ss->bits_per_sample) {
115 
116 	case 1:{
117 		FOREACH_N_8(in, 8)
118 	case 8:
119 		q[8] = (byte) - (in & 1);
120 	case 7:
121 		q[7] = (byte) - ((in >> 1) & 1);
122 	case 6:
123 		q[6] = (byte) - ((in >> 2) & 1);
124 	case 5:
125 		q[5] = (byte) - ((in >> 3) & 1);
126 	case 4:
127 		q[4] = (byte) - ((in >> 4) & 1);
128 	case 3:
129 		q[3] = (byte) - ((in >> 5) & 1);
130 	case 2:
131 		q[2] = (byte) - ((in >> 6) & 1);
132 	case 1:
133 		q[1] = (byte) - (in >> 7);
134 		END_FOREACH_N_8;
135 	    }
136 	    break;
137 
138 	case 2:{
139 		static const byte b2[4] =
140 		{0x00, 0x55, 0xaa, 0xff};
141 
142 		FOREACH_N_8(in, 4)
143 	case 4:
144 		q[4] = b2[in & 3];
145 	case 3:
146 		q[3] = b2[(in >> 2) & 3];
147 	case 2:
148 		q[2] = b2[(in >> 4) & 3];
149 	case 1:
150 		q[1] = b2[in >> 6];
151 		END_FOREACH_N_8;
152 	    }
153 	    break;
154 
155 	case 4:{
156 		static const byte b4[16] =
157 		{
158 		    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
159 		    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
160 		};
161 
162 		FOREACH_N_8(in, 2)
163 	case 2:
164 		q[2] = b4[in & 0xf];
165 	case 1:
166 		q[1] = b4[in >> 4];
167 		END_FOREACH_N_8;
168 	    }
169 	    break;
170 
171 	default:
172 	    return ERRC;
173     }
174 
175     END_1248;
176 }
177 
178 /* 12-to-8 "expansion" */
179 static int
s_12_8_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)180 s_12_8_process(stream_state * st, stream_cursor_read * pr,
181 	       stream_cursor_write * pw, bool last)
182 {
183     BEGIN_1248;
184 
185     n = ss->samples_per_row;	/* misuse n to avoid a compiler warning */
186     status = 0;
187     for (; rlimit - p >= 2; ++q) {
188 	if (q >= wlimit) {
189 	    status = 1;
190 	    break;
191 	}
192 	if (left == 0)
193 	    left = n;
194 	if ((n - left) & 1) {
195 	    q[1] = (byte)((p[1] << 4) | (p[2] >> 4));
196 	    p += 2, --left;
197 	} else {
198 	    q[1] = *++p;
199 	    if (!--left)
200 		++p;
201 	}
202     }
203 
204     END_1248;
205 }
206 
207 
208 /* 8-to-N reduction */
209 #define FOREACH_8_N(out, nin)\
210 	byte out;\
211 	status = 1;\
212 	for ( ; q < wlimit; left -= n, p += n, ++q ) {\
213 	  n = min(left, nin);\
214 	  if ( rlimit - p < n ) {\
215 	    status = 0;\
216 	    break;\
217 	  }\
218 	  out = 0;\
219 	  switch ( n ) {\
220 	    case 0: left = ss->samples_per_row; --q; continue;
221 #define END_FOREACH_8_N\
222 	    q[1] = out;\
223 	  }\
224 	}
225 static int
s_8_N_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)226 s_8_N_process(stream_state * st, stream_cursor_read * pr,
227 	      stream_cursor_write * pw, bool last)
228 {
229     BEGIN_1248;
230 
231     switch (ss->bits_per_sample) {
232 
233 	case 1:{
234 		FOREACH_8_N(out, 8)
235 	case 8:
236 		out = p[8] >> 7;
237 	case 7:
238 		out |= (p[7] >> 7) << 1;
239 	case 6:
240 		out |= (p[6] >> 7) << 2;
241 	case 5:
242 		out |= (p[5] >> 7) << 3;
243 	case 4:
244 		out |= (p[4] >> 7) << 4;
245 	case 3:
246 		out |= (p[3] >> 7) << 5;
247 	case 2:
248 		out |= (p[2] >> 7) << 6;
249 	case 1:
250 		out |= p[1] & 0x80;
251 		END_FOREACH_8_N;
252 	    }
253 	    break;
254 
255 	case 2:{
256 		FOREACH_8_N(out, 4)
257 	case 4:
258 		out |= p[4] >> 6;
259 	case 3:
260 		out |= (p[3] >> 6) << 2;
261 	case 2:
262 		out |= (p[2] >> 6) << 4;
263 	case 1:
264 		out |= p[1] & 0xc0;
265 		END_FOREACH_8_N;
266 	    }
267 	    break;
268 
269 	case 4:{
270 		FOREACH_8_N(out, 2)
271 	case 2:
272 		out |= p[2] >> 4;
273 	case 1:
274 		out |= p[1] & 0xf0;
275 		END_FOREACH_8_N;
276 	    }
277 	    break;
278 
279 	default:
280 	    return ERRC;
281     }
282 
283     END_1248;
284 }
285 
286 const stream_template s_1_8_template = {
287     &st_1248_state, s_1_init, s_N_8_process, 1, 8
288 };
289 const stream_template s_2_8_template = {
290     &st_1248_state, s_2_init, s_N_8_process, 1, 4
291 };
292 const stream_template s_4_8_template = {
293     &st_1248_state, s_4_init, s_N_8_process, 1, 2
294 };
295 const stream_template s_12_8_template = {
296     &st_1248_state, s_12_init, s_12_8_process, 1, 2
297 };
298 
299 const stream_template s_8_1_template = {
300     &st_1248_state, s_1_init, s_8_N_process, 8, 1
301 };
302 const stream_template s_8_2_template = {
303     &st_1248_state, s_2_init, s_8_N_process, 4, 1
304 };
305 const stream_template s_8_4_template = {
306     &st_1248_state, s_4_init, s_8_N_process, 2, 1
307 };
308 
309 /* ---------------- Color space conversion ---------------- */
310 
311 /* ------ Convert CMYK to RGB ------ */
312 
313 private_st_C2R_state();
314 
315 /* Initialize a CMYK => RGB conversion stream. */
316 int
s_C2R_init(stream_C2R_state * ss,const gs_imager_state * pis)317 s_C2R_init(stream_C2R_state *ss, const gs_imager_state *pis)
318 {
319     ss->pis = pis;
320     return 0;
321 }
322 
323 /* Set default parameter values (actually, just clear pointers). */
324 static void
s_C2R_set_defaults(stream_state * st)325 s_C2R_set_defaults(stream_state * st)
326 {
327     stream_C2R_state *const ss = (stream_C2R_state *) st;
328 
329     ss->pis = 0;
330 }
331 
332 /* Process one buffer. */
333 static int
s_C2R_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)334 s_C2R_process(stream_state * st, stream_cursor_read * pr,
335 	      stream_cursor_write * pw, bool last)
336 {
337     stream_C2R_state *const ss = (stream_C2R_state *) st;
338     const byte *p = pr->ptr;
339     const byte *rlimit = pr->limit;
340     byte *q = pw->ptr;
341     byte *wlimit = pw->limit;
342 
343     for (; rlimit - p >= 4 && wlimit - q >= 3; p += 4, q += 3) {
344 	byte bc = p[1], bm = p[2], by = p[3], bk = p[4];
345 	frac rgb[3];
346 
347 	color_cmyk_to_rgb(byte2frac(bc), byte2frac(bm), byte2frac(by),
348 			  byte2frac(bk), ss->pis, rgb);
349 	q[1] = frac2byte(rgb[0]);
350 	q[2] = frac2byte(rgb[1]);
351 	q[3] = frac2byte(rgb[2]);
352     }
353     pr->ptr = p;
354     pw->ptr = q;
355     return (rlimit - p < 4 ? 0 : 1);
356 }
357 
358 const stream_template s_C2R_template = {
359     &st_C2R_state, 0 /*NULL */ , s_C2R_process, 4, 3, 0, s_C2R_set_defaults
360 };
361 
362 /* ------ Convert any color space to Indexed ------ */
363 
364 private_st_IE_state();
365 static
366 ENUM_PTRS_WITH(ie_state_enum_ptrs, stream_IE_state *st) return 0;
367 case 0: return ENUM_OBJ(st->Decode);
368 case 1: return ENUM_BYTESTRING(&st->Table);
369 ENUM_PTRS_END
370 static
RELOC_PTRS_WITH(ie_state_reloc_ptrs,stream_IE_state * st)371 RELOC_PTRS_WITH(ie_state_reloc_ptrs, stream_IE_state *st)
372 {
373     RELOC_VAR(st->Decode);
374     RELOC_BYTESTRING_VAR(st->Table);
375 }
376 RELOC_PTRS_END
377 
378 /* Set defaults. */
379 static void
s_IE_set_defaults(stream_state * st)380 s_IE_set_defaults(stream_state * st)
381 {
382     stream_IE_state *const ss = (stream_IE_state *) st;
383 
384     ss->Decode = 0;		/* clear pointers */
385     gs_bytestring_from_string(&ss->Table, 0, 0);
386 }
387 
388 /* Initialize the state. */
389 static int
s_IE_init(stream_state * st)390 s_IE_init(stream_state * st)
391 {
392     stream_IE_state *const ss = (stream_IE_state *) st;
393     int key_index = (1 << ss->BitsPerIndex) * ss->NumComponents;
394     int i;
395 
396     if (ss->Table.data == 0 || ss->Table.size < key_index)
397 	return ERRC;		/****** WRONG ******/
398     /* Initialize Table with default values. */
399     memset(ss->Table.data, 0, ss->NumComponents);
400     ss->Table.data[ss->Table.size - 1] = 0;
401     for (i = 0; i < countof(ss->hash_table); ++i)
402 	ss->hash_table[i] = key_index;
403     ss->next_index = 0;
404     ss->in_bits_left = 0;
405     ss->next_component = 0;
406     ss->byte_out = 1;
407     ss->x = 0;
408     return 0;
409 }
410 
411 /* Process a buffer. */
412 static int
s_IE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)413 s_IE_process(stream_state * st, stream_cursor_read * pr,
414 	     stream_cursor_write * pw, bool last)
415 {
416     stream_IE_state *const ss = (stream_IE_state *) st;
417     /* Constant values from the state */
418     const int bpc = ss->BitsPerComponent;
419     const int num_components = ss->NumComponents;
420     const int end_index = (1 << ss->BitsPerIndex) * num_components;
421     byte *const table = ss->Table.data;
422     byte *const key = table + end_index;
423     /* Dynamic values from the state */
424     uint byte_in = ss->byte_in;
425     int in_bits_left = ss->in_bits_left;
426     int next_component = ss->next_component;
427     uint byte_out = ss->byte_out;
428     /* Other dynamic values */
429     const byte *p = pr->ptr;
430     const byte *rlimit = pr->limit;
431     byte *q = pw->ptr;
432     byte *wlimit = pw->limit;
433     int status = 0;
434 
435     for (;;) {
436 	uint hash, reprobe;
437 	int i, index;
438 
439 	/* Check for a filled output byte. */
440 	if (byte_out >= 0x100) {
441 	    if (q >= wlimit) {
442 		status = 1;
443 		break;
444 	    }
445 	    *++q = (byte)byte_out;
446 	    byte_out = 1;
447 	}
448 	/* Acquire a complete input value. */
449 	while (next_component < num_components) {
450 	    const float *decode = &ss->Decode[next_component * 2];
451 	    int sample;
452 
453 	    if (in_bits_left == 0) {
454 		if (p >= rlimit)
455 		    goto out;
456 		byte_in = *++p;
457 		in_bits_left = 8;
458 	    }
459 	    /* An input sample can never span a byte boundary. */
460 	    in_bits_left -= bpc;
461 	    sample = (byte_in >> in_bits_left) & ((1 << bpc) - 1);
462 	    /* Scale the sample according to Decode. */
463 	    sample = (int)((decode[0] +
464 			    (sample / (float)((1 << bpc) - 1) *
465 			     (decode[1] - decode[0]))) * 255 + 0.5);
466 	    key[next_component++] =
467 		(sample < 0 ? 0 : sample > 255 ? 255 : (byte)sample);
468 	}
469 	/* Look up the input value. */
470 	for (hash = 0, i = 0; i < num_components; ++i)
471 	    hash = hash + 23 * key[i];  /* adhoc */
472 	reprobe = (hash / countof(ss->hash_table)) | 137;  /* adhoc */
473 	for (hash %= countof(ss->hash_table);
474 	     memcmp(table + ss->hash_table[hash], key, num_components);
475 	     hash = (hash + reprobe) % countof(ss->hash_table)
476 	     )
477 	    DO_NOTHING;
478 	index = ss->hash_table[hash];
479 	if (index == end_index) {
480 	    /* The match was on an empty entry. */
481 	    if (ss->next_index == end_index) {
482 		/* Too many different values. */
483 		status = ERRC;
484 		break;
485 	    }
486 	    ss->hash_table[hash] = index = ss->next_index;
487 	    ss->next_index += num_components;
488 	    memcpy(table + index, key, num_components);
489 	}
490 	byte_out = (byte_out << ss->BitsPerIndex) + index / num_components;
491 	next_component = 0;
492 	if (++(ss->x) == ss->Width) {
493 	    /* Handle input and output padding. */
494 	    in_bits_left = 0;
495 	    if (byte_out != 1)
496 		while (byte_out < 0x100)
497 		    byte_out <<= 1;
498 	    ss->x = 0;
499 	}
500     }
501 out:
502     pr->ptr = p;
503     pw->ptr = q;
504     ss->byte_in = byte_in;
505     ss->in_bits_left = in_bits_left;
506     ss->next_component = next_component;
507     ss->byte_out = byte_out;
508     /* For simplicity, always update the record of the table size. */
509     ss->Table.data[ss->Table.size - 1] =
510 	(ss->next_index == 0 ? 0 :
511 	 ss->next_index / ss->NumComponents - 1);
512     return status;
513 }
514 
515 const stream_template s_IE_template = {
516     &st_IE_state, s_IE_init, s_IE_process, 1, 1,
517     0 /* NULL */, s_IE_set_defaults
518 };
519 
520 #if 0
521 
522 /* Test code */
523 void
524 test_IE(void)
525 {
526     const stream_template *const template = &s_IE_template;
527     stream_IE_state state;
528     stream_state *const ss = (stream_state *)&state;
529     static const float decode[6] = {1, 0, 1, 0, 1, 0};
530     static const byte in[] = {
531 	/*
532 	 * Each row is 3 pixels x 3 components x 4 bits.  Processing the
533 	 * first two rows doesn't cause an error; processing all 3 rows
534 	 * does.
535 	 */
536 	0x12, 0x35, 0x67, 0x9a, 0xb0,
537 	0x56, 0x7d, 0xef, 0x12, 0x30,
538 	0x88, 0x88, 0x88, 0x88, 0x80
539     };
540     byte table[3 * 5];
541     int n;
542 
543     template->set_defaults(ss);
544     state.BitsPerComponent = 4;
545     state.NumComponents = 3;
546     state.Width = 3;
547     state.BitsPerIndex = 2;
548     state.Decode = decode;
549     gs_bytestring_from_bytes(&state.Table, table, 0, sizeof(table));
550     for (n = 10; n <= 15; n += 5) {
551 	stream_cursor_read r;
552 	stream_cursor_write w;
553 	byte out[100];
554 	int status;
555 
556 	s_IE_init(ss);
557 	r.ptr = in; --r.ptr;
558 	r.limit = r.ptr + n;
559 	w.ptr = out; --w.ptr;
560 	w.limit = w.ptr + sizeof(out);
561 	memset(table, 0xcc, sizeof(table));
562 	memset(out, 0xff, sizeof(out));
563 	dprintf1("processing %d bytes\n", n);
564 	status = template->process(ss, &r, &w, true);
565 	dprintf3("%d bytes read, %d bytes written, status = %d\n",
566 		 (int)(r.ptr + 1 - in), (int)(w.ptr + 1 - out), status);
567 	debug_dump_bytes(table, table + sizeof(table), "table");
568 	debug_dump_bytes(out, w.ptr + 1, "out");
569     }
570 }
571 
572 #endif
573 
574 /* ---------------- Downsampling ---------------- */
575 
576 /* Return the number of samples after downsampling. */
577 int
s_Downsample_size_out(int size_in,int factor,bool pad)578 s_Downsample_size_out(int size_in, int factor, bool pad)
579 {
580     return ((pad ? size_in + factor - 1 : size_in) / factor);
581 }
582 
583 static void
s_Downsample_set_defaults(register stream_state * st)584 s_Downsample_set_defaults(register stream_state * st)
585 {
586     stream_Downsample_state *const ss = (stream_Downsample_state *)st;
587 
588     s_Downsample_set_defaults_inline(ss);
589 }
590 
591 /* ------ Subsample ------ */
592 
593 gs_private_st_simple(st_Subsample_state, stream_Subsample_state,
594 		     "stream_Subsample_state");
595 
596 /* Initialize the state. */
597 static int
s_Subsample_init(stream_state * st)598 s_Subsample_init(stream_state * st)
599 {
600     stream_Subsample_state *const ss = (stream_Subsample_state *) st;
601 
602     ss->x = ss->y = 0;
603     return 0;
604 }
605 
606 /* Process one buffer. */
607 static int
s_Subsample_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)608 s_Subsample_process(stream_state * st, stream_cursor_read * pr,
609 		    stream_cursor_write * pw, bool last)
610 {
611     stream_Subsample_state *const ss = (stream_Subsample_state *) st;
612     const byte *p = pr->ptr;
613     const byte *rlimit = pr->limit;
614     byte *q = pw->ptr;
615     byte *wlimit = pw->limit;
616     int spp = ss->Colors;
617     int width = ss->WidthIn, height = ss->HeightIn;
618     int xf = ss->XFactor, yf = ss->YFactor;
619     int xf2 = xf / 2, yf2 = yf / 2;
620     int xlimit = (width / xf) * xf, ylimit = (height / yf) * yf;
621     int xlast =
622 	(ss->padX && xlimit < width ? xlimit + (width % xf) / 2 : -1);
623     int ylast =
624 	(ss->padY && ylimit < height ? ylimit + (height % yf) / 2 : -1);
625     int x = ss->x, y = ss->y;
626     int status = 0;
627 
628     if_debug4('w', "[w]subsample: x=%d, y=%d, rcount=%ld, wcount=%ld\n",
629 	      x, y, (long)(rlimit - p), (long)(wlimit - q));
630     for (; rlimit - p >= spp; p += spp) {
631 	if (((y % yf == yf2 && y < ylimit) || y == ylast) &&
632 	    ((x % xf == xf2 && x < xlimit) || x == xlast)
633 	    ) {
634 	    if (wlimit - q < spp) {
635 		status = 1;
636 		break;
637 	    }
638 	    memcpy(q + 1, p + 1, spp);
639 	    q += spp;
640 	}
641 	if (++x == width)
642 	    x = 0, ++y;
643     }
644     if_debug5('w',
645 	      "[w]subsample: x'=%d, y'=%d, read %ld, wrote %ld, status = %d\n",
646 	      x, y, (long)(p - pr->ptr), (long)(q - pw->ptr), status);
647     pr->ptr = p;
648     pw->ptr = q;
649     ss->x = x, ss->y = y;
650     return status;
651 }
652 
653 const stream_template s_Subsample_template = {
654     &st_Subsample_state, s_Subsample_init, s_Subsample_process, 4, 4,
655     0 /* NULL */, s_Downsample_set_defaults
656 };
657 
658 /* ------ Average ------ */
659 
660 private_st_Average_state();
661 
662 /* Set default parameter values (actually, just clear pointers). */
663 static void
s_Average_set_defaults(stream_state * st)664 s_Average_set_defaults(stream_state * st)
665 {
666     stream_Average_state *const ss = (stream_Average_state *) st;
667 
668     s_Downsample_set_defaults(st);
669     /* Clear pointers */
670     ss->sums = 0;
671 }
672 
673 /* Initialize the state. */
674 static int
s_Average_init(stream_state * st)675 s_Average_init(stream_state * st)
676 {
677     stream_Average_state *const ss = (stream_Average_state *) st;
678 
679     ss->sum_size =
680 	ss->Colors * ((ss->WidthIn + ss->XFactor - 1) / ss->XFactor);
681     ss->copy_size = ss->sum_size -
682 	(ss->padX || (ss->WidthIn % ss->XFactor == 0) ? 0 : ss->Colors);
683     ss->sums =
684 	(uint *)gs_alloc_byte_array(st->memory, ss->sum_size,
685 				    sizeof(uint), "Average sums");
686     if (ss->sums == 0)
687 	return ERRC;	/****** WRONG ******/
688     memset(ss->sums, 0, ss->sum_size * sizeof(uint));
689     return s_Subsample_init(st);
690 }
691 
692 /* Release the state. */
693 static void
s_Average_release(stream_state * st)694 s_Average_release(stream_state * st)
695 {
696     stream_Average_state *const ss = (stream_Average_state *) st;
697 
698     gs_free_object(st->memory, ss->sums, "Average sums");
699 }
700 
701 /* Process one buffer. */
702 static int
s_Average_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)703 s_Average_process(stream_state * st, stream_cursor_read * pr,
704 		  stream_cursor_write * pw, bool last)
705 {
706     stream_Average_state *const ss = (stream_Average_state *) st;
707     const byte *p = pr->ptr;
708     const byte *rlimit = pr->limit;
709     byte *q = pw->ptr;
710     byte *wlimit = pw->limit;
711     int spp = ss->Colors;
712     int width = ss->WidthIn;
713     int xf = ss->XFactor, yf = ss->YFactor;
714     int x = ss->x, y = ss->y;
715     uint *sums = ss->sums;
716     int status = 0;
717 
718 top:
719     if (y == yf || (last && p >= rlimit && ss->padY && y != 0)) {
720 	/* We're copying averaged values to the output. */
721 	int ncopy = min(ss->copy_size - x, wlimit - q);
722 
723 	if (ncopy) {
724 	    int scale = xf * y;
725 
726 	    while (--ncopy >= 0)
727 		*++q = (byte) (sums[x++] / scale);
728 	}
729 	if (x < ss->copy_size) {
730 	    status = 1;
731 	    goto out;
732 	}
733 	/* Done copying. */
734 	x = y = 0;
735 	memset(sums, 0, ss->sum_size * sizeof(uint));
736     }
737     while (rlimit - p >= spp) {
738 	uint *bp = sums + x / xf * spp;
739 	int i;
740 
741 	for (i = spp; --i >= 0;)
742 	    *bp++ += *++p;
743 	if (++x == width) {
744 	    x = 0;
745 	    ++y;
746 	    goto top;
747 	}
748     }
749 out:
750     pr->ptr = p;
751     pw->ptr = q;
752     ss->x = x, ss->y = y;
753     return status;
754 }
755 
756 const stream_template s_Average_template = {
757     &st_Average_state, s_Average_init, s_Average_process, 4, 4,
758     s_Average_release, s_Average_set_defaults
759 };
760 
761 /* ---------------- Image compression chooser ---------------- */
762 
763 private_st_compr_chooser_state();
764 
765 /* Initialize the state. */
766 static int
s_compr_chooser_init(stream_state * st)767 s_compr_chooser_init(stream_state * st)
768 {
769     stream_compr_chooser_state *const ss = (stream_compr_chooser_state *) st;
770 
771     ss->choice = 0;
772     ss->width = ss->height = ss->depth = ss->bits_per_sample = 0;
773     ss->sample = 0;
774     ss->samples_count = 0;
775     ss->bits_left = 0;
776     ss->packed_data = 0;
777     ss->lower_plateaus = ss->upper_plateaus = 0;
778     ss->gradients = 0;
779     return 0;
780 }
781 
782 /* Set image dimensions. */
783 int
s_compr_chooser_set_dimensions(stream_compr_chooser_state * ss,int width,int height,int depth,int bits_per_sample)784 s_compr_chooser_set_dimensions(stream_compr_chooser_state * ss, int width,
785 		    int height, int depth, int bits_per_sample)
786 {
787     ss->width = width;
788     ss->height = height;
789     ss->depth = depth;
790     ss->bits_per_sample = bits_per_sample;
791     ss->sample = gs_alloc_bytes(ss->memory, width * depth, "s_compr_chooser_set_dimensions");
792     if (ss->sample == 0)
793 	return_error(gs_error_VMerror);
794     return 0;
795 }
796 
797 /* Release state. */
798 static void
s_compr_chooser_release(stream_state * st)799 s_compr_chooser_release(stream_state * st)
800 {
801     stream_compr_chooser_state *const ss = (stream_compr_chooser_state *) st;
802 
803     gs_free_object(ss->memory, ss->sample, "s_compr_chooser_release");
804 }
805 
806 /* Estimate a row for photo/lineart recognition. */
807 static void
s_compr_chooser__estimate_row(stream_compr_chooser_state * const ss,byte * p)808 s_compr_chooser__estimate_row(stream_compr_chooser_state *const ss, byte *p)
809 {
810     /*	This function uses a statistical algorithm being not well defined.
811 
812 	We compute areas covered by gradients,
813 	separately with small width (line art)
814 	and with big width (photo).
815 	Making the choice based on the areas.
816 
817 	Note that we deal with horizontal frequencies only.
818 	Dealing with vertical ones would be too expensive.
819     */
820     const int delta = 256 / 16; /* about 1/16 of the color range */
821     const int max_lineart_boundary_width = 3; /* pixels */
822     const int max_gradient_constant = 10; /* pixels */
823     int i, j0 = 0, j1 = 0;
824     int w0 = p[0], w1 = p[0], v;
825     ulong plateau_count = 0, lower_plateaus = 0;
826     ulong upper_plateaus = 0, gradients = 0;
827     bool lower = false, upper = false;
828 
829     for (i = 1; i < ss->width; i++) {
830 	v = p[i];
831 	if (!lower) {
832 	    if (w1 < v) {
833 		if (!upper)
834 		    j1 = i - 1;
835 		w1 = v;
836 		upper = true;
837 	    } else if (w1 == v && j1 < i - max_gradient_constant)
838 		j1 = i - max_gradient_constant; /* inner constant plateaw */
839 	    else if (upper && w1 - delta > v) {
840 		/* end of upper plateau at w1-delta...w1 */
841 		for (j0 = i - 1; j0 > j1 && w1 - delta <= p[j0]; j0--) DO_NOTHING;
842 		/* upper plateau j0+1...i-1 */
843 		if(j0 > 0 && i < ss->width - 1) /* ignore sides */
844 		    upper_plateaus += i - j0;
845 		plateau_count ++;
846 		if (j0 > j1) {
847 		    /* upgrade j1...j0 */
848 		    if (j0 > j1 + max_lineart_boundary_width)
849 			gradients += j0 - j1;
850 		}
851 		j1 = i;
852 		upper = false;
853 		w0 = w1;
854 		continue;
855 	    }
856 	}
857 	if (!upper) {
858 	    if (w0 > v) {
859 		if (!lower)
860 		    j1 = i - 1;
861 		w0 = v;
862 		lower = true;
863 	    } else if (w0 == v && j1 < i - max_gradient_constant)
864 		j1 = i - max_gradient_constant; /* inner constant plateaw */
865 	    else if (lower && w0 + delta < v) {
866 		/* end of lower plateau at w0...w0+delta */
867 		for (j0 = i - 1; j0 > j1 && w0 + delta >= p[j0]; j0--) DO_NOTHING;
868 		/* lower plateau j0+1...i-1 */
869 		if(j0 > 0 && i < ss->width - 1) /* ignore sides */
870 		    lower_plateaus += i - j0;
871 		plateau_count ++;
872 		if (j0 > j1) {
873 		    /* downgrade j1...j0 */
874 		    if (j0 > j1 + max_lineart_boundary_width)
875 			gradients += j0 - j1;
876 		}
877 		j1 = i;
878 		lower = false;
879 		w1 = w0;
880 	    }
881 	}
882     }
883     if (plateau_count > ss->width / 6) {
884 	/*  Possibly a dithering, can't recognize.
885 	    It would be better to estimate frequency histogram rather than
886 	    rough quantity, but we hope that the simpler test can work fine.
887 	*/
888     } else if (!plateau_count) /* a pseudo-constant color through entire row */
889 	DO_NOTHING; /* ignore such lines */
890     else {
891 	int plateaus;
892 	ss->lower_plateaus += lower_plateaus;
893 	ss->upper_plateaus += upper_plateaus;
894 	ss->gradients += gradients;
895 	plateaus = min(ss->lower_plateaus, ss->upper_plateaus); /* (fore/back)ground */
896 	if (ss->gradients >= 10000 && ss->gradients > plateaus / 6)
897 	    ss->choice = 1; /* choice is made : photo */
898 	else if (plateaus >= 100000 && plateaus / 5000 >= ss->gradients)
899 	    ss->choice = 2; /* choice is made : lineart */
900     }
901 }
902 
903 /* Recognize photo/lineart. */
904 static void
s_compr_chooser__recognize(stream_compr_chooser_state * ss)905 s_compr_chooser__recognize(stream_compr_chooser_state * ss)
906 {
907     int i;
908     byte *p = ss->sample;
909 
910     for (i = 0; i < ss->depth; i++, p += ss->width)
911 	s_compr_chooser__estimate_row(ss, p);
912     /* todo: make decision */
913 }
914 
915 /* Uppack data and recognize photo/lineart. */
916 static void
s_compr_chooser__unpack_and_recognize(stream_compr_chooser_state * const ss,const byte * data,int length)917 s_compr_chooser__unpack_and_recognize(stream_compr_chooser_state *const ss,
918 				      const byte *data, int length)
919 {
920     /*
921      * Input samples are packed ABCABCABC..., but the sample[] array of
922      * unpacked values is stored AAA...BBB...CCC.  i counts samples within
923      * a pixel, multiplied by width; j counts pixels.
924      */
925     uint i = (ss->samples_count % ss->depth) * ss->width;
926     uint j = ss->samples_count / ss->depth;
927     const byte *p = data;
928     int l = length;
929 
930     while (l) {
931 	if (ss->bits_left < 8) {
932 	    uint k = (sizeof(ss->packed_data) * 8 - ss->bits_left) / 8;
933 
934 	    k = min(k, l);
935 	    for (; k; k--, l--, p++, ss->bits_left += 8)
936 		ss->packed_data = (ss->packed_data << 8) + *p;
937 	}
938 	while (ss->bits_left >= ss->bits_per_sample) {
939 	    uint k = ss->bits_left - ss->bits_per_sample;
940 	    ulong v = ss->packed_data >> k;
941 
942 	    ss->packed_data -= (v << k);
943 	    ss->bits_left -= ss->bits_per_sample;
944 	    if (ss->bits_per_sample > 8)
945 		v >>= ss->bits_per_sample - 8;
946 	    else
947 		v <<= 8 - ss->bits_per_sample;
948 	    ss->sample[i + j] = (byte)v;  /* scaled to 0...255 */
949 	    i += ss->width;
950 	    if (i >= ss->width * ss->depth)
951 		i = 0, j++;
952 	    ss->samples_count++;
953 	    if (ss->samples_count >= ss->width * ss->depth) {
954 		s_compr_chooser__recognize(ss);
955 		ss->packed_data = 0;
956 		ss->bits_left = 0;
957 		ss->samples_count = 0;
958 		i = j = 0;
959 	    }
960 	}
961     }
962 }
963 
964 /* Process a buffer. */
965 static int
s_compr_chooser_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)966 s_compr_chooser_process(stream_state * st, stream_cursor_read * pr,
967 	     stream_cursor_write * pw, bool last)
968 {
969     stream_compr_chooser_state *const ss = (stream_compr_chooser_state *) st;
970     int l = pr->limit - pr->ptr;
971 
972     if (ss->width >= 3) /* Can't process narrow images. */
973 	s_compr_chooser__unpack_and_recognize(ss, pr->ptr + 1, l);
974     pr->ptr += l;
975     return 0;
976 }
977 
978 const stream_template s_compr_chooser_template = {
979     &st_compr_chooser_state, s_compr_chooser_init, s_compr_chooser_process, 1, 1,
980     s_compr_chooser_release, 0 /* NULL */
981 };
982 
983 /* Get choice */
984 uint
s_compr_chooser__get_choice(stream_compr_chooser_state * ss,bool force)985 s_compr_chooser__get_choice(stream_compr_chooser_state *ss, bool force)
986 {
987     ulong plateaus = min(ss->lower_plateaus, ss->upper_plateaus);
988 
989     if (ss->choice)
990 	return ss->choice;
991     if (force) {
992 	if (ss->gradients > plateaus / 12) /* messenger16.pdf, page 3. */
993 	    return 1; /* photo */
994 	else if (plateaus / 5000 >= ss->gradients)
995 	    return 2; /* lineart */
996     }
997     return 0;
998 }
999 
1000 /* ---------------- Am image color conversion filter ---------------- */
1001 
1002 private_st_image_colors_state();
1003 
1004 /* Initialize the state. */
1005 static int
s_image_colors_init(stream_state * st)1006 s_image_colors_init(stream_state * st)
1007 {
1008     stream_image_colors_state *const ss = (stream_image_colors_state *) st;
1009 
1010     ss->width = ss->height = ss->depth = ss->bits_per_sample = 0;
1011     ss->output_bits_buffer = 0;
1012     ss->output_bits_buffered = 0;
1013     ss->output_depth = 1;
1014     ss->output_component_index = ss->output_depth;
1015     ss->output_bits_per_sample = 1;
1016     ss->output_component_bits_written = 0;
1017     ss->raster = 0;
1018     ss->row_bits = 0;
1019     ss->row_bits_passed = 0;
1020     ss->row_alignment_bytes = 0;
1021     ss->row_alignment_bytes_left = 0;
1022     ss->input_component_index = 0;
1023     ss->input_bits_buffer = 0;
1024     ss->input_bits_buffered = 0;
1025     ss->convert_color = 0;
1026     ss->pcs = 0;
1027     ss->pdev = 0;
1028     ss->pis = 0;
1029     return 0;
1030 }
1031 
1032 static int
s_image_colors_convert_color_to_mask(stream_image_colors_state * ss)1033 s_image_colors_convert_color_to_mask(stream_image_colors_state *ss)
1034 {
1035     int i, ii;
1036 
1037     for (i = ii = 0; i < ss->depth; i++, ii += 2)
1038 	if (ss->input_color[i] < ss->MaskColor[ii] ||
1039 	    ss->input_color[i] > ss->MaskColor[ii + 1])
1040 	    break;
1041     ss->output_color[0] = (i < ss->depth ? 1 : 0);
1042     return 0;
1043 }
1044 
1045 static int
s_image_colors_convert_to_device_color(stream_image_colors_state * ss)1046 s_image_colors_convert_to_device_color(stream_image_colors_state * ss)
1047 {
1048     gs_client_color cc;
1049     gx_device_color dc;
1050     int i, code;
1051     double v0 = (1 << ss->bits_per_sample) - 1;
1052     double v1 = (1 << ss->output_bits_per_sample) - 1;
1053 
1054     for (i = 0; i < ss->depth; i++)
1055 	cc.paint.values[i] = ss->input_color[i] *
1056 		(ss->Decode[i * 2 + 1] - ss->Decode[i * 2]) / v0 + ss->Decode[i * 2];
1057 
1058     code = ss->pcs->type->remap_color(&cc, ss->pcs, &dc, ss->pis,
1059 			      ss->pdev, gs_color_select_texture);
1060     if (code < 0)
1061 	return code;
1062     for (i = 0; i < ss->output_depth; i++) {
1063 	uint m = (1 << ss->pdev->color_info.comp_bits[i]) - 1;
1064 	uint w = (dc.colors.pure >> ss->pdev->color_info.comp_shift[i]) & m;
1065 
1066 	ss->output_color[i] = (uint)(v1 * w / m + 0.5);
1067     }
1068     return 0;
1069 }
1070 
1071 /* Set masc colors dimensions. */
1072 void
s_image_colors_set_mask_colors(stream_image_colors_state * ss,uint * MaskColor)1073 s_image_colors_set_mask_colors(stream_image_colors_state * ss, uint *MaskColor)
1074 {
1075     ss->convert_color = s_image_colors_convert_color_to_mask;
1076     memcpy(ss->MaskColor, MaskColor, ss->depth * sizeof(MaskColor[0]) * 2);
1077 }
1078 
1079 /* Set image dimensions. */
1080 void
s_image_colors_set_dimensions(stream_image_colors_state * ss,int width,int height,int depth,int bits_per_sample)1081 s_image_colors_set_dimensions(stream_image_colors_state * ss,
1082 			       int width, int height, int depth, int bits_per_sample)
1083 {
1084     ss->width = width;
1085     ss->height = height;
1086     ss->depth = depth;
1087     ss->bits_per_sample = bits_per_sample;
1088     ss->row_bits = bits_per_sample * depth * width;
1089     ss->raster = bitmap_raster(ss->row_bits);
1090     ss->row_alignment_bytes = 0; /* (ss->raster * 8 - ss->row_bits) / 8) doesn't work. */
1091 }
1092 
1093 void
s_image_colors_set_color_space(stream_image_colors_state * ss,gx_device * pdev,const gs_color_space * pcs,const gs_imager_state * pis,float * Decode)1094 s_image_colors_set_color_space(stream_image_colors_state * ss, gx_device *pdev,
1095 			       const gs_color_space *pcs, const gs_imager_state *pis,
1096 			       float *Decode)
1097 {
1098     ss->output_depth = pdev->color_info.num_components;
1099     ss->output_component_index = ss->output_depth;
1100     ss->output_bits_per_sample = pdev->color_info.comp_bits[0]; /* Same precision for all components. */
1101     ss->convert_color = s_image_colors_convert_to_device_color;
1102     ss->pdev = pdev;
1103     ss->pcs = pcs;
1104     ss->pis = pis;
1105     memcpy(ss->Decode, Decode, ss->depth * sizeof(Decode[0]) * 2);
1106 }
1107 
1108 
1109 /* Process a buffer. */
1110 static int
s_image_colors_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)1111 s_image_colors_process(stream_state * st, stream_cursor_read * pr,
1112 	     stream_cursor_write * pw, bool last)
1113 {
1114     stream_image_colors_state *const ss = (stream_image_colors_state *) st;
1115 
1116     for (;;) {
1117 	if (pw->ptr >= pw->limit)
1118 	    return 1;
1119 	if (ss->row_bits_passed >= ss->row_bits) {
1120 	    ss->row_alignment_bytes_left = ss->row_alignment_bytes;
1121 	    ss->input_bits_buffered = 0;
1122 	    ss->input_bits_buffer = 0; /* Just to simplify the debugging. */
1123 	    if (ss->output_bits_buffered) {
1124 		*(++pw->ptr) = ss->output_bits_buffer;
1125 		ss->output_bits_buffered = 0;
1126 		ss->output_bits_buffer = 0;
1127 	    }
1128 	    ss->row_bits_passed = 0;
1129 	    continue;
1130 	}
1131 	if (ss->row_alignment_bytes_left) {
1132 	    uint k = pr->limit - pr->ptr;
1133 
1134 	    if (k > ss->row_alignment_bytes_left)
1135 		k = ss->row_alignment_bytes_left;
1136 	    pr->ptr += k;
1137 	    ss->row_alignment_bytes_left -= k;
1138 	    if (pr->ptr >= pr->limit)
1139 		return 0;
1140 	}
1141 	if (ss->output_component_index < ss->output_depth) {
1142 	    for (;ss->output_component_index < ss->output_depth;) {
1143 		uint fitting = (uint)(8 - ss->output_bits_buffered);
1144 		uint v, w, u, n, m;
1145 
1146 		if (pw->ptr >= pw->limit)
1147 		    return 1;
1148 		v = ss->output_color[ss->output_component_index];
1149 		n = ss->output_bits_per_sample - ss->output_component_bits_written; /* no. of bits left */
1150 		w = v - ((v >> n) << n); /* the current component without written bits. */
1151 		if (fitting > n)
1152 		    fitting = n; /* no. of bits to write. */
1153 		m = n - fitting; /* no. of bits will left. */
1154 		u = w >> m;  /* bits to write (near lsb). */
1155 		ss->output_bits_buffer |= u << (8 - ss->output_bits_buffered - fitting);
1156 		ss->output_bits_buffered += fitting;
1157 		if (ss->output_bits_buffered >= 8) {
1158 		    *(++pw->ptr) = ss->output_bits_buffer;
1159 		    ss->output_bits_buffered = 0;
1160 		    ss->output_bits_buffer = 0;
1161 		}
1162 		ss->output_component_bits_written += fitting;
1163 		if (ss->output_component_bits_written >= ss->output_bits_per_sample) {
1164 		    ss->output_component_index++;
1165 		    ss->output_component_bits_written = 0;
1166 		}
1167 	    }
1168 	    ss->row_bits_passed += ss->bits_per_sample * ss->depth;
1169 	    continue;
1170 	}
1171 	if (ss->input_bits_buffered < ss->bits_per_sample) {
1172 	    if (pr->ptr >= pr->limit)
1173 		return 0;
1174 	    ss->input_bits_buffer = (ss->input_bits_buffer << 8) | *++pr->ptr;
1175 	    ss->input_bits_buffered += 8;
1176 	    /* fixme: delay shifting the input ptr until input_bits_buffer is cleaned. */
1177 	}
1178 	if (ss->input_bits_buffered >= ss->bits_per_sample) {
1179 	    uint w;
1180 
1181 	    ss->input_bits_buffered -= ss->bits_per_sample;
1182 	    ss->input_color[ss->input_component_index] = w = ss->input_bits_buffer >> ss->input_bits_buffered;
1183 	    ss->input_bits_buffer &= ~(w << ss->input_bits_buffered);
1184 	    ss->input_component_index++;
1185 	    if (ss->input_component_index >= ss->depth) {
1186 		int code = ss->convert_color(ss);
1187 
1188 		if (code < 0)
1189 		    return ERRC;
1190 		ss->output_component_index = 0;
1191 		ss->input_component_index = 0;
1192 	    }
1193 	}
1194     }
1195 }
1196 
1197 const stream_template s__image_colors_template = {
1198     &st_stream_image_colors_state, s_image_colors_init, s_image_colors_process, 1, 1,
1199     NULL, NULL
1200 };
1201 
1202