"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under licence and may not be copied,
7 modified or distributed except as expressly authorised under the terms
8 of the licence contained in the file LICENCE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd,
12 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA,
13 Fax +61 3 9886 6616.
14 */
15
16 /* $Id: cimg.c,v 1.21 2005/06/10 09:39:24 ghostgum Exp $ */
17 /* Common image format and conversion functions */
18
19 #include "common.h"
20 #include "gdevdsp.h"
21 #include "cimg.h"
22 #include "clzw.h"
23
24 static int a85write(char *line, unsigned char *buf, int count);
25
26 /* Return a palette entry for given format and index */
27 void
28 image_colour(unsigned int format, int index,
29 unsigned char *r, unsigned char *g, unsigned char *b)
30 {
31 switch (format & DISPLAY_COLORS_MASK) {
32 case DISPLAY_COLORS_NATIVE:
33 switch (format & DISPLAY_DEPTH_MASK) {
34 case DISPLAY_DEPTH_1:
35 *r = *g = *b = (unsigned char)(index ? 0 : 255);
36 break;
37 case DISPLAY_DEPTH_4:
38 {
39 int one = index & 8 ? 255 : 128;
40 *r = (unsigned char)(index & 4 ? one : 0);
41 *g = (unsigned char)(index & 2 ? one : 0);
42 *b = (unsigned char)(index & 1 ? one : 0);
43 }
44 break;
45 case DISPLAY_DEPTH_8:
46 /* palette of 96 colours */
47 /* 0->63 = 00RRGGBB, 64->95 = 010YYYYY */
48 if (index < 64) {
49 int one = 255 / 3;
50 *r = (unsigned char)(((index & 0x30) >> 4) * one);
51 *g = (unsigned char)(((index & 0x0c) >> 2) * one);
52 *b = (unsigned char)( (index & 0x03) * one);
53 }
54 else {
55 int val = index & 0x1f;
56 *r = *g = *b = (unsigned char)((val << 3) + (val >> 2));
57 }
58 break;
59 }
60 break;
61 case DISPLAY_COLORS_GRAY:
62 switch (format & DISPLAY_DEPTH_MASK) {
63 case DISPLAY_DEPTH_1:
64 *r = *g = *b = (unsigned char)(index ? 255 : 0);
65 break;
66 case DISPLAY_DEPTH_4:
67 *r = *g = *b = (unsigned char)((index<<4) + index);
68 break;
69 case DISPLAY_DEPTH_8:
70 *r = *g = *b = (unsigned char)index;
71 break;
72 }
73 break;
74 }
75 }
76
77 unsigned char
78 colour_to_grey(unsigned char r, unsigned char g, unsigned char b)
79 {
80 return (unsigned char)
81 ((r * 77) / 255 + (g * 150) / 255 + (b * 28) / 255);
82 }
83
84
85 /********************************************************/
86 /* 24BGR */
87
88 /* convert one line of 4-bit native to 24BGR */
89 void
90 image_4native_to_24BGR(int width, unsigned char *dest, unsigned char *source)
91 {
92 int i;
93 int val;
94 for (i=0; i<width; i++) {
95 val = *source;
96 if (i & 1)
97 source++;
98 else
99 val >>= 4;
100 val &= 0x0f;
101 image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4,
102 val, dest+2, dest+1, dest);
103 dest += 3;
104 }
105 }
106
107
108 /* convert one line of 16BGR555 to 24BGR */
109 /* byte0=GGGBBBBB byte1=0RRRRRGG */
110 void
111 image_16BGR555_to_24BGR(int width, unsigned char *dest, unsigned char *source)
112 {
113 int i;
114 WORD w;
115 unsigned char value;
116 for (i=0; i<width; i++) {
117 w = (WORD)(source[0] + (source[1] << 8));
118 value = (unsigned char)(w & 0x1f); /* blue */
119 *dest++ = (unsigned char)((value << 3) + (value >> 2));
120 value = (unsigned char)((w >> 5) & 0x1f); /* green */
121 *dest++ = (unsigned char)((value << 3) + (value >> 2));
122 value = (unsigned char)((w >> 10) & 0x1f); /* red */
123 *dest++ = (unsigned char)((value << 3) + (value >> 2));
124 source += 2;
125 }
126 }
127
128 /* convert one line of 16BGR565 to 24BGR */
129 /* byte0=GGGBBBBB byte1=RRRRRGGG */
130 void
131 image_16BGR565_to_24BGR(int width, unsigned char *dest, unsigned char *source)
132 {
133 int i;
134 WORD w;
135 unsigned char value;
136 for (i=0; i<width; i++) {
137 w = (WORD)(source[0] + (source[1] << 8));
138 value = (unsigned char)(w & 0x1f); /* blue */
139 *dest++ = (unsigned char)((value << 3) + (value >> 2));
140 value = (unsigned char)((w >> 5) & 0x3f); /* green */
141 *dest++ = (unsigned char)((value << 2) + (value >> 4));
142 value = (unsigned char)((w >> 11) & 0x1f); /* red */
143 *dest++ = (unsigned char)((value << 3) + (value >> 2));
144 source += 2;
145 }
146 }
147
148 /* convert one line of 16RGB555 to 24BGR */
149 /* byte0=0RRRRRGG byte1=GGGBBBBB */
150 void
151 image_16RGB555_to_24BGR(int width, unsigned char *dest, unsigned char *source)
152 {
153 int i;
154 WORD w;
155 unsigned char value;
156 for (i=0; i<width; i++) {
157 w = (WORD)((source[0] << 8) + source[1]);
158 value = (unsigned char)(w & 0x1f); /* blue */
159 *dest++ = (unsigned char)((value << 3) + (value >> 2));
160 value = (unsigned char)((w >> 5) & 0x1f); /* green */
161 *dest++ = (unsigned char)((value << 3) + (value >> 2));
162 value = (unsigned char)((w >> 10) & 0x1f); /* red */
163 *dest++ = (unsigned char)((value << 3) + (value >> 2));
164 source += 2;
165 }
166 }
167
168 /* convert one line of 16RGB565 to 24BGR */
169 /* byte0=RRRRRGGG byte1=GGGBBBBB */
170 void
171 image_16RGB565_to_24BGR(int width, unsigned char *dest, unsigned char *source)
172 {
173 int i;
174 WORD w;
175 unsigned char value;
176 for (i=0; i<width; i++) {
177 w = (WORD)((source[0] << 8) + source[1]);
178 value = (unsigned char)(w & 0x1f); /* blue */
179 *dest++ = (unsigned char)((value << 3) + (value >> 2));
180 value = (unsigned char)((w >> 5) & 0x3f); /* green */
181 *dest++ = (unsigned char)((value << 2) + (value >> 4));
182 value = (unsigned char)((w >> 11) & 0x1f); /* red */
183 *dest++ = (unsigned char)((value << 3) + (value >> 2));
184 source += 2;
185 }
186 }
187
188
189 /* convert one line of 32CMYK to 24BGR */
190 void
191 image_32CMYK_to_24BGR(int width, unsigned char *dest, unsigned char *source,
192 int sep)
193 {
194 int i;
195 int cyan, magenta, yellow, black;
196 for (i=0; i<width; i++) {
197 cyan = source[0];
198 magenta = source[1];
199 yellow = source[2];
200 black = source[3];
201 if (!(sep & SEP_CYAN))
202 cyan = 0;
203 if (!(sep & SEP_MAGENTA))
204 magenta = 0;
205 if (!(sep & SEP_YELLOW))
206 yellow = 0;
207 if (!(sep & SEP_BLACK))
208 black = 0;
209 *dest++ =
210 (unsigned char)((255 - yellow) * (255 - black)/255); /* blue */
211 *dest++ =
212 (unsigned char)((255 - magenta) * (255 - black)/255); /* green */
213 *dest++ =
214 (unsigned char)((255 - cyan) * (255 - black)/255); /* red */
215 source += 4;
216 }
217 }
218
219 int
220 image_to_24BGR(IMAGE *img, unsigned char *dest, unsigned char *source)
221 {
222 unsigned char *d = dest;
223 unsigned char *s = source;
224 int width = img->width;
225 unsigned int alpha = img->format & DISPLAY_ALPHA_MASK;
226 BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN;
227 int code = -1;
228 int i;
229
230 switch (img->format & DISPLAY_COLORS_MASK) {
231 case DISPLAY_COLORS_NATIVE:
232 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
233 image_1native_to_24RGB(width, dest, source); /* monochrome */
234 code = 0;
235 }
236 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
237 image_4native_to_24BGR(width, dest, source);
238 code = 0;
239 }
240 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
241 for (i=0; i<width; i++) {
242 image_colour(img->format, *s++, d+2, d+1, d);
243 d+= 3;
244 }
245 code = 0;
246 }
247 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) {
248 if (bigendian) {
249 if ((img->format & DISPLAY_555_MASK)
250 == DISPLAY_NATIVE_555)
251 image_16RGB555_to_24BGR(img->width,
252 dest, source);
253 else
254 image_16RGB565_to_24BGR(img->width,
255 dest, source);
256 }
257 else {
258 if ((img->format & DISPLAY_555_MASK)
259 == DISPLAY_NATIVE_555) {
260 image_16BGR555_to_24BGR(img->width,
261 dest, source);
262 }
263 else
264 image_16BGR565_to_24BGR(img->width,
265 dest, source);
266 }
267 code = 0;
268 }
269 break;
270 case DISPLAY_COLORS_GRAY:
271 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
272 image_1grey_to_24RGB(width, dest, source);
273 code = 0;
274 }
275 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
276 image_4grey_to_24RGB(width, dest, source);
277 code = 0;
278 }
279 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
280 image_8grey_to_24RGB(width, dest, source);
281 code = 0;
282 }
283 break;
284 case DISPLAY_COLORS_RGB:
285 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
286 for (i=0; i<width; i++) {
287 if ((alpha == DISPLAY_ALPHA_FIRST) ||
288 (alpha == DISPLAY_UNUSED_FIRST))
289 s++;
290 if (bigendian) {
291 *d++ = s[2];
292 *d++ = s[1];
293 *d++ = s[0];
294 s+=3;
295 }
296 else {
297 *d++ = *s++;
298 *d++ = *s++;
299 *d++ = *s++;
300 }
301 if ((alpha == DISPLAY_ALPHA_LAST) ||
302 (alpha == DISPLAY_UNUSED_LAST))
303 s++;
304 }
305 code = 0;
306 }
307 break;
308 case DISPLAY_COLORS_CMYK:
309 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
310 image_32CMYK_to_24BGR(width, dest, source,
311 SEP_CYAN | SEP_MAGENTA | SEP_YELLOW | SEP_BLACK);
312 code = 0;
313 }
314 break;
315 }
316 return code;
317 }
318
319 /********************************************************/
320 /* 24RGB */
321
322 /* convert one line of 16BGR555 to 24RGB */
323 /* byte0=GGGBBBBB byte1=0RRRRRGG */
324 void
325 image_16BGR555_to_24RGB(int width, unsigned char *dest, unsigned char *source)
326 {
327 int i;
328 WORD w;
329 unsigned char value;
330 for (i=0; i<width; i++) {
331 w = (WORD)(source[0] + (source[1] << 8));
332 value = (unsigned char)((w >> 10) & 0x1f); /* red */
333 *dest++ = (unsigned char)((value << 3) + (value >> 2));
334 value = (unsigned char)((w >> 5) & 0x1f); /* green */
335 *dest++ = (unsigned char)((value << 3) + (value >> 2));
336 value = (unsigned char)(w & 0x1f); /* blue */
337 *dest++ = (unsigned char)((value << 3) + (value >> 2));
338 source += 2;
339 }
340 }
341
342 /* convert one line of 16BGR565 to 24RGB */
343 /* byte0=GGGBBBBB byte1=RRRRRGGG */
344 void
345 image_16BGR565_to_24RGB(int width, unsigned char *dest, unsigned char *source)
346 {
347 int i;
348 WORD w;
349 unsigned char value;
350 for (i=0; i<width; i++) {
351 w = (WORD)(source[0] + (source[1] << 8));
352 value = (unsigned char)((w >> 11) & 0x1f); /* red */
353 *dest++ = (unsigned char)((value << 3) + (value >> 2));
354 value = (unsigned char)((w >> 5) & 0x3f); /* green */
355 *dest++ = (unsigned char)((value << 2) + (value >> 4));
356 value = (unsigned char)(w & 0x1f); /* blue */
357 *dest++ = (unsigned char)((value << 3) + (value >> 2));
358 source += 2;
359 }
360 }
361
362 /* convert one line of 16RGB555 to 24RGB */
363 /* byte0=0RRRRRGG byte1=GGGBBBBB */
364 void
365 image_16RGB555_to_24RGB(int width, unsigned char *dest, unsigned char *source)
366 {
367 int i;
368 WORD w;
369 unsigned char value;
370 for (i=0; i<width; i++) {
371 w = (WORD)((source[0] << 8) + source[1]);
372 value = (unsigned char)((w >> 10) & 0x1f); /* red */
373 *dest++ = (unsigned char)((value << 3) + (value >> 2));
374 value = (unsigned char)((w >> 5) & 0x1f); /* green */
375 *dest++ = (unsigned char)((value << 3) + (value >> 2));
376 value = (unsigned char)(w & 0x1f); /* blue */
377 *dest++ = (unsigned char)((value << 3) + (value >> 2));
378 source += 2;
379 }
380 }
381
382 /* convert one line of 16RGB565 to 24RGB */
383 /* byte0=RRRRRGGG byte1=GGGBBBBB */
384 void
385 image_16RGB565_to_24RGB(int width, unsigned char *dest, unsigned char *source)
386 {
387 int i;
388 WORD w;
389 unsigned char value;
390 for (i=0; i<width; i++) {
391 w = (WORD)((source[0] << 8) + source[1]);
392 value = (unsigned char)((w >> 11) & 0x1f); /* red */
393 *dest++ = (unsigned char)((value << 3) + (value >> 2));
394 value = (unsigned char)((w >> 5) & 0x3f); /* green */
395 *dest++ = (unsigned char)((value << 2) + (value >> 4));
396 value = (unsigned char)(w & 0x1f); /* blue */
397 *dest++ = (unsigned char)((value << 3) + (value >> 2));
398 source += 2;
399 }
400 }
401
402
403 /* convert one line of 32CMYK to 24RGB */
404 void
405 image_32CMYK_to_24RGB(int width, unsigned char *dest, unsigned char *source,
406 int sep)
407 {
408 int i;
409 int cyan, magenta, yellow, black;
410 for (i=0; i<width; i++) {
411 cyan = source[0];
412 magenta = source[1];
413 yellow = source[2];
414 black = source[3];
415 if (!(sep & SEP_CYAN))
416 cyan = 0;
417 if (!(sep & SEP_MAGENTA))
418 magenta = 0;
419 if (!(sep & SEP_YELLOW))
420 yellow = 0;
421 if (!(sep & SEP_BLACK))
422 black = 0;
423 *dest++ = (unsigned char)
424 ((255 - cyan) * (255 - black)/255); /* red */
425 *dest++ = (unsigned char)
426 ((255 - magenta) * (255 - black)/255); /* green */
427 *dest++ = (unsigned char)
428 ((255 - yellow) * (255 - black)/255); /* blue */
429 source += 4;
430 }
431 }
432
433 /* convert one line of 1-bit gray to 24RGB */
434 void
435 image_1grey_to_24RGB(int width, unsigned char *dest, unsigned char *source)
436 {
437 int i;
438 for (i=0; i<width; i++) {
439 if (*source & (1 << (7 - (i & 7))))
440 dest[0] = dest[1] = dest[2] = 255;
441 else
442 dest[0] = dest[1] = dest[2] = 0;
443 dest += 3;
444 if ((i & 7) == 7)
445 source++;
446 }
447 }
448
449 /* convert one line of 4-bit grey to 24RGB */
450 void
451 image_4grey_to_24RGB(int width, unsigned char *dest, unsigned char *source)
452 {
453 int i;
454 int val;
455 for (i=0; i<width; i++) {
456 if (i & 1) {
457 val = (*source) & 0xf;
458 source++;
459 }
460 else
461 val = (*source >> 4) & 0xf;
462 val = val + (val << 4);
463 dest[0] = dest[1] = dest[2] = (unsigned char)val;
464 dest += 3;
465 }
466 }
467
468 /* convert one line of 8-bit grey to 24RGB */
469 void
470 image_8grey_to_24RGB(int width, unsigned char *dest, unsigned char *source)
471 {
472 int i;
473 for (i=0; i<width; i++) {
474 dest[0] = dest[1] = dest[2] = *source++;
475 dest += 3;
476 }
477 }
478
479 /* convert one line of 1-bit native to 24RGB */
480 void
481 image_1native_to_24RGB(int width, unsigned char *dest, unsigned char *source)
482 {
483 int i;
484 for (i=0; i<width; i++) {
485 if (*source & (1 << (7 - (i & 7))))
486 dest[0] = dest[1] = dest[2] = 0;
487 else
488 dest[0] = dest[1] = dest[2] = 255;
489 dest += 3;
490 if ((i & 7) == 7)
491 source++;
492 }
493 }
494
495 /* convert one line of 4-bit native to 24RGB */
496 void
497 image_4native_to_24RGB(int width, unsigned char *dest, unsigned char *source)
498 {
499 int i;
500 int val;
501 for (i=0; i<width; i++) {
502 val = *source;
503 if (i & 1)
504 source++;
505 else
506 val >>= 4;
507 val &= 0x0f;
508 image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4,
509 val, dest, dest+1, dest+2);
510 dest += 3;
511 }
512 }
513
514 int
515 image_to_24RGB(IMAGE *img, unsigned char *dest, unsigned char *source)
516 {
517 unsigned char *d = dest;
518 unsigned char *s = source;
519 int width = img->width;
520 unsigned int alpha = img->format & DISPLAY_ALPHA_MASK;
521 BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN;
522 int i;
523 int code = -1;
524
525 switch (img->format & DISPLAY_COLORS_MASK) {
526 case DISPLAY_COLORS_NATIVE:
527 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
528 image_1native_to_24RGB(img->width, dest, source);
529 code = 0;
530 }
531 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
532 image_4native_to_24RGB(img->width, dest, source);
533 code = 0;
534 }
535 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
536 for (i=0; i<width; i++) {
537 image_colour(img->format, *s++, d, d+1, d+2);
538 d+= 3;
539 }
540 code = 0;
541 }
542 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) {
543 if (bigendian) {
544 if ((img->format & DISPLAY_555_MASK)
545 == DISPLAY_NATIVE_555)
546 image_16RGB555_to_24RGB(img->width,
547 dest, source);
548 else
549 image_16RGB565_to_24RGB(img->width,
550 dest, source);
551 }
552 else {
553 if ((img->format & DISPLAY_555_MASK)
554 == DISPLAY_NATIVE_555) {
555 image_16BGR555_to_24RGB(img->width,
556 dest, source);
557 }
558 else
559 image_16BGR565_to_24RGB(img->width,
560 dest, source);
561 }
562 code = 0;
563 }
564 break;
565 case DISPLAY_COLORS_GRAY:
566 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
567 image_1grey_to_24RGB(width, dest, source);
568 code = 0;
569 }
570 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
571 image_4grey_to_24RGB(width, dest, source);
572 code = 0;
573 }
574 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
575 image_8grey_to_24RGB(width, dest, source);
576 code = 0;
577 }
578 break;
579 case DISPLAY_COLORS_RGB:
580 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
581 for (i=0; i<width; i++) {
582 if ((alpha == DISPLAY_ALPHA_FIRST) ||
583 (alpha == DISPLAY_UNUSED_FIRST))
584 s++;
585 if (bigendian) {
586 *d++ = *s++;
587 *d++ = *s++;
588 *d++ = *s++;
589 }
590 else {
591 *d++ = s[2];
592 *d++ = s[1];
593 *d++ = s[0];
594 s+=3;
595 }
596 if ((alpha == DISPLAY_ALPHA_LAST) ||
597 (alpha == DISPLAY_UNUSED_LAST))
598 s++;
599 }
600 code = 0;
601 }
602 break;
603 case DISPLAY_COLORS_CMYK:
604 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
605 image_32CMYK_to_24RGB(width, dest, source,
606 SEP_CYAN | SEP_MAGENTA | SEP_YELLOW | SEP_BLACK);
607 code = 0;
608 }
609 break;
610 }
611 return code;
612 }
613
614 /********************************************************/
615 /* Grey */
616
617 void
618 image_1grey_to_8grey(int width, unsigned char *dest, unsigned char *source)
619 {
620 int i;
621 for (i=0; i<width; i++) {
622 if (*source & (1 << (7 - (i & 7))))
623 *dest++ = 255;
624 else
625 *dest++ = 0;
626 if ((i & 7) == 7)
627 source++;
628 }
629 }
630
631 void
632 image_4grey_to_8grey(int width, unsigned char *dest, unsigned char *source)
633 {
634 int i;
635 int value;
636 for (i=0; i<width; i++) {
637 if (i & 1)
638 value = (*source >> 4) & 0x0f;
639 else {
640 value = (*source) & 0x0f;
641 source++;
642 }
643 *dest++ = (unsigned char)(value + (value << 4));
644 }
645 }
646
647 void
648 image_1native_to_8grey(int width, unsigned char *dest, unsigned char *source)
649 {
650 int i;
651 for (i=0; i<width; i++) {
652 if (*source & (1 << (7 - (i & 7))))
653 *dest++ = 0;
654 else
655 *dest++ = 255;
656 if ((i & 7) == 7)
657 source++;
658 }
659 }
660
661 void
662 image_4native_to_8grey(int width, unsigned char *dest, unsigned char *source)
663 {
664 int i;
665 int value;
666 unsigned char r, g, b;
667 for (i=0; i<width; i++) {
668 if (i & 1)
669 value = (*source >> 4) & 0x0f;
670 else {
671 value = (*source) & 0x0f;
672 source++;
673 }
674 image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4,
675 value, &r, &g, &b);
676 *dest++ = colour_to_grey(r,g,b);
677 }
678 }
679
680 void
681 image_8native_to_8grey(int width, unsigned char *dest, unsigned char *source)
682 {
683 int i;
684 int value;
685 unsigned char r, g, b;
686 for (i=0; i<width; i++) {
687 value = *source++;
688 image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_8,
689 value, &r, &g, &b);
690 *dest++ = colour_to_grey(r,g,b);
691 }
692 }
693
694
695 void
696 image_24RGB_to_8grey(int width, unsigned char *dest, unsigned char *source)
697 {
698 int i;
699 for (i=0; i<width; i++) {
700 *dest++ = colour_to_grey(source[0], source[1], source[2]);
701 source+=3;
702 }
703 }
704
705 void
706 image_24BGR_to_8grey(int width, unsigned char *dest, unsigned char *source)
707 {
708 int i;
709 for (i=0; i<width; i++) {
710 *dest++ = colour_to_grey(source[2], source[1], source[0]);
711 source+=3;
712 }
713 }
714
715 static int
716 image_to_8grey(IMAGE *img, unsigned char *dest, unsigned char *source)
717 {
718 /* This is the fallback method which converts to 24RGB first */
719 unsigned char *row = (unsigned char *)malloc(img->width*3);
720 int code = -1;
721 if (row) {
722 code = image_to_24RGB(img, row, source);
723 image_24RGB_to_8grey(img->width, dest, row);
724 free(row);
725 }
726 return code;
727 }
728
729 /* Convert any format to 8-bit grey.
730 * Returns -ve if unsupported format.
731 */
732 int
733 image_to_grey(IMAGE *img, unsigned char *dest, unsigned char *source)
734 {
735 int width = img->width;
736 int code = -1;
737 unsigned int alpha = img->format & DISPLAY_ALPHA_MASK;
738 switch (img->format & DISPLAY_COLORS_MASK) {
739 case DISPLAY_COLORS_NATIVE:
740 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
741 image_1native_to_8grey(width, dest, source);
742 code = 0;
743 }
744 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
745 image_4native_to_8grey(width, dest, source);
746 code = 0;
747 }
748 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
749 image_8native_to_8grey(width, dest, source);
750 code = 0;
751 }
752 else
753 code = image_to_8grey(img, dest, source);
754 break;
755 case DISPLAY_COLORS_GRAY:
756 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
757 image_1grey_to_8grey(width, dest, source);
758 code = 0;
759 }
760 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
761 image_4grey_to_8grey(width, dest, source);
762 code = 0;
763 }
764 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
765 memcpy(dest, source, width);
766 code = 0;
767 }
768 break;
769 case DISPLAY_COLORS_RGB:
770 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
771 code = -1;
772 else if (alpha == DISPLAY_ALPHA_NONE) {
773 if ((img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
774 image_24RGB_to_8grey(width, dest, source);
775 else
776 image_24BGR_to_8grey(width, dest, source);
777 code = 0;
778 }
779 else
780 code = image_to_8grey(img, dest, source);
781 break;
782 case DISPLAY_COLORS_CMYK:
783 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
784 code = -1;
785 else
786 code = image_to_8grey(img, dest, source);
787 break;
788 }
789
790 return code;
791 }
792
793 /********************************************************/
794
795
796 /* Convert a line of image to monochrome with 0=white, 1=black.
797 * Returns -ve if unsupported format.
798 */
799 int
800 image_to_mono(IMAGE *img, unsigned char *dest, unsigned char *source)
801 {
802 int width = img->width;
803 unsigned int alpha = img->format & DISPLAY_ALPHA_MASK;
804 BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN;
805 int bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */
806 unsigned char omask = 0x80;
807 int oroll = 7;
808 int black;
809 unsigned char *s = source;
810 unsigned char mask0 = 0;
811 unsigned char mask1 = 0;
812 unsigned char mask2 = 0;
813 unsigned char mask3 = 0;
814 int bytes_per_pixel = 0;
815 BOOL additive = TRUE;
816 int j;
817
818 switch (img->format & DISPLAY_COLORS_MASK) {
819 case DISPLAY_COLORS_NATIVE:
820 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
821 for (j = 0; j < bwidth ; j++)
822 dest[j] = source[j];
823 return 0;
824 }
825 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
826 for (j = 0; j < width; j++) {
827 if (j & 1) {
828 black = (*s & 0x0f) != 0x0f;
829 s++;
830 }
831 else
832 black = (*s & 0xf0) != 0xf0;
833 if (black)
834 dest[j/8] |= omask;
835 else
836 dest[j/8] &= (unsigned char)(~omask);
837 oroll--;
838 omask >>= 1;
839 if (oroll < 0) {
840 omask = 0x80;
841 oroll = 7;
842 }
843 }
844 return 0;
845 }
846 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
847 for (j = 0; j < width; j++) {
848 black = (*s != 0x3f) && (*s != 0x5f);
849 s++;
850 if (black)
851 dest[j/8] |= omask;
852 else
853 dest[j/8] &= (unsigned char)(~omask);
854 oroll--;
855 omask >>= 1;
856 if (oroll < 0) {
857 omask = 0x80;
858 oroll = 7;
859 }
860 }
861 return 0;
862 }
863 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) {
864 bytes_per_pixel = 2;
865 if (bigendian) {
866 if ((img->format & DISPLAY_555_MASK)
867 == DISPLAY_NATIVE_555) {
868 mask0 = 0x7f;
869 mask1 = 0xff;
870 }
871 else {
872 mask0 = 0xff;
873 mask1 = 0xff;
874 }
875 }
876 else {
877 if ((img->format & DISPLAY_555_MASK)
878 == DISPLAY_NATIVE_555) {
879 mask0 = 0xff;
880 mask1 = 0x7f;
881 }
882 else {
883 mask0 = 0xff;
884 mask1 = 0xff;
885 }
886 }
887 }
888 break;
889 case DISPLAY_COLORS_GRAY:
890 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
891 for (j = 0; j < bwidth ; j++)
892 dest[j] = (unsigned char)~source[j];
893 return 0;
894 }
895 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
896 for (j = 0; j < width; j++) {
897 if (j & 1) {
898 black = (*s & 0x0f) != 0x0f;
899 s++;
900 }
901 else
902 black = (*s & 0xf0) != 0xf0;
903 if (black)
904 dest[j/8] |= omask;
905 else
906 dest[j/8] &= (unsigned char)(~omask);
907 oroll--;
908 omask >>= 1;
909 if (oroll < 0) {
910 omask = 0x80;
911 oroll = 7;
912 }
913 }
914 return 0;
915 }
916 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
917 bytes_per_pixel = 1;
918 mask0 = 0xff;
919 }
920 else
921 return -1;
922 break;
923 case DISPLAY_COLORS_RGB:
924 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
925 return -1;
926
927 if ((alpha == DISPLAY_ALPHA_FIRST) ||
928 (alpha == DISPLAY_UNUSED_FIRST)) {
929 bytes_per_pixel = 4;
930 mask0 = 0;
931 mask1 = 0xff;
932 mask2 = 0xff;
933 mask3 = 0xff;
934 }
935 else {
936 bytes_per_pixel = 3;
937 mask0 = 0xff;
938 mask1 = 0xff;
939 mask2 = 0xff;
940 mask3 = 0;
941 }
942 if ((alpha == DISPLAY_ALPHA_LAST) ||
943 (alpha == DISPLAY_UNUSED_LAST))
944 bytes_per_pixel++;
945 break;
946 case DISPLAY_COLORS_CMYK:
947 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
948 return -1;
949
950 additive = FALSE;
951 bytes_per_pixel = 4;
952 mask0 = 0xff;
953 mask1 = 0xff;
954 mask2 = 0xff;
955 mask3 = 0xff;
956 break;
957 }
958
959 /* one or more bytes per pixel */
960
961 memset(dest, 0xff, bwidth);
962 omask = 0x80;
963 oroll = 7;
964
965 for (j = 0; j < width; j++) {
966 if (additive) {
967 /* RGB */
968 black = (s[0] & mask0) != mask0;
969 if (bytes_per_pixel > 1)
970 black |= (s[1] & mask1) != mask1;
971 if (bytes_per_pixel > 2)
972 black |= (s[2] & mask2) != mask2;
973 if (bytes_per_pixel > 3)
974 black |= (s[3] & mask3) != mask3;
975 }
976 else {
977 /* CMYK */
978 black = (s[0] & mask0) != 0;
979 black |= (s[1] & mask1) != 0;
980 black |= (s[2] & mask2) != 0;
981 black |= (s[3] & mask3) != 0;
982 }
983 s += bytes_per_pixel;
984 if (black)
985 dest[j/8] |= omask;
986 else
987 dest[j/8] &= (unsigned char)(~omask);
988 oroll--;
989 omask >>= 1;
990 if (oroll < 0) {
991 omask = 0x80;
992 oroll = 7;
993 }
994 }
995 return 0;
996 }
997
998
999 /* Return number of bits per pixel.
1000 * If format unknown, return -ve.
1001 */
1002 int
1003 image_depth(IMAGE *img)
1004 {
1005 unsigned int alpha = img->format & DISPLAY_ALPHA_MASK;
1006 int bitcount = -1;
1007 switch (img->format & DISPLAY_COLORS_MASK) {
1008 case DISPLAY_COLORS_NATIVE:
1009 case DISPLAY_COLORS_GRAY:
1010 switch (img->format & DISPLAY_DEPTH_MASK) {
1011 case DISPLAY_DEPTH_1:
1012 bitcount = 1;
1013 break;
1014 case DISPLAY_DEPTH_4:
1015 bitcount = 4;
1016 break;
1017 case DISPLAY_DEPTH_8:
1018 bitcount = 8;
1019 break;
1020 case DISPLAY_DEPTH_16:
1021 bitcount = 16;
1022 break;
1023 }
1024 break;
1025 case DISPLAY_COLORS_RGB:
1026 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1027 if ((alpha == DISPLAY_ALPHA_FIRST) ||
1028 (alpha == DISPLAY_UNUSED_FIRST))
1029 bitcount = 32;
1030 else
1031 bitcount = 24;
1032 if ((alpha == DISPLAY_ALPHA_LAST) ||
1033 (alpha == DISPLAY_UNUSED_LAST))
1034 bitcount += 8;
1035 }
1036 break;
1037 case DISPLAY_COLORS_CMYK:
1038 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8)
1039 bitcount = 32;
1040 break;
1041 }
1042
1043 return bitcount;
1044 }
1045
1046 /********************************************************/
1047
1048 /* Copy an image, converting format if needed */
1049 int image_copy(IMAGE *newimg, IMAGE *oldimg, unsigned int format)
1050 {
1051 int code = 0;
1052 int depth;
1053 int colour_format = (format & DISPLAY_COLORS_MASK);
1054 BOOL mono = FALSE;
1055 BOOL grey = FALSE;
1056 BOOL rgb24 = FALSE;
1057 BOOL bgr24 = FALSE;
1058 memset(newimg, 0, sizeof(IMAGE));
1059 newimg->width = oldimg->width;
1060 newimg->height = oldimg->height;
1061 newimg->raster = oldimg->raster; /* bytes per row */
1062 newimg->format = format;
1063 newimg->image = NULL;
1064 if (newimg->format == oldimg->format) {
1065 /* copy unmodified */
1066 int image_size = newimg->height * newimg->raster;
1067 newimg->image = (unsigned char *)malloc(image_size);
1068 if (newimg->image == NULL)
1069 code = -1;
1070 else {
1071 memcpy(newimg->image, oldimg->image, image_size);
1072 if (image_platform_init(newimg) < 0) {
1073 free(newimg->image);
1074 newimg->image = NULL;
1075 code = -1;
1076 }
1077 }
1078 return code;
1079 }
1080
1081 /* Need to convert the format */
1082 /* We support 1-bit monochrome, 8-bit grey, 24-bit RGB and 24-bit BGR */
1083 depth = image_depth(newimg);
1084 if ((depth == 1) && (colour_format == DISPLAY_COLORS_NATIVE))
1085 mono = TRUE;
1086 else if ((depth == 8) && (colour_format == DISPLAY_COLORS_GRAY))
1087 grey = TRUE;
1088 else if ((depth == 24) && (colour_format == DISPLAY_COLORS_RGB)) {
1089 if ((format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
1090 rgb24 = TRUE;
1091 else
1092 bgr24 = TRUE;
1093 }
1094 else
1095 code = -1;
1096
1097 if (code == 0) {
1098 newimg->raster = (((depth * newimg->width + 7) >> 3) + 3) & ~3;
1099 newimg->image = (unsigned char *)
1100 malloc(newimg->raster * newimg->height);
1101 }
1102
1103 if ((newimg->image == NULL))
1104 code = -1;
1105 else if (code == 0) {
1106 /* convert each row */
1107 unsigned char *source, *dest;
1108 BOOL invert = (newimg->format & DISPLAY_FIRSTROW_MASK) !=
1109 (oldimg->format & DISPLAY_FIRSTROW_MASK);
1110 int i;
1111 for (i=0; i<(int)newimg->height; i++) {
1112 source = oldimg->image + oldimg->raster * i;
1113 if (invert)
1114 dest = newimg->image + newimg->raster * (newimg->height-1-i);
1115 else
1116 dest = newimg->image + newimg->raster * i;
1117 if (mono)
1118 code = image_to_mono(oldimg, dest, source);
1119 else if (grey)
1120 code = image_to_grey(oldimg, dest, source);
1121 else if (rgb24)
1122 code = image_to_24RGB(oldimg, dest, source);
1123 else if (bgr24)
1124 code = image_to_24BGR(oldimg, dest, source);
1125 if (code)
1126 break;
1127 }
1128 }
1129
1130 if (code == 0)
1131 code = image_platform_init(newimg);
1132 if (code) {
1133 if (newimg->image) {
1134 free(newimg->image);
1135 newimg->image = NULL;
1136 }
1137 }
1138 return code;
1139 }
1140
1141 /********************************************************/
1142
1143 /* Merge a separation stored as greyscale into a CMYK composite */
1144 int
1145 image_merge_cmyk(IMAGE *img, IMAGE *layer, float cyan, float magenta,
1146 float yellow, float black)
1147 {
1148 int x;
1149 int y;
1150 unsigned char *img_row;
1151 unsigned char *layer_row;
1152 unsigned char *p;
1153 int img_topfirst;
1154 int layer_topfirst;
1155 unsigned int val;
1156 if ((img == NULL) || (img->image == NULL))
1157 return -1;
1158 if ((layer == NULL) || (layer->image == NULL))
1159 return -1;
1160 if ((img->format & DISPLAY_COLORS_MASK) != DISPLAY_COLORS_CMYK)
1161 return -1;
1162 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
1163 return -1;
1164 if ((img->format & DISPLAY_ENDIAN_MASK) != DISPLAY_BIGENDIAN)
1165 return -1;
1166 if ((layer->format & DISPLAY_COLORS_MASK) != DISPLAY_COLORS_GRAY)
1167 return -1;
1168 if ((layer->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
1169 return -1;
1170 if (img->width != layer->width)
1171 return -1;
1172 if (img->height != layer->height)
1173 return -1;
1174
1175 img_topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1176 layer_topfirst = ((layer->format & DISPLAY_FIRSTROW_MASK)
1177 == DISPLAY_TOPFIRST);
1178
1179 for (y=0; y<(int)img->height; y++) {
1180 img_row = img->image + img->raster *
1181 (img_topfirst ? y : ((int)img->height - y - 1));
1182 layer_row = layer->image + layer->raster *
1183 (layer_topfirst ? y : ((int)layer->height - y - 1));
1184 for (x=0; x<(int)img->width; x++) {
1185 val = layer_row[x];
1186 p = &img_row[x*4];
1187 p[0] = (unsigned char)min(255, p[0] + (255-val) * cyan);
1188 p[1] = (unsigned char)min(255, p[1] + (255-val) * magenta);
1189 p[2] = (unsigned char)min(255, p[2] + (255-val) * yellow);
1190 p[3] = (unsigned char)min(255, p[3] + (255-val) * black);
1191 }
1192 }
1193 return 0;
1194 }
1195
1196 /********************************************************/
1197
1198 typedef struct scale_pixels_s {
1199 unsigned int end; /* index of last pixel (full or partial) */
1200 unsigned int frac; /* fraction * 16 of last pixel */
1201 } scale_pixels_t;
1202
1203 /* Down scale an image.
1204 * This is intended to scale a hires resolution monochrome image
1205 * to a lower resolution greyscale image.
1206 * Input can be:
1207 * 1bit/pixel native or grey
1208 * 8bit/pixel grey,
1209 * 24 or 32bit/pixel RGB
1210 * 32bit/pixel CMYK.
1211 * If the input format is grey, the output format can be one of
1212 * 8bit/pixel grey,
1213 * 24 or 32bit/pixel RGB
1214 * 32bit/pixel CMYK.
1215 * If the input format is RGB or CMYK, the output format must match.
1216 * Row order must be the same for both images.
1217 */
1218 int image_down_scale(IMAGE *newimg, IMAGE *oldimg)
1219 {
1220 unsigned int i;
1221 unsigned int xi, xo, yi, yo;
1222 unsigned int end, last;
1223 scale_pixels_t *spx = NULL;
1224 scale_pixels_t *spy = NULL;
1225 unsigned int *sum1 = NULL; /* horizontal merge of one source row */
1226 unsigned int *sumn = NULL; /* merge of several rows */
1227 unsigned int frac;
1228 unsigned int val;
1229 unsigned int maxval;
1230 unsigned char *row_in;
1231 unsigned char *row_out;
1232 unsigned int mask;
1233 unsigned int byteval = 0;
1234 unsigned int width_in = oldimg->width;
1235 unsigned int height_in = oldimg->height;
1236 unsigned int width_out = newimg->width;
1237 unsigned int height_out = newimg->height;
1238 BOOL mono_wb = FALSE;
1239 BOOL mono_bw = FALSE;
1240 BOOL cmyk_in = FALSE;
1241 BOOL cmyk_out = FALSE;
1242 unsigned int ncomp_in = 0;
1243 unsigned int ncomp_out = 0;
1244 unsigned int ncomp_out_first = 0;
1245 unsigned int ncomp_out_last = 0;
1246
1247 /* Check if input image format is supported */
1248 switch (oldimg->format & DISPLAY_COLORS_MASK) {
1249 case DISPLAY_COLORS_NATIVE:
1250 switch (oldimg->format & DISPLAY_DEPTH_MASK) {
1251 case DISPLAY_DEPTH_1:
1252 ncomp_in = 1;
1253 mono_wb = TRUE;
1254 break;
1255 }
1256 break;
1257 case DISPLAY_COLORS_GRAY:
1258 switch (oldimg->format & DISPLAY_DEPTH_MASK) {
1259 case DISPLAY_DEPTH_1:
1260 ncomp_in = 1;
1261 mono_bw = TRUE;
1262 break;
1263 case DISPLAY_DEPTH_8:
1264 ncomp_in = 1;
1265 break;
1266 }
1267 break;
1268 case DISPLAY_COLORS_RGB:
1269 if ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1270 int alpha = (oldimg->format & DISPLAY_ALPHA_MASK);
1271 ncomp_in = 3;
1272 if ((alpha == DISPLAY_ALPHA_FIRST) ||
1273 (alpha == DISPLAY_UNUSED_FIRST))
1274 ncomp_in++;
1275 if ((alpha == DISPLAY_ALPHA_LAST) ||
1276 (alpha == DISPLAY_UNUSED_LAST))
1277 ncomp_in++;
1278 }
1279 break;
1280 case DISPLAY_COLORS_CMYK:
1281 if ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1282 ncomp_in = 4;
1283 cmyk_in = TRUE;
1284 }
1285 }
1286
1287 if (ncomp_in == 0)
1288 return -1;
1289
1290 /* Check if output image format is supported */
1291 switch (newimg->format & DISPLAY_COLORS_MASK) {
1292 case DISPLAY_COLORS_GRAY:
1293 switch (newimg->format & DISPLAY_DEPTH_MASK) {
1294 case DISPLAY_DEPTH_8:
1295 ncomp_out = 1;
1296 ncomp_out_last = ncomp_out;
1297 break;
1298 }
1299 break;
1300 case DISPLAY_COLORS_RGB:
1301 if ((newimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1302 int alpha = (newimg->format & DISPLAY_ALPHA_MASK);
1303 ncomp_out = 3;
1304 ncomp_out_first = 0;
1305 ncomp_out_last = ncomp_out;
1306 if (alpha == DISPLAY_ALPHA_FIRST) {
1307 ncomp_out++;
1308 ncomp_out_last++;
1309 }
1310 else if (alpha == DISPLAY_UNUSED_FIRST) {
1311 ncomp_out++;
1312 ncomp_out_first++;
1313 ncomp_out_last++;
1314 }
1315 if (alpha == DISPLAY_ALPHA_LAST) {
1316 ncomp_out++;
1317 ncomp_out_last++;
1318 }
1319 else if (alpha == DISPLAY_UNUSED_LAST) {
1320 ncomp_out++;
1321 }
1322 }
1323 break;
1324 case DISPLAY_COLORS_CMYK:
1325 if ((newimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1326 ncomp_out = 4;
1327 cmyk_out = TRUE;
1328 }
1329 }
1330
1331 if (ncomp_out == 0)
1332 return -1;
1333 if (ncomp_out < ncomp_in)
1334 return -1;
1335 if ((ncomp_out != ncomp_in) && (ncomp_in != 1))
1336 return -1;
1337 if (cmyk_out != cmyk_in)
1338 return -1;
1339
1340 if ((newimg->format && DISPLAY_FIRSTROW_MASK) !=
1341 (oldimg->format && DISPLAY_FIRSTROW_MASK))
1342 return -1;
1343
1344 if (width_out > width_in)
1345 width_out = width_in;
1346 if (height_out > height_in)
1347 height_out = height_in;
1348
1349 maxval = (int)(16 * width_in / width_out) *
1350 (int)(16 * height_in / height_out);
1351
1352 spy = (scale_pixels_t *)malloc(height_out * sizeof(scale_pixels_t));
1353 spx = (scale_pixels_t *)malloc(width_out * sizeof(scale_pixels_t));
1354 sum1 = (unsigned int *)malloc(width_out * ncomp_in * sizeof(unsigned int));
1355 sumn = (unsigned int *)malloc(width_out * ncomp_in * sizeof(unsigned int));
1356 if ((spy == NULL) || (spx == NULL) || (sum1 == NULL) || (sumn == NULL)) {
1357 if (spy != NULL)
1358 free(spy);
1359 if (spx != NULL)
1360 free(spx);
1361 if (sum1 != NULL)
1362 free(sum1);
1363 if (sumn == NULL)
1364 free(sumn);
1365 return -1;
1366 }
1367
1368 /* precalculate the integer pixel offsets and fractions */
1369 for (xo=0; xo<width_out; xo++) {
1370 last = (xo+1) * 16 * width_in / width_out;
1371 end = (last) & (~0xf);
1372 spx[xo].end= end>>4;
1373 spx[xo].frac = last - end;
1374 if (spx[xo].frac == 0) {
1375 spx[xo].end--;
1376 spx[xo].frac = 16;
1377 }
1378 }
1379 for (yo=0; yo<height_out; yo++) {
1380 last = (yo+1) * 16 * height_in / height_out;
1381 end = (last) & (~0xf);
1382 spy[yo].end= end>>4;
1383 spy[yo].frac = last - end;
1384 if (spy[yo].frac == 0) {
1385 spy[yo].end--;
1386 spy[yo].frac = 16;
1387 }
1388 }
1389 yo = 0;
1390 memset(sumn, 0, width_out * ncomp_in * sizeof(unsigned int));
1391 for (yi=0; yi<height_in; yi++) {
1392 xo = 0;
1393 for (i=0; i<ncomp_in; i++)
1394 sum1[xo*ncomp_in+i] = 0;
1395 row_in = oldimg->image + yi * oldimg->raster;
1396 if (mono_wb) {
1397 /* 1bit/pixel, 0 is white, 1 is black */
1398 mask = 0;
1399 end = spx[xo].end;
1400 for (xi=0; xi<width_in; xi++) {
1401 if ((mask >>= 1) == 0) {
1402 mask = 0x80;
1403 byteval = row_in[xi>>3];
1404 }
1405 val = (byteval & mask) ? 0 : 255;
1406 if (xi >= end) {
1407 /* last (possibly partial) pixel of group */
1408 sum1[xo] += val * (frac = spx[xo].frac);
1409 if (++xo < width_out)
1410 sum1[xo] = val * (16 - frac);
1411 end = spx[xo].end;
1412 }
1413 else
1414 sum1[xo] += val << 4;
1415 }
1416 }
1417 else if (mono_bw) {
1418 /* 0 is black, 1 is white */
1419 mask = 0;
1420 end = spx[xo].end;
1421 for (xi=0; xi<width_in; xi++) {
1422 if ((mask >>= 1) == 0) {
1423 mask = 0x80;
1424 byteval = row_in[xi>>3];
1425 }
1426 val = (byteval & mask) ? 255 : 0;
1427 if (xi >= end) {
1428 /* last (possibly partial) pixel of group */
1429 sum1[xo] += val * (frac = spx[xo].frac);
1430 if (++xo < width_out)
1431 sum1[xo] = val * (16 - frac);
1432 end = spx[xo].end;
1433 }
1434 else
1435 sum1[xo] += val << 4;
1436 }
1437 }
1438 else if (ncomp_in == 1) {
1439 /* 8bits/component grey */
1440 for (xi=0; xi<width_in; xi++) {
1441 val = row_in[xi];
1442 if (xi >= spx[xo].end) {
1443 /* last (possibly partial) pixel of group */
1444 sum1[xo] += val * (frac = spx[xo].frac);
1445 if (++xo < width_out)
1446 sum1[xo] = val * (16 - frac);
1447 }
1448 else
1449 sum1[xo] += val << 4;
1450 }
1451 }
1452 else if (ncomp_in >= 3) {
1453 /* 8bits/component RGB, BGR, xRGB, CMYK etc. */
1454 for (xi=0; xi<width_in; xi++) {
1455 for (i=0; i<ncomp_in; i++) {
1456 val = row_in[xi*ncomp_in+i];
1457 if (xi >= spx[xo].end) {
1458 /* last (possibly partial) pixel of group */
1459 frac = spx[xo].frac;
1460 sum1[xo*ncomp_in+i] += val * frac;
1461 if (xo+1 < width_out)
1462 sum1[(xo+1)*ncomp_in+i] = val * (16 - frac);
1463 }
1464 else
1465 sum1[xo*ncomp_in+i] += val << 4;
1466 }
1467 if (xi >= spx[xo].end)
1468 xo++;
1469 }
1470 }
1471 if (yi >= spy[yo].end) {
1472 frac = spy[yo].frac;
1473 /* add last partial row to sumn */
1474 for (xo=0; xo<width_out*ncomp_in; xo++)
1475 sumn[xo] += sum1[xo] * frac;
1476 /* write out merged row */
1477 row_out = newimg->image + yo * newimg->raster;
1478 for (xo=0; xo < width_out*ncomp_in; xo++) {
1479 val = sumn[xo] / maxval;
1480 if (val > 255)
1481 val = 255;
1482 if (ncomp_in == ncomp_out) {
1483 row_out[xo] = (unsigned char)val;
1484 }
1485 else {
1486 /* we are converting grey to colour */
1487 if (cmyk_out) {
1488 row_out[xo*ncomp_out+0] =
1489 row_out[xo*ncomp_out+1] =
1490 row_out[xo*ncomp_out+2] = (unsigned char)0;
1491 row_out[xo*ncomp_out+3] = (unsigned char)val;
1492
1493 }
1494 else {
1495 /* RGB */
1496 for (i=0; i<ncomp_out_first; i++)
1497 row_out[xo*ncomp_out+i] = (unsigned char)0;
1498 for (; i<ncomp_out_last; i++)
1499 row_out[xo*ncomp_out+i] = (unsigned char)val;
1500 for (; i<ncomp_out; i++)
1501 row_out[xo*ncomp_out+i] = (unsigned char)0;
1502 }
1503 }
1504 }
1505 /* Put first partial row in sumn */
1506 yo++;
1507 frac = 16 - frac;
1508 if (yo < height_out) {
1509 for (xo=0; xo<width_out*ncomp_in; xo++)
1510 sumn[xo] = sum1[xo] * frac;
1511 }
1512 }
1513 else {
1514 /* add whole row to sumn */
1515 for (xo=0; xo<width_out*ncomp_in; xo++)
1516 sumn[xo] += sum1[xo]*16;
1517 }
1518 }
1519
1520 free(spy);
1521 free(spx);
1522 free(sum1);
1523 free(sumn);
1524
1525 return 0;
1526 }
1527
1528
1529 /* Copy an image, resizing it if needed.
1530 * Currently only supports resizing down.
1531 */
1532 int
1533 image_copy_resize(IMAGE *newimg, IMAGE *oldimg, unsigned int format,
1534 float xddpi, float yddpi, float xrdpi, float yrdpi)
1535 {
1536 if ((xddpi != xrdpi) && (yddpi != yrdpi) &&
1537 (xddpi <= xrdpi) && (yddpi <= yrdpi)) {
1538 int temp_format =
1539 DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1540 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; /* 24-bit BGR */
1541 int grey_format =
1542 DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1543 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; /* 8-bit grey */
1544 /* Down scale image */
1545 memset(newimg, 0, sizeof(IMAGE));
1546 newimg->width = (unsigned int)(oldimg->width * xddpi / xrdpi + 0.5);
1547 newimg->height = (unsigned int)(oldimg->height * yddpi / yrdpi + 0.5);
1548 if ((((format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_NATIVE) ||
1549 ((format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)) &&
1550 (((format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)))
1551 /* need to convert up to 8bit/pixel */
1552 newimg->format = image_platform_format(
1553 (format & ~DISPLAY_COLORS_MASK & ~DISPLAY_DEPTH_MASK)
1554 | DISPLAY_COLORS_GRAY | DISPLAY_DEPTH_8);
1555 else
1556 newimg->format = format;
1557 newimg->raster =
1558 (((image_depth(newimg) * newimg->width + 7) >> 3) + 3) & ~3;
1559 /* Try converting as is */
1560 newimg->image = malloc(newimg->raster * newimg->height);
1561 if (newimg->image == NULL)
1562 return -1;
1563 if (image_down_scale(newimg, oldimg) != 0) {
1564 /* Conversion failed, so input format probably not OK.
1565 * Convert to RGB and try again.
1566 * Ignore requested format.
1567 */
1568 IMAGE tempimg;
1569 free(newimg->image);
1570 newimg->image = NULL;
1571 memset(&tempimg, 0, sizeof(tempimg));
1572 tempimg.width = oldimg->width;
1573 tempimg.height = oldimg->height;
1574 if (((((oldimg->format & DISPLAY_COLORS_MASK)
1575 == DISPLAY_COLORS_NATIVE) ||
1576 ((oldimg->format & DISPLAY_COLORS_MASK)
1577 == DISPLAY_COLORS_GRAY)) &&
1578 ((oldimg->format & DISPLAY_DEPTH_MASK)
1579 == DISPLAY_DEPTH_1))
1580 ||
1581 (((oldimg->format & DISPLAY_COLORS_MASK)
1582 == DISPLAY_COLORS_GRAY) &&
1583 ((oldimg->format & DISPLAY_DEPTH_MASK)
1584 == DISPLAY_DEPTH_8)))
1585 tempimg.format = image_platform_format(grey_format);
1586 else
1587 tempimg.format = image_platform_format(temp_format);
1588 tempimg.raster =
1589 (((image_depth(&tempimg) * tempimg.width + 7) >> 3) + 3) & ~3;
1590 tempimg.image = malloc(tempimg.raster * tempimg.height);
1591 if (tempimg.image == NULL) {
1592 return -1;
1593 }
1594 newimg->format = tempimg.format;
1595 newimg->raster =
1596 (((image_depth(newimg) * newimg->width + 7) >> 3) + 3) & ~3;
1597 newimg->image = malloc(newimg->raster * newimg->height);
1598 if (newimg->image == NULL) {
1599 free(tempimg.image);
1600 return -1;
1601 }
1602 image_copy(&tempimg, oldimg, tempimg.format);
1603 if (image_down_scale(newimg, &tempimg) != 0) {
1604 /* nothing worked */
1605 free(tempimg.image);
1606 free(newimg->image);
1607 newimg->image = NULL;
1608 /* fall through to copy unmodified */
1609 }
1610 else {
1611 free(tempimg.image);
1612 image_platform_init(newimg);
1613 return 0; /* succesfully resized */
1614 }
1615 }
1616 else {
1617 image_platform_init(newimg);
1618 return 0; /* succesfully resized */
1619 }
1620 }
1621
1622 /* Not resized, or failed resize, so just copy image */
1623 return image_copy(newimg, oldimg, format);
1624 }
1625
1626
1627 /********************************************************/
1628
1629
1630 /* ASCII85Encode to a character line.
1631 * Returns the number of characters produced, which can be
1632 * no more than count+1
1633 */
1634 static int
1635 a85write(char *line, unsigned char *buf, int count)
1636 {
1637 int i;
1638 unsigned long value;
1639 unsigned char abuf[5];
1640 if (count == 0)
1641 return 0;
1642 if (count < 4) {
1643 for (i = count; i < 4; i++)
1644 buf[i] = 0;
1645 }
1646 if ((count == 4) &&
1647 (buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0) && (buf[3] == 0)) {
1648 line[0] = 'z';
1649 return 1;
1650 }
1651 value = ((unsigned int)(buf[0])<<24) +
1652 ((unsigned int)(buf[1])<<16) +
1653 ((unsigned int)(buf[2])<<8) +
1654 (unsigned int)(buf[3]);
1655 abuf[0] = (unsigned char)(value / (85L*85*85*85));
1656 value -= abuf[0] * (85L*85*85*85);
1657 abuf[1] = (unsigned char)(value / (85L*85*85));
1658 value -= abuf[1] * (85L*85*85);
1659 abuf[2] = (unsigned char)(value / (85L*85));
1660 value -= abuf[2] * (85L*85);
1661 abuf[3] = (unsigned char)(value / (85L));
1662 value -= abuf[3] * (85L);
1663 abuf[4] = (unsigned char)(value);
1664 for (i=0; i<count+1; i++)
1665 line[i] = (char)(abuf[i]+'!');
1666 return count+1;
1667 }
1668
1669 /* Simple byte RLE, known as PackBits on the Macintosh and
1670 * RunLengthEncode in PostScript.
1671 * The output buffer is comp.
1672 * The input buffer is raw, containing length bytes.
1673 * The output buffer must be at least length*129/128 bytes long.
1674 */
1675 int
1676 packbits(BYTE *comp, BYTE *raw, int length)
1677 {
1678 BYTE *cp;
1679 int literal = 0; /* number of literal bytes */
1680 int prevlit = 0; /* length of previous literal */
1681 int repeat = 0; /* number of repeat bytes - 1*/
1682 int start = 0; /* start of block to be coded */
1683 BYTE previous = raw[0];
1684 int i, j;
1685
1686 cp = comp;
1687 for (i=0; i<length; i++) {
1688 if (literal == 128) {
1689 /* code now */
1690 *cp++ = (BYTE)(literal-1);
1691 for (j=0; j<literal; j++)
1692 *cp++ = (BYTE)raw[start+j];
1693 prevlit = 0; /* because we can't add to it */
1694 literal = 0;
1695 /* repeat = 0; */ /* implicit */
1696 start = i;
1697 previous = raw[i];
1698 }
1699 if (repeat == 128) {
1700 /* write out repeat block */
1701 *cp++ = (BYTE)-127; /* repeat count 128 */
1702 *cp++ = previous;
1703 repeat = 0;
1704 literal = 0;
1705 start = i;
1706 prevlit = 0;
1707 previous = raw[i];
1708 }
1709 if (raw[i] == previous) {
1710 if (literal == 1) {
1711 /* replace by repeat */
1712 repeat = 1;
1713 literal = 0;
1714 }
1715 else if (literal) {
1716 /* write out existing literal */
1717 literal--; /* remove repeat byte from literal */
1718 *cp++ = (BYTE)(literal-1);
1719 for (j=0; j<literal; j++)
1720 *cp++ = raw[start+j];
1721 if (literal < 126)
1722 prevlit = literal;
1723 else
1724 prevlit = 0; /* we won't be able to add to it */
1725 /* repeat = 0; */ /* implicit */
1726 start = i-1;
1727 repeat = 1;
1728 literal = 0;
1729 }
1730 repeat++;
1731 }
1732 else {
1733 /* doesn't match previous byte */
1734 if (repeat) {
1735 /* write out repeat block, or merge with literal */
1736 if (repeat == 1) {
1737 /* repeats must be 2 bytes or more, so code as literal */
1738 literal = repeat;
1739 repeat = 0;
1740 } else if (repeat == 2) { /* 2 byte repeat */
1741 /* code 2 byte repeat as repeat */
1742 /* except when preceeded by literal */
1743 if ( (prevlit) && (prevlit < 126) ) {
1744 /* previous literal and room to combine */
1745 start -= prevlit; /* continue previous literal */
1746 cp -= prevlit+1;
1747 literal = prevlit + 2;
1748 prevlit = 0;
1749 repeat = 0;
1750 }
1751 else {
1752 /* code as repeat */
1753 *cp++ = (BYTE)(-repeat+1);
1754 *cp++ = previous;
1755 start = i;
1756 prevlit = 0;
1757 /* literal = 0; */ /* implicit */
1758 repeat = 0;
1759 }
1760 /* literals will be coded later */
1761 }
1762 else {
1763 /* repeat of 3 or more bytes */
1764 *cp++ = (BYTE)(-repeat+1);
1765 *cp++ = previous;
1766 start = i;
1767 repeat = 0;
1768 prevlit = 0;
1769 }
1770 }
1771 literal++;
1772 }
1773 previous = raw[i];
1774 }
1775 if (repeat == 1) {
1776 /* can't code repeat 1, use literal instead */
1777 literal = 1;
1778 repeat = 0;
1779 }
1780 if (literal) {
1781 /* code left over literal */
1782 *cp++ = (BYTE)(literal-1);
1783 for (j=0; j<literal; j++)
1784 *cp++ = raw[start+j];
1785 }
1786 if (repeat) {
1787 /* code left over repeat */
1788 *cp++ = (BYTE)(-repeat+1);
1789 *cp++ = previous;
1790 }
1791 return (int)(cp - comp); /* number of code bytes */
1792 }
1793
1794
1795 /* Write an image as an EPS file.
1796 * Currently we support 8bits/component RGB or CMYK without conversion,
1797 * 1, 4 or 8 bits/pixel grey without conversion,
1798 * 1 bit native without conversion,
1799 * and a number of other formats by conversion to 24RGB.
1800 * Output can be ASCII85 or ASCIIHex encoded, and can be
1801 * compressed with RunLengthEncode.
1802 */
1803 int
1804 image_to_eps(GFile *f, IMAGE *img, int llx, int lly, int urx, int ury,
1805 float fllx, float flly, float furx, float fury, int use_a85, int compress)
1806 {
1807 int x, y;
1808 int topfirst;
1809 int bigendian;
1810 int hires_bbox_valid = 1;
1811 unsigned char *row;
1812 int i;
1813 int ncomp; /* number of components per source pixel */
1814 int count = 0;
1815 const char hex[] = "0123456789abcdef";
1816 unsigned char *packin;
1817 unsigned char *packout;
1818 int packin_count;
1819 int packout_count;
1820 int packout_len;
1821 int separate = 0; /* Write components separately */
1822 int depth;
1823 int compwidth; /* width of one row of one component in bytes */
1824 BOOL convert = FALSE; /* convert to RGB24 */
1825 BOOL invert = FALSE; /* black=0 for FALSE, black=1 for TRUE */
1826 unsigned char *convert_row = NULL;
1827 char buf[MAXSTR];
1828 lzw_state_t *lzw = NULL;
1829
1830 if ((fllx >= furx) || (flly >= fury))
1831 hires_bbox_valid = 0;
1832
1833 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1834 bigendian = ((img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN);
1835
1836 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) {
1837 depth = 1;
1838 compwidth = (img->width + 7) >> 3;
1839 }
1840 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) {
1841 depth = 4;
1842 compwidth = (img->width + 1) >> 1;
1843 }
1844 else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1845 depth = 8;
1846 compwidth = img->width;
1847 }
1848 else
1849 return -1;
1850
1851
1852 if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_CMYK)
1853 ncomp = 4;
1854 else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_RGB) {
1855 ncomp = 3;
1856 if ((img->format & DISPLAY_ALPHA_MASK) != DISPLAY_ALPHA_NONE) {
1857 convert = TRUE;
1858 compwidth = img->width;
1859 bigendian = TRUE; /* Convert to RGB, not BGR */
1860 }
1861 }
1862 else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)
1863 ncomp = 1;
1864 else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_NATIVE) {
1865 if (depth == 1) {
1866 ncomp = 1;
1867 invert = TRUE;
1868 }
1869 else {
1870 ncomp = 3;
1871 compwidth = img->width;
1872 convert = TRUE;
1873 bigendian = TRUE; /* Convert to RGB, not BGR */
1874 }
1875 }
1876 else
1877 return -1;
1878
1879 packin = (unsigned char *)malloc(compwidth * ncomp);
1880 if (packin == NULL)
1881 return -1;
1882 packout_len = compwidth * ncomp * 5 / 4 + 4;
1883 packout = (unsigned char *)malloc(packout_len);
1884 if (packout == NULL) {
1885 free(packin);
1886 return -1;
1887 }
1888 if (convert) {
1889 convert_row = (unsigned char *)malloc(compwidth * ncomp);
1890 if (convert_row == NULL) {
1891 free(packin);
1892 free(packout);
1893 return -1;
1894 }
1895 }
1896 if (compress == IMAGE_COMPRESS_LZW) {
1897 lzw = lzw_new();
1898 if (lzw == (lzw_state_t *)NULL) {
1899 free(packin);
1900 free(packout);
1901 if (convert_row)
1902 free(convert_row);
1903 return -1;
1904 }
1905 }
1906
1907 gfile_puts(f, "%!PS-Adobe-3.0 EPSF-3.0\n");
1908 snprintf(buf, sizeof(buf)-1,
1909 "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
1910 gfile_puts(f, buf);
1911 if (hires_bbox_valid) {
1912 snprintf(buf, sizeof(buf)-1, "%%%%HiResBoundingBox: %g %g %g %g\n",
1913 fllx, flly, furx, fury);
1914 gfile_puts(f, buf);
1915 }
1916 gfile_puts(f, "%%Pages: 1\n");
1917 gfile_puts(f, "%%EndComments\n");
1918 gfile_puts(f, "%%Page: 1 1\n");
1919 gfile_puts(f, "gsave\n");
1920 if (hires_bbox_valid) {
1921 snprintf(buf, sizeof(buf)-1, "%g %g translate\n", fllx, flly);
1922 gfile_puts(f, buf);
1923 snprintf(buf, sizeof(buf)-1, "%g %g scale\n", furx-fllx, fury-flly);
1924 gfile_puts(f, buf);
1925 }
1926 else {
1927 snprintf(buf, sizeof(buf)-1, "%d %d translate\n", llx, lly);
1928 gfile_puts(f, buf);
1929 snprintf(buf, sizeof(buf)-1, "%d %d scale\n", urx - llx, ury - lly);
1930 gfile_puts(f, buf);
1931 }
1932 if (ncomp == 1)
1933 gfile_puts(f, "/DeviceGray setcolorspace\n");
1934 else if (ncomp == 3)
1935 gfile_puts(f, "/DeviceRGB setcolorspace\n");
1936 else if (ncomp == 4)
1937 gfile_puts(f, "/DeviceCMYK setcolorspace\n");
1938 if ((ncomp > 1) && (compress != IMAGE_COMPRESS_NONE)) {
1939 /* Include as RRRRGGGGBBBB not RGBRGBRGBRGB
1940 * (or CCCCMMMMYYYYKKKK not CMYKCMYKCMYKCMYK)
1941 * Since this compresses with RLE better.
1942 */
1943 separate = 1;
1944 }
1945 if (separate) {
1946 /* Include as RRGGBB not RGBRGB (or CCMMYYKK not CMYKCMYK) */
1947 /* Since this compresses with RLE better */
1948 if (use_a85)
1949 gfile_puts(f, "/infile currentfile /ASCII85Decode filter");
1950 else
1951 gfile_puts(f, "/infile currentfile /ASCIIHexDecode filter");
1952 if (compress == IMAGE_COMPRESS_LZW)
1953 gfile_puts(f, " /LZWDecode filter");
1954 else if (compress == IMAGE_COMPRESS_RLE)
1955 gfile_puts(f, " /RunLengthDecode filter");
1956 gfile_puts(f, " def\n");
1957 for (i=0; i<ncomp; i++) {
1958 snprintf(buf, sizeof(buf)-1,
1959 "/str%d %d string def\n", i, img->width);
1960 gfile_puts(f, buf);
1961 }
1962 }
1963 gfile_puts(f, "<<\n /ImageType 1\n");
1964 snprintf(buf, sizeof(buf)-1, " /Width %d\n", img->width);
1965 gfile_puts(f, buf);
1966 snprintf(buf, sizeof(buf)-1, " /Height %d\n", img->height);
1967 gfile_puts(f, buf);
1968 snprintf(buf, sizeof(buf)-1, " /BitsPerComponent %d\n", depth);
1969 gfile_puts(f, buf);
1970 gfile_puts(f, " /Decode [ ");
1971 for (i=0; i<ncomp; i++) {
1972 if (invert)
1973 gfile_puts(f, "1 0 ");
1974 else
1975 gfile_puts(f, "0 1 ");
1976 }
1977 gfile_puts(f, "]\n");
1978 snprintf(buf, sizeof(buf)-1, " /ImageMatrix [%d 0 0 %d 0 %d]\n",
1979 img->width, -(int)img->height, img->height);
1980 gfile_puts(f, buf);
1981 if (separate) {
1982 gfile_puts(f, " /MultipleDataSources true\n");
1983 gfile_puts(f, " /DataSource [\n");
1984 for (i=0; i<ncomp; i++) {
1985 snprintf(buf, sizeof(buf)-1,
1986 " {infile str%d readstring pop}\n", i);
1987 gfile_puts(f, buf);
1988 }
1989 gfile_puts(f, " ]\n");
1990 }
1991 else {
1992 if (use_a85)
1993 gfile_puts(f, " /DataSource currentfile /ASCII85Decode filter\n");
1994 else
1995 gfile_puts(f, " /DataSource currentfile /ASCIIHexDecode filter\n");
1996 if (compress == IMAGE_COMPRESS_LZW)
1997 gfile_puts(f, " /LZWDecode filter\n");
1998 else if (compress == IMAGE_COMPRESS_RLE)
1999 gfile_puts(f, " /RunLengthDecode filter\n");
2000 }
2001 gfile_puts(f, ">>\nimage\n");
2002 count = 0;
2003 packout_count = 0;
2004 for (y=0; y<(int)img->height; y++) {
2005 row = img->image + img->raster *
2006 (topfirst != 0 ? y : ((int)img->height - y - 1));
2007 if (convert) {
2008 image_to_24RGB(img, convert_row, row);
2009 row = convert_row;
2010 }
2011 packin_count = 0;
2012 if (separate) {
2013 if (bigendian) {
2014 for (i=0; i<ncomp; i++)
2015 for (x=0; x<compwidth; x++)
2016 packin[packin_count++] = row[x*ncomp+i];
2017 }
2018 else {
2019 for (i=ncomp-1; i>=0; i--)
2020 for (x=0; x<compwidth; x++)
2021 packin[packin_count++] = row[x*ncomp+i];
2022 }
2023 }
2024 else {
2025 for (x=0; x<compwidth; x++) {
2026 if (bigendian) {
2027 for (i=0; i<ncomp; i++)
2028 packin[packin_count++] = row[x*ncomp+i];
2029 }
2030 else {
2031 for (i=ncomp-1; i>=0; i--)
2032 packin[packin_count++] = row[x*ncomp+i];
2033 }
2034 }
2035 }
2036 if (compress == IMAGE_COMPRESS_LZW) {
2037 int inlen = packin_count;
2038 int outlen = packout_len - packout_count;
2039 lzw_compress(lzw, packin, &inlen, packout+packout_count, &outlen);
2040 packout_count += outlen;
2041 if (y == (int)img->height-1) {
2042 /* This is the last row */
2043 /* Flush and EOD */
2044 inlen = 0; /* EOD */
2045 outlen = packout_len - packout_count;
2046 lzw_compress(lzw, packin, &inlen, packout+packout_count,
2047 &outlen);
2048 packout_count += outlen;
2049 }
2050 }
2051 else if (compress == IMAGE_COMPRESS_RLE) {
2052 packout_count +=
2053 packbits(packout+packout_count, packin, packin_count);
2054 }
2055 else {
2056 memcpy(packout+packout_count, packin, packin_count);
2057 packout_count += packin_count;
2058 }
2059 for (i=0; i<packout_count; i++) {
2060 if (use_a85) {
2061 if (packout_count-i < 4)
2062 break;
2063 else
2064 count += a85write(buf+count, packout+i, 4);
2065 i += 3;
2066 }
2067 else {
2068 buf[count++] = hex[(packout[i]>>4) & 0xf];
2069 buf[count++] = hex[packout[i] & 0xf];
2070 }
2071 if (count >= 70) {
2072 buf[count++] = '\n';
2073 gfile_write(f, buf, count);
2074 count = 0;
2075 }
2076
2077 }
2078 if (packout_count-i > 0)
2079 memmove(packout, packout+i, packout_count-i);
2080 packout_count -= i;
2081 }
2082 if (use_a85) {
2083 if (packout_count)
2084 count += a85write(buf+count, packout, packout_count);
2085 buf[count++] = '~';
2086 buf[count++] = '>';
2087 buf[count++] = '\n';
2088 }
2089 else {
2090 buf[count++] = '>';
2091 buf[count++] = '\n';
2092 }
2093 gfile_write(f, buf, count);
2094 gfile_puts(f, "grestore\n");
2095 gfile_puts(f, "showpage\n");
2096 gfile_puts(f, "%%Trailer\n");
2097 gfile_puts(f, "%%EOF\n");
2098 if (lzw)
2099 lzw_free(lzw);
2100 if (convert)
2101 free(convert_row);
2102 free(packin);
2103 free(packout);
2104 return 0;
2105 }
2106
2107 int
2108 image_to_epsfile(IMAGE *img, LPCTSTR filename, float xdpi, float ydpi)
2109 {
2110 GFile *f;
2111 int code = 0;
2112 int width = (int)(img->width * 72.0 / xdpi);
2113 int height = (int)(img->height * 72.0 / ydpi);
2114
2115
2116 if ((img == NULL) || (img->image == NULL))
2117 return -1;
2118
2119 f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate);
2120 if (f == NULL)
2121 return -1;
2122
2123 code = image_to_eps(f, img, 0, 0, width, height,
2124 0.0, 0.0, (float)width, (float)height,
2125 TRUE, IMAGE_COMPRESS_LZW);
2126
2127 gfile_close(f);
2128 return code;
2129 }
2130
2131
2132 /********************************************************/