"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: cbmp.c,v 1.17 2005/06/10 09:39:24 ghostgum Exp $ */
17 /* BMP and PBM to IMAGE conversion */
18 /* IMAGE to BMP, PBM, TIFF, PICT conversion */
19
20 /* These functions convert between a BMP or PBM file
21 * and an IMAGE in the format as used by the Ghostscript
22 * display device.
23 */
24
25 #include "common.h"
26 #include "gdevdsp.h"
27 #include "cbmp.h"
28 #include "cimg.h"
29 #include "cps.h" /* for ps_fgets */
30 #include <time.h>
31
32 #ifdef HAVE_LIBPNG
33 #include "png.h"
34 #endif
35
36 /* local prototypes */
37 static int read_pbm_bits(unsigned char *pbitmap,
38 unsigned int width, unsigned int height, GFile *f);
39 static int read_pgnm_bytes(unsigned char *pbitmap,
40 unsigned int length, GFile *f);
41 static int image_bmp2init(IMAGE *img, BITMAP2 *bmp2);
42 static void shift_bits(unsigned char *bits, int bwidth, int offset);
43 static void write_bigendian_dword(DWORD val, GFile *f);
44 static void write_bigendian_word(WORD val, GFile *f);
45
46 static const char szGSviewName[] = "GSview";
47
48 /* read/write word and dword in a portable way */
49
50 DWORD
51 get_dword(const unsigned char *buf)
52 {
53 DWORD dw;
54 dw = (DWORD)buf[0];
55 dw += ((DWORD)buf[1])<<8;
56 dw += ((DWORD)buf[2])<<16;
57 dw += ((DWORD)buf[3])<<24;
58 return dw;
59 }
60
61 WORD
62 get_word(const unsigned char *buf)
63 {
64 WORD w;
65 w = (WORD)buf[0];
66 w |= (WORD)(buf[1]<<8);
67 return w;
68 }
69
70 /* write DWORD as DWORD */
71 void
72 write_dword(DWORD val, GFile *f)
73 {
74 unsigned char dw[4];
75 dw[0] = (unsigned char)( val & 0xff);
76 dw[1] = (unsigned char)((val>>8) & 0xff);
77 dw[2] = (unsigned char)((val>>16) & 0xff);
78 dw[3] = (unsigned char)((val>>24) & 0xff);
79 gfile_write(f, &dw, 4);
80 }
81
82 /* write WORD as DWORD */
83 void
84 write_word_as_dword(WORD val, GFile *f)
85 {
86 unsigned char dw[4];
87 dw[0] = (unsigned char)( val & 0xff);
88 dw[1] = (unsigned char)((val>>8) & 0xff);
89 dw[2] = '\0';
90 dw[3] = '\0';
91 gfile_write(f, &dw, 4);
92 }
93
94 /* write WORD as WORD */
95 void
96 write_word(WORD val, GFile *f)
97 {
98 unsigned char w[2];
99 w[0] = (unsigned char)( val & 0xff);
100 w[1] = (unsigned char)((val>>8) & 0xff);
101 gfile_write(f, &w, 2);
102 }
103
104 /* write bigendian DWORD */
105 static void
106 write_bigendian_dword(DWORD val, GFile *f)
107 {
108 unsigned char dw[4];
109 dw[3] = (unsigned char)( val & 0xff);
110 dw[2] = (unsigned char)((val>>8) & 0xff);
111 dw[1] = (unsigned char)((val>>16) & 0xff);
112 dw[0] = (unsigned char)((val>>24) & 0xff);
113 gfile_write(f, &dw, 4);
114 }
115
116 /* write bigendian WORD */
117 static void
118 write_bigendian_word(WORD val, GFile *f)
119 {
120 unsigned char w[2];
121 w[1] = (unsigned char)( val & 0xff);
122 w[0] = (unsigned char)((val>>8) & 0xff);
123 gfile_write(f, &w, 2);
124 }
125
126 /* shift preview by offset bits to the left */
127 /* width is in bytes */
128 /* fill exposed bits with 1's */
129 static void
130 shift_bits(unsigned char *bits, int bwidth, int offset)
131 {
132 int bitoffset;
133 int byteoffset;
134 int newwidth;
135 int shifter;
136 int i;
137 if (offset == 0)
138 return;
139 byteoffset = offset / 8;
140 newwidth = bwidth - byteoffset;
141 /* first remove byte offset */
142 memmove(bits, bits+byteoffset, newwidth);
143 memset(bits+newwidth, 0xff, bwidth-newwidth);
144 /* next remove bit offset */
145 bitoffset = offset - byteoffset*8;
146 if (bitoffset==0)
147 return;
148 bitoffset = 8 - bitoffset;
149 for (i=0; i<newwidth; i++) {
150 shifter = bits[i] << 8;
151 if (i==newwidth-1)
152 shifter += 0xff; /* can't access bits[bwidth] */
153 else
154 shifter += bits[i+1];
155 bits[i] = (unsigned char)(shifter>>bitoffset);
156 }
157 }
158
159
160 /* Load a Windows bitmap and return an image.
161 * Because we are forcing this into a format that
162 * could be written by the Ghostscript "display"
163 * device, we can't write palette images since
164 * the palette in the display device is fixed.
165 * We convert 4 and 8-bit palette bitmaps to
166 * 24-bit colour.
167 */
168 IMAGE *
169 bmpfile_to_image(LPCTSTR filename)
170 {
171 GFile *f = gfile_open(filename, gfile_modeRead);
172 IMAGE *img;
173 unsigned char bmf_buf[BITMAPFILE_LENGTH];
174 unsigned char *pbitmap;
175 unsigned int length;
176 unsigned int count;
177 BITMAPFILE bmf;
178 if (f == (GFile *)NULL)
179 return NULL;
180 gfile_read(f, bmf_buf, sizeof(bmf_buf));
181 if ((bmf_buf[0] != 'B') || (bmf_buf[1] != 'M')) {
182 /* Not a Windows bitmap */
183 gfile_close(f);
184 return NULL;
185 }
186 bmf.bfType = get_word(bmf_buf);
187 bmf.bfSize = get_dword(bmf_buf+2);
188 bmf.bfReserved1 = get_word(bmf_buf+6);
189 bmf.bfReserved1 = get_word(bmf_buf+8);
190 bmf.bfOffBits = get_dword(bmf_buf+10);
191 length = bmf.bfSize - BITMAPFILE_LENGTH;
192
193 pbitmap = (unsigned char *)malloc(length);
194 if (pbitmap == NULL) {
195 gfile_close(f);
196 return NULL;
197 }
198
199 count = (int)gfile_read(f, pbitmap, length);
200 gfile_close(f);
201
202 img = bmp_to_image(pbitmap, length);
203 free(pbitmap);
204
205 return img;
206 }
207
208 static const unsigned char clr555[] = {
209 0x1f, 0x00, 0x00, 0x00, /* blue */
210 0xe0, 0x03, 0x00, 0x00, /* green */
211 0x00, 0x7c, 0x00, 0x00 /* red */
212 };
213 static const unsigned char clr565[] = {
214 0x1f, 0x00, 0x00, 0x00, /* blue */
215 0xe0, 0x07, 0x00, 0x00, /* green */
216 0x00, 0xf8, 0x00, 0x00 /* red */
217 };
218
219 IMAGE *
220 bmp_to_image(unsigned char *pbitmap, unsigned int length)
221 {
222 BITMAP2 bmp2;
223 RGB4 colour[256];
224 int depth;
225 int palcount;
226 int pallength;
227 int bytewidth;
228 BOOL convert;
229 int i;
230 int x, y;
231 IMAGE img;
232 IMAGE *pimage;
233 unsigned char *bits;
234 unsigned char *dest;
235 memset(&img, 0, sizeof(img));
236 if (length < BITMAP2_LENGTH)
237 return NULL;
238 /* Read the BITMAPINFOHEADER in a portable way. */
239 bmp2.biSize = get_dword(pbitmap);
240 pbitmap += 4;
241 if (bmp2.biSize < BITMAP2_LENGTH)
242 return NULL; /* we don't read OS/2 BMP format */
243 bmp2.biWidth = get_dword(pbitmap);
244 pbitmap += 4;
245 bmp2.biHeight = get_dword(pbitmap);
246 pbitmap += 4;
247 bmp2.biPlanes = get_word(pbitmap);
248 pbitmap += 2;
249 bmp2.biBitCount = get_word(pbitmap);
250 pbitmap += 2;
251 bmp2.biCompression = get_dword(pbitmap);
252 pbitmap += 4;
253 bmp2.biSizeImage = get_dword(pbitmap);
254 pbitmap += 4;
255 bmp2.biXPelsPerMeter = get_dword(pbitmap);
256 pbitmap += 4;
257 bmp2.biYPelsPerMeter = get_dword(pbitmap);
258 pbitmap += 4;
259 bmp2.biClrUsed = get_dword(pbitmap);
260 pbitmap += 4;
261 bmp2.biClrImportant = get_dword(pbitmap);
262 pbitmap += 4;
263 pbitmap += bmp2.biSize - BITMAP2_LENGTH;
264
265 /* Calculate the raster size, depth, palette length etc. */
266 depth = bmp2.biPlanes * bmp2.biBitCount;
267 bytewidth = ((bmp2.biWidth * depth + 31) & ~31) >> 3;
268 palcount = 0;
269 if (depth <= 8)
270 palcount = (bmp2.biClrUsed != 0) ?
271 (int)bmp2.biClrUsed : (int)(1 << depth);
272 pallength = 0;
273 if ((depth == 16) || (depth == 32)) {
274 if (bmp2.biCompression == BI_BITFIELDS)
275 pallength = 12;
276 }
277 else
278 pallength = palcount * RGB4_LENGTH;
279 for (i=0; i<palcount; i++) {
280 colour[i].rgbBlue = pbitmap[i*4+RGB4_BLUE];
281 colour[i].rgbGreen = pbitmap[i*4+RGB4_GREEN];
282 colour[i].rgbRed = pbitmap[i*4+RGB4_RED];
283 }
284
285 if (length < bmp2.biSize + pallength + bmp2.biHeight * bytewidth)
286 return NULL;
287
288 /* Now find out which format to use */
289 /* Default is 24-bit BGR */
290 img.width = bmp2.biWidth;
291 img.height = bmp2.biHeight;
292 img.raster = img.width * 3;
293 img.format = DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE |
294 DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
295 convert = FALSE;
296
297 /* We will save it as either 1-bit/pixel, 8-bit/pixel grey,
298 * or 24-bit/pixel RGB.
299 */
300 if (depth == 1) {
301 if ((colour[0].rgbBlue == 0) &&
302 (colour[0].rgbGreen == 0) &&
303 (colour[0].rgbRed == 0) &&
304 (colour[1].rgbBlue == 0xff) &&
305 (colour[1].rgbGreen == 0xff) &&
306 (colour[1].rgbRed == 0xff)) {
307 /* black and white */
308 img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE |
309 DISPLAY_DEPTH_1 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
310 img.raster = (img.width + 7) >> 3;
311 }
312 else if ((colour[0].rgbBlue == 0xff) &&
313 (colour[0].rgbGreen == 0xff) &&
314 (colour[0].rgbRed == 0xff) &&
315 (colour[1].rgbBlue == 0) &&
316 (colour[1].rgbGreen == 0) &&
317 (colour[1].rgbRed == 0)) {
318 /* black and white */
319 img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
320 DISPLAY_DEPTH_1 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
321 img.raster = (img.width + 7) >> 3;
322 }
323 else if ( (colour[0].rgbBlue == colour[0].rgbGreen) &&
324 (colour[0].rgbRed == colour[0].rgbGreen) &&
325 (colour[1].rgbBlue == colour[1].rgbGreen) &&
326 (colour[1].rgbRed == colour[1].rgbGreen)) {
327 /* convert to greyscale */
328 img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE |
329 DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
330 img.raster = img.width;
331 convert = TRUE;
332 }
333 else
334 /* convert to colour */
335 convert = TRUE;
336 }
337 else if ((depth == 4) || (depth == 8)) {
338 BOOL grey = TRUE;
339 for (i=0; i<palcount; i++) {
340 if ((colour[i].rgbBlue != colour[i].rgbGreen) ||
341 (colour[i].rgbRed != colour[i].rgbGreen))
342 grey = FALSE;
343 }
344 if (grey) {
345 img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE |
346 DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
347 img.raster = img.width;
348 }
349 convert = TRUE;
350
351 }
352 else if (depth == 16) {
353 if (pallength == 0) {
354 img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
355 DISPLAY_DEPTH_16 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST |
356 DISPLAY_NATIVE_555;
357 img.raster = img.width * 2;
358 }
359 else if ((pallength == 12) &&
360 (memcmp(pbitmap, clr555, sizeof(clr555)) == 0)) {
361 img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
362 DISPLAY_DEPTH_16 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST |
363 DISPLAY_NATIVE_555;
364 img.raster = img.width * 2;
365 }
366 else if ((pallength == 12) &&
367 (memcmp(pbitmap, clr565, sizeof(clr565)) == 0)) {
368 img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
369 DISPLAY_DEPTH_16 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST |
370 DISPLAY_NATIVE_565;
371 img.raster = img.width * 2;
372 }
373 else
374 return NULL; /* unrecognised format */
375 }
376 else if (depth == 24) {
377 /* already in correct format */
378 }
379 else if (depth == 32) {
380 unsigned char clr888[] = {
381 0xff, 0x00, 0x00, 0x00, /* blue */
382 0x00, 0xff, 0x00, 0x00, /* green */
383 0x00, 0x00, 0xff, 0x00 /* red */
384 };
385 if ( (pallength == 0) ||
386 ((pallength == 12) &&
387 (memcmp(pbitmap, clr888, sizeof(clr888)) == 0)) ) {
388 img.format = DISPLAY_COLORS_RGB | DISPLAY_UNUSED_LAST |
389 DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
390 img.raster = img.width * 4;
391 }
392 else
393 return NULL; /* unrecognised format */
394 }
395 else
396 return NULL; /* unrecognised format */
397
398 pbitmap += pallength;
399
400 img.raster = (img.raster + 3) & ~3;
401 bits = (unsigned char *)malloc(img.raster * img.height);
402 if (bits == NULL)
403 return NULL;
404
405 for (y=0; y<(int)img.height; y++) {
406 dest = bits + y * img.raster;
407 if (convert) {
408 int idx;
409 int shift = 7;
410 if (depth == 1) {
411 for (x=0; x<bmp2.biWidth; x++) {
412 idx = pbitmap[x >> 3];
413 idx = (idx >> shift) & 1;
414 if ((img.format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)
415 *dest++ = colour[idx].rgbBlue;
416 else {
417 /* colour */
418 *dest++ = colour[idx].rgbBlue;
419 *dest++ = colour[idx].rgbGreen;
420 *dest++ = colour[idx].rgbRed;
421 }
422 shift--;
423 if (shift < 0)
424 shift = 7;
425 }
426 }
427 else if (depth == 4) {
428 for (x=0; x<bmp2.biWidth; x++) {
429 idx = pbitmap[x/2];
430 if (x & 0)
431 idx &= 0xf;
432 else
433 idx = (idx >> 4) & 0xf;
434 if ((img.format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)
435 *dest++ = colour[idx].rgbBlue;
436 else {
437 /* colour */
438 *dest++ = colour[idx].rgbBlue;
439 *dest++ = colour[idx].rgbGreen;
440 *dest++ = colour[idx].rgbRed;
441 }
442 }
443 }
444 else if (depth == 8) {
445 for (x=0; x<bmp2.biWidth; x++) {
446 idx = pbitmap[x];
447 if ((img.format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)
448 *dest++ = colour[idx].rgbBlue;
449 else {
450 /* colour */
451 *dest++ = colour[idx].rgbBlue;
452 *dest++ = colour[idx].rgbGreen;
453 *dest++ = colour[idx].rgbRed;
454 }
455 }
456 }
457 else {
458 free(bits);
459 return NULL;
460 }
461 }
462 else {
463 memcpy(dest, pbitmap, img.raster);
464 }
465 pbitmap += bytewidth;
466 }
467
468 pimage = (IMAGE *)malloc(sizeof(IMAGE));
469 if (pimage == NULL) {
470 free(bits);
471 return NULL;
472 }
473 memcpy(pimage, &img, sizeof(IMAGE));
474 pimage->image = bits;
475 return pimage;
476 }
477
478
479 /* read width * height "bits" from file */
480 static int
481 read_pbm_bits(unsigned char *pbitmap, unsigned int width, unsigned int height,
482 GFile *f)
483 {
484 int count = 0;
485 int ch;
486 int mask = 0x80;
487 int x, y;
488 char buf[MAXSTR];
489 int buf_count = 0;
490 int buf_idx = 0;
491
492 for (y=0; y<(int)height; y++) {
493 mask = 0x80;
494 for (x=0; x<(int)width; x++) {
495 if (mask == 0) {
496 mask = 0x80;
497 pbitmap++;
498 count++;
499 }
500 ch = 0;
501 while ((ch != '0') && (ch != '1')) {
502 if (buf_idx >= buf_count) {
503 buf_count = gfile_read(f, buf, min(sizeof(buf), width-x));
504 if (buf_count == 0)
505 return -1; /* premature EOF */
506 buf_idx = 0;
507 }
508 ch = buf[buf_idx++];
509 }
510 *pbitmap = (unsigned char)
511 ((ch == '1') ? (*pbitmap | mask) : (*pbitmap & (~mask)));
512 mask >>= 1;
513 }
514 pbitmap++;
515 count++;
516 }
517 return count;
518 }
519
520 /* read length "bytes" from file */
521 static int
522 read_pgnm_bytes(unsigned char *pbitmap, unsigned int length, GFile *f)
523 {
524 int count = 0;
525 int ch = 0;
526 int val;
527 char buf[MAXSTR];
528 int buf_count = 0;
529 int buf_idx = 0;
530
531 for (count=0; count < (int)length; count++) {
532 val = 0;
533 while (!((ch >= '0') && (ch <= '9'))) {
534 if (buf_idx >= buf_count) {
535 buf_count = gfile_read(f, buf, min(sizeof(buf), length-count));
536 if (buf_count == 0)
537 return -1; /* premature EOF */
538 buf_idx = 0;
539 }
540 ch = buf[buf_idx++];
541 }
542 while ((ch >= '0') && (ch <= '9')) {
543 val = (val*10) + ch - '0';
544 if (buf_idx >= buf_count) {
545 buf_count = gfile_read(f, buf, min(sizeof(buf), length-count));
546 if (buf_count == 0)
547 return -1; /* premature EOF */
548 buf_idx = 0;
549 }
550 ch = buf[buf_idx++];
551 }
552 *pbitmap++ = (unsigned char)val;
553 }
554 return count;
555 }
556
557 /* Load a PBMPLUS bitmap and return an image.
558 * Supported formats are pbmraw, pgmraw and ppmraw as written
559 * by Ghostscript.
560 */
561 IMAGE *
562 pnmfile_to_image(LPCTSTR filename)
563 {
564 GFile *f = gfile_open(filename, gfile_modeRead);
565 IMAGE img;
566 IMAGE *pimage;
567 int code;
568 char typeline[256];
569 char sizeline[256];
570 char maxvalline[256];
571 char hdrline[256];
572 char tupltype[256];
573 int width = 0;
574 int height = 0;
575 int maxval = 255;
576 int depth = 0;
577 int pam = 0;
578 int pbm = 0;
579 int pgm = 0;
580 int ppm = 0;
581 int raw = 0;
582 int cmyk = 0;
583 unsigned int length;
584 unsigned char *pbitmap;
585 int endhdr;
586 char *t1;
587 char *t2;
588
589 unsigned int count;
590
591 if (f == (GFile *)NULL)
592 return NULL;
593 memset(&img, 0, sizeof(img));
594 memset(typeline, 0, sizeof(typeline));
595 memset(sizeline, 0, sizeof(sizeline));
596 memset(maxvalline, 0, sizeof(maxvalline));
597 code = ps_fgets(typeline, sizeof(typeline)-1, f) == 0;
598 if (typeline[0] != 'P')
599 code = 1;
600 switch (typeline[1]) {
601 case '1':
602 pbm = 1;
603 raw = 0;
604 break;
605 case '2':
606 pgm = 1;
607 raw = 0;
608 break;
609 case '3':
610 ppm = 1;
611 raw = 0;
612 break;
613 case '4':
614 pbm = 1;
615 raw = 1;
616 break;
617 case '5':
618 pgm = 1;
619 raw = 1;
620 break;
621 case '6':
622 ppm = 1;
623 raw = 1;
624 break;
625 case '7':
626 pam = 1;
627 raw = 1;
628 break;
629 default:
630 code = 1;
631 }
632
633 if (pam) {
634 /* Portable Arbitrary Map */
635 endhdr = 0;
636 while (!endhdr && !code) {
637 if (!code)
638 code = ps_fgets(hdrline, sizeof(hdrline)-1, f) == 0;
639 while (!code && (hdrline[0] == '#'))
640 /* skip comments */
641 code = ps_fgets(hdrline, sizeof(hdrline)-1, f) == 0;
642 if (code)
643 break;
644 t1 = hdrline;
645 while (*t1 && ((*t1==' ') || (*t1=='\t')))
646 t1++; /* skip whitespace */
647 t1 = strtok(t1, " \t\r\n");
648 if (t1 == NULL)
649 break;
650 t2 = strtok(NULL, " \t\r\n");
651 if (strcmp(t1, "ENDHDR")==0) {
652 endhdr = 1;
653 continue;
654 }
655 else if (strcmp(t1, "WIDTH")==0) {
656 if (t2)
657 code = sscanf(t2, "%u", &width) != 1;
658 }
659 else if (strcmp(t1, "HEIGHT")==0) {
660 if (t2)
661 code = sscanf(t2, "%u", &height) != 1;
662 }
663 else if (strcmp(t1, "DEPTH")==0) {
664 if (t2)
665 code = sscanf(t2, "%u", &depth) != 1;
666 }
667 else if (strcmp(t1, "MAXVAL")==0) {
668 if (t2)
669 code = sscanf(t2, "%u", &maxval) != 1;
670 }
671 else if (strcmp(t1, "TUPLTYPE")==0) {
672 if (t2)
673 strncpy(tupltype, t2, sizeof(tupltype)-1);
674 }
675 }
676 if (!endhdr)
677 code = 1;
678 if ((width == 0) || (height == 0) || (depth == 0) || (maxval == 0))
679 code = 1;
680 if ((strcmp(tupltype, "BLACKANDWHITE")==0) &&
681 (depth == 1) && (maxval == 1))
682 pbm = 1;
683 if ((strcmp(tupltype, "GRAYSCALE")==0) &&
684 (depth == 1) && (maxval == 255))
685 pgm = 1;
686 if ((strcmp(tupltype, "RGB")==0) &&
687 (depth == 3) && (maxval == 255))
688 ppm = 1;
689 if ((strcmp(tupltype, "CMYK")==0) &&
690 (depth == 4) && (maxval == 255))
691 cmyk = 1;
692 }
693 else {
694 if (!code)
695 code = ps_fgets(sizeline, sizeof(sizeline)-1, f) == 0;
696 while (!code && (sizeline[0] == '#')) /* skip comments */
697 code = ps_fgets(sizeline, sizeof(sizeline)-1, f) == 0;
698
699 if (!code)
700 code = sscanf(sizeline, "%u %u", &width, &height) != 2;
701 if ((width == 0) || (height == 0))
702 code = 1;
703
704 if (!code && (pgm || ppm)) {
705 code = ps_fgets(maxvalline, sizeof(maxvalline)-1, f) == 0;
706 while (!code && (maxvalline[0] == '#'))
707 code = ps_fgets(maxvalline, sizeof(maxvalline)-1, f) == 0;
708 if (!code)
709 code = sscanf(maxvalline, "%u", &maxval) != 1;
710 }
711 if (maxval != 255)
712 code = 1;
713 }
714
715 img.width = width;
716 img.height = height;
717 if (pbm) {
718 img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
719 DISPLAY_DEPTH_1 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST;
720 img.raster = (img.width + 7) >> 3;
721 }
722 else if (pgm) {
723 img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE |
724 DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST;
725 img.raster = img.width;
726 }
727 else if (ppm) {
728 img.format = DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE |
729 DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST;
730 img.raster = img.width * 3;
731 }
732 else if (cmyk) {
733 img.format = DISPLAY_COLORS_CMYK | DISPLAY_ALPHA_NONE |
734 DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST;
735 img.raster = img.width * 4;
736 }
737 else
738 code = 1;
739
740 length = img.raster * img.height;
741
742 if (code) {
743 gfile_close(f);
744 return NULL;
745 }
746
747 pbitmap = (unsigned char *)malloc(length);
748 if (pbitmap == NULL) {
749 gfile_close(f);
750 return NULL;
751 }
752
753 if (raw)
754 count = (int)gfile_read(f, pbitmap, length);
755 else if (pbm)
756 count = read_pbm_bits(pbitmap, img.width, img.height, f);
757 else
758 count = read_pgnm_bytes(pbitmap, length, f);
759 gfile_close(f);
760
761 if (count != length) {
762 free(pbitmap);
763 return NULL;
764 }
765
766 pimage = (IMAGE *)malloc(sizeof(IMAGE));
767 if (pimage == NULL) {
768 free(pbitmap);
769 return NULL;
770 }
771 memcpy(pimage, &img, sizeof(IMAGE));
772 pimage->image = pbitmap;
773 return pimage;
774 }
775
776 /* Free an image created by bmpfile_to_image or pnmfile_to_image */
777 void
778 bitmap_image_free(IMAGE *img)
779 {
780 if (img && img->image) {
781 free(img->image);
782 memset(img, 0, sizeof(IMAGE));
783 free(img);
784 }
785 }
786
787 static int
788 image_bmp2init(IMAGE *img, BITMAP2 *bmp2)
789 {
790 /* Create a BMP header from the IMAGE */
791 /* If we need to convert the IMAGE before writing to a BMP file,
792 * the BMP header will not exactly match the image.
793 */
794 bmp2->biSize = BITMAP2_LENGTH;
795 bmp2->biWidth = img->width;
796 bmp2->biHeight = img->height;
797 bmp2->biPlanes = 1;
798 bmp2->biCompression = 0;
799 switch (img->format & DISPLAY_COLORS_MASK) {
800 case DISPLAY_COLORS_NATIVE:
801 switch (img->format & DISPLAY_DEPTH_MASK) {
802 case DISPLAY_DEPTH_1:
803 bmp2->biBitCount = 1;
804 bmp2->biClrUsed = 2;
805 bmp2->biClrImportant = 2;
806 break;
807 case DISPLAY_DEPTH_4:
808 /* Fixed color palette */
809 bmp2->biBitCount = 4;
810 bmp2->biClrUsed = 16;
811 bmp2->biClrImportant = 16;
812 break;
813 case DISPLAY_DEPTH_8:
814 /* Fixed color palette */
815 bmp2->biBitCount = 8;
816 bmp2->biClrUsed = 96;
817 bmp2->biClrImportant = 96;
818 break;
819 case DISPLAY_DEPTH_16:
820 /* RGB bitfields */
821 /* Bit fields */
822 if ((img->format & DISPLAY_ENDIAN_MASK)
823 == DISPLAY_BIGENDIAN) {
824 /* convert */
825 bmp2->biBitCount = 24;
826 bmp2->biClrUsed = 0;
827 bmp2->biClrImportant = 0;
828 }
829 else {
830 bmp2->biBitCount = 16;
831 bmp2->biCompression = BI_BITFIELDS;
832 bmp2->biClrUsed = 0;
833 bmp2->biClrImportant = 0;
834 }
835 break;
836 default:
837 return_error(-1);
838 }
839 break;
840 case DISPLAY_COLORS_GRAY:
841 switch (img->format & DISPLAY_DEPTH_MASK) {
842 case DISPLAY_DEPTH_1:
843 bmp2->biBitCount = 1;
844 bmp2->biClrUsed = 2;
845 bmp2->biClrImportant = 2;
846 break;
847 case DISPLAY_DEPTH_4:
848 /* Fixed gray palette */
849 bmp2->biBitCount = 4;
850 bmp2->biClrUsed = 16;
851 bmp2->biClrImportant = 16;
852 break;
853 case DISPLAY_DEPTH_8:
854 /* Fixed gray palette */
855 bmp2->biBitCount = 8;
856 bmp2->biClrUsed = 256;
857 bmp2->biClrImportant = 256;
858 break;
859 default:
860 return_error(-1);
861 }
862 break;
863 case DISPLAY_COLORS_RGB:
864 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
865 return_error(-1);
866 /* either native BGR, or we need to convert it */
867 bmp2->biBitCount = 24;
868 bmp2->biClrUsed = 0;
869 bmp2->biClrImportant = 0;
870 break;
871 case DISPLAY_COLORS_CMYK:
872 /* convert */
873 bmp2->biBitCount = 24;
874 bmp2->biClrUsed = 0;
875 bmp2->biClrImportant = 0;
876 break;
877 }
878
879 bmp2->biSizeImage = 0;
880 bmp2->biXPelsPerMeter = 0;
881 bmp2->biYPelsPerMeter = 0;
882 return 0;
883 }
884
885
886 /* Write an IMAGE as a Windows BMP file */
887 /* This is typically used to copy the display bitmap to a file */
888 int
889 image_to_bmpfile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi)
890 {
891 BITMAP2 bmp2;
892 BITMAPFILE bmf;
893 int bytewidth;
894 int depth;
895 int palcount;
896 int pallength;
897 GFile *f;
898 unsigned char r, g, b;
899 unsigned char quad[4];
900 unsigned char nulchar = '\0';
901 int i;
902 unsigned char *bits;
903 unsigned char *row;
904 int topfirst;
905
906 if ((img == NULL) || (img->image == NULL))
907 return -1;
908 if (image_bmp2init(img, &bmp2) < 0)
909 return -1;
910
911 if ((xdpi > 0.0) && (ydpi > 0.0)) {
912 bmp2.biXPelsPerMeter = (int)(xdpi * 1000.0 / 25.4 + 0.5);
913 bmp2.biYPelsPerMeter = (int)(ydpi * 1000.0 / 25.4 + 0.5);
914 }
915
916 depth = bmp2.biPlanes * bmp2.biBitCount;
917 bytewidth = ((bmp2.biWidth * depth + 31) & ~31) >> 3;
918 switch (depth) {
919 case 1:
920 case 4:
921 case 8:
922 palcount = 1 << depth;
923 pallength = palcount * RGB4_LENGTH;
924 break;
925 case 16:
926 palcount = 0;
927 pallength = 12;
928 default:
929 palcount = 0;
930 pallength = 0;
931 }
932
933 bmf.bfType = get_word((const unsigned char *)"BM");
934 bmf.bfReserved1 = 0;
935 bmf.bfReserved2 = 0;;
936 bmf.bfOffBits = BITMAPFILE_LENGTH + BITMAP2_LENGTH + palcount;
937 bmf.bfSize = bmf.bfOffBits + bytewidth * bmp2.biHeight;
938
939 row = (unsigned char *)malloc(bytewidth);
940 if (row == NULL)
941 return -1;
942
943 f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate);
944 if (f == (GFile *)NULL) {
945 free(row);
946 return -1;
947 }
948
949 /* Write BITMAPFILEHEADER */
950 write_word(bmf.bfType, f);
951 write_dword(bmf.bfSize, f);
952 write_word(bmf.bfReserved1, f);
953 write_word(bmf.bfReserved2, f);
954 write_dword(bmf.bfOffBits, f);
955
956 /* Write BITMAPINFOHEADER */
957 write_dword(bmp2.biSize, f);
958 write_dword(bmp2.biWidth, f);
959 write_dword(bmp2.biHeight, f);
960 write_word(bmp2.biPlanes, f);
961 write_word(bmp2.biBitCount, f);
962 write_dword(bmp2.biCompression, f);
963 write_dword(bmp2.biSizeImage, f);
964 write_dword(bmp2.biXPelsPerMeter, f);
965 write_dword(bmp2.biYPelsPerMeter, f);
966 write_dword(bmp2.biClrUsed, f);
967 write_dword(bmp2.biClrImportant, f);
968
969 /* Write palette or bitmasks */
970 for (i=0; i<palcount; i++) {
971 image_colour(img->format, i, &r, &g, &b);
972 quad[0] = b;
973 quad[1] = g;
974 quad[2] = r;
975 quad[3] = '\0';
976 gfile_write(f, quad, 4);
977 }
978 if (bmp2.biCompression == BI_BITFIELDS) {
979 if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555)
980 gfile_write(f, clr555, sizeof(clr555));
981 else
982 gfile_write(f, clr565, sizeof(clr565));
983 }
984
985 /* Write the bits */
986 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
987 for (i=0; i<bmp2.biHeight; i++) {
988 if (topfirst)
989 bits = img->image + img->raster * (img->height - i - 1);
990 else
991 bits = img->image + img->raster * i;
992 if (depth == 24) {
993 image_to_24BGR(img, row, bits);
994 gfile_write(f, row, bytewidth);
995 }
996 else {
997 if ((int)img->raster < bytewidth) {
998 int j;
999 gfile_write(f, bits, img->raster);
1000 for (j=bytewidth-img->raster; j>0; j--)
1001 gfile_write(f, &nulchar, 1);
1002 }
1003 else
1004 gfile_write(f, bits, bytewidth);
1005 }
1006 }
1007
1008 free(row);
1009 gfile_close(f);
1010 return 0;
1011 }
1012
1013 /*********************************************************/
1014
1015 #define tiff_long(val, f) write_dword(val, f)
1016 #define tiff_short(val, f) write_word_as_dword(val, f)
1017 #define tiff_word(val, f) write_word(val, f)
1018
1019 #define TIFF_BYTE 1
1020 #define TIFF_ASCII 2
1021 #define TIFF_SHORT 3
1022 #define TIFF_LONG 4
1023 #define TIFF_RATIONAL 5
1024
1025 struct rational_s {
1026 DWORD numerator;
1027 DWORD denominator;
1028 };
1029 #define TIFF_RATIONAL_SIZE 8
1030
1031 struct ifd_entry_s {
1032 WORD tag;
1033 WORD type;
1034 DWORD length;
1035 DWORD value;
1036 };
1037 #define TIFF_IFD_SIZE 12
1038
1039 struct tiff_head_s {
1040 WORD order;
1041 WORD version;
1042 DWORD ifd_offset;
1043 };
1044 #define TIFF_HEAD_SIZE 8
1045
1046 /* Write tiff file from IMAGE.
1047 * Since this will be used by a DOS EPS file, we write an Intel TIFF file.
1048 * Include the pixels specified in devbbox, which is in pixel coordinates
1049 * not points. If this is empty, the whole image will be used.
1050 * Resolution of bitmap is xdpi,ydpi.
1051 * If tiff4 is true, write a monochrome file compatible with TIFF 4,
1052 * otherwise make it compatible with TIFF 6.
1053 * If use_packbits is true and tiff4 is false, use packbits to
1054 * compress the bitmap.
1055 */
1056 int image_to_tiff(GFile *f, IMAGE *img,
1057 int xoffset, int yoffset, int width, int height,
1058 float xdpi, float ydpi,
1059 BOOL tiff4, BOOL use_packbits)
1060 {
1061 #define IFD_MAX_ENTRY 12
1062 WORD ifd_length;
1063 DWORD ifd_next;
1064 DWORD tiff_end, end;
1065 int i, j;
1066 unsigned char *preview;
1067 BYTE *line;
1068 const unsigned char nulchar = '\0';
1069 int temp_bwidth, bwidth;
1070 BOOL soft_extra = FALSE;
1071 int bitoffset;
1072 WORD *comp_length=NULL; /* lengths of compressed lines */
1073 BYTE *comp_line=NULL; /* compressed line buffer */
1074 int rowsperstrip;
1075 int stripsperimage;
1076 int strip, is;
1077 int strip_len;
1078 int lastrow;
1079
1080 int depth;
1081 int preview_depth;
1082 int topfirst;
1083
1084 if (img == NULL)
1085 return -1;
1086
1087 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1088
1089 depth = image_depth(img);
1090 if (depth == 1)
1091 preview_depth = 1;
1092 else if (depth == 4)
1093 preview_depth = 4;
1094 else if (depth == 8)
1095 preview_depth = 8;
1096 else
1097 preview_depth = 24;
1098 if (tiff4)
1099 preview_depth = 1;
1100
1101 /* byte width of source bitmap is img->raster */
1102 /* byte width of intermediate line, after conversion
1103 * to preview_depth, but before shifting to remove
1104 * unwanted pixels.
1105 */
1106 temp_bwidth = (img->width * preview_depth + 7) >> 3;
1107 /* byte width of preview */
1108 bwidth = (width * preview_depth + 7) >> 3;
1109 /* Number of bits to shift intermediate line to get preview line */
1110 bitoffset = xoffset * preview_depth;
1111
1112 if (tiff4)
1113 rowsperstrip = 1; /* make TIFF 4 very simple */
1114 else {
1115 /* work out RowsPerStrip, to give < 8k compressed */
1116 /* or uncompressed data per strip */
1117 rowsperstrip = (8192 - 256) / bwidth;
1118 if (rowsperstrip == 0)
1119 rowsperstrip = 1; /* strips are larger than 8k */
1120 }
1121 stripsperimage = (height + rowsperstrip - 1) / rowsperstrip;
1122 if (stripsperimage == 1)
1123 rowsperstrip = height;
1124
1125 preview = (unsigned char *) malloc(img->raster);
1126 if (preview == NULL)
1127 return -1;
1128 memset(preview,0xff,img->raster);
1129
1130 /* compress bitmap, throwing away result, to find out compressed size */
1131 if (use_packbits) {
1132 comp_length = (WORD *)malloc(stripsperimage * sizeof(WORD));
1133 if (comp_length == NULL) {
1134 free(preview);
1135 return -1;
1136 }
1137 comp_line = (BYTE *)malloc(bwidth + bwidth/64 + 1);
1138 if (comp_line == NULL) {
1139 free(preview);
1140 free(comp_length);
1141 return -1;
1142 }
1143 if (topfirst)
1144 line = img->image + img->raster * (img->height - yoffset - height);
1145 else
1146 line = img->image + img->raster * (yoffset + height-1);
1147
1148 /* process each strip */
1149 for (strip = 0; strip < stripsperimage; strip++) {
1150 is = strip * rowsperstrip;
1151 lastrow = min( rowsperstrip, height - is);
1152 comp_length[strip] = 0;
1153 strip_len = 0;
1154 /* process each line within strip */
1155 for (i = 0; i< lastrow; i++) {
1156 if (preview_depth == 1) {
1157 memset(preview,0xff,img->raster);
1158 image_to_mono(img, preview, line);
1159 for (j=0; j<temp_bwidth; j++)
1160 preview[j] ^= 0xff;
1161 }
1162 else if (preview_depth == 24)
1163 image_to_24RGB(img, preview, line);
1164 else if (depth == preview_depth)
1165 memmove(preview, line, img->raster);
1166 if (bitoffset)
1167 shift_bits(preview, temp_bwidth, bitoffset);
1168 strip_len += packbits(comp_line, preview, bwidth);
1169 if (topfirst)
1170 line += img->raster;
1171 else
1172 line -= img->raster;
1173 }
1174 comp_length[strip] = (WORD)strip_len;
1175 }
1176 }
1177
1178
1179 /* write header */
1180 tiff_end = TIFF_HEAD_SIZE;
1181 tiff_word(0x4949, f); /* Intel = little endian */
1182 tiff_word(42, f);
1183 tiff_long(tiff_end, f);
1184
1185 /* write count of ifd entries */
1186 tiff_end += 2 /* sizeof(ifd_length) */;
1187 if (tiff4)
1188 ifd_length = 10;
1189 else {
1190 switch (preview_depth) {
1191 case 24:
1192 /* extras are BitsPerPixel, SamplesPerPixel */
1193 ifd_length = 15;
1194 break;
1195 case 8:
1196 case 4:
1197 /* extras are BitsPerPixel, ColorMap */
1198 ifd_length = 15;
1199 break;
1200 default: /* bi-level */
1201 ifd_length = 13;
1202 }
1203 }
1204 tiff_word(ifd_length, f);
1205
1206 tiff_end += ifd_length * TIFF_IFD_SIZE + 4 /* sizeof(ifd_next) */;
1207 ifd_next = 0;
1208
1209 /* write each of the ifd entries */
1210 if (tiff4) {
1211 tiff_word(0xff, f); /* SubfileType */
1212 tiff_word(TIFF_SHORT, f); /* value type */
1213 tiff_long(1, f); /* length */
1214 tiff_short(0, f); /* value */
1215 }
1216 else {
1217 tiff_word(0xfe, f); /* NewSubfileType */
1218 tiff_word(TIFF_LONG, f);
1219 tiff_long(1, f); /* length */
1220 tiff_long(0, f); /* value */
1221 }
1222
1223 tiff_word(0x100, f); /* ImageWidth */
1224 if (tiff4) {
1225 tiff_word(TIFF_SHORT, f);
1226 tiff_long(1, f);
1227 tiff_short((short)width, f);
1228 }
1229 else {
1230 tiff_word(TIFF_LONG, f);
1231 tiff_long(1, f);
1232 tiff_long(width, f);
1233 }
1234
1235 tiff_word(0x101, f); /* ImageHeight */
1236 if (tiff4) {
1237 tiff_word(TIFF_SHORT, f);
1238 tiff_long(1, f);
1239 tiff_short((short)height, f);
1240 }
1241 else {
1242 tiff_word(TIFF_LONG, f);
1243 tiff_long(1, f);
1244 tiff_long(height, f);
1245 }
1246
1247 if (!tiff4 && preview_depth>1) {
1248 tiff_word(0x102, f); /* BitsPerSample */
1249 tiff_word(TIFF_SHORT, f);
1250 if (preview_depth == 24) {
1251 tiff_long(3, f);
1252 tiff_long(tiff_end, f);
1253 tiff_end += 6;
1254 }
1255 else {
1256 tiff_long(1, f);
1257 tiff_short((WORD)preview_depth, f);
1258 }
1259 }
1260
1261 tiff_word(0x103, f); /* Compression */
1262 tiff_word(TIFF_SHORT, f);
1263 tiff_long(1, f);
1264 if (use_packbits)
1265 tiff_short(32773U, f); /* packbits compression */
1266 else
1267 tiff_short(1, f); /* no compression */
1268
1269 tiff_word(0x106, f); /* PhotometricInterpretation */
1270 tiff_word(TIFF_SHORT, f);
1271 tiff_long(1, f);
1272 if (tiff4 || preview_depth==1)
1273 tiff_short(1, f); /* black is zero */
1274 else if (preview_depth==24)
1275 tiff_short(2, f); /* RGB */
1276 else /* preview_depth == 4 or 8 */
1277 tiff_short(3, f); /* Palette Color */
1278
1279 tiff_word(0x111, f); /* StripOffsets */
1280 tiff_word(TIFF_LONG, f);
1281 if (stripsperimage == 1) {
1282 /* This is messy and fragile */
1283 int len = 0;
1284 tiff_long(1, f);
1285 len += TIFF_RATIONAL_SIZE * 2; /* resolutions */
1286 if (!tiff4) {
1287 len += (((int)strlen(szGSviewName)+2)&~1) + 20; /* software and date */
1288 if (preview_depth == 4 || preview_depth == 8)
1289 len += 2 * 3*(1<<preview_depth); /* palette */
1290 }
1291 tiff_long(tiff_end + len, f);
1292 }
1293 else {
1294 tiff_long(stripsperimage, f);
1295 tiff_long(tiff_end, f);
1296 tiff_end += (stripsperimage * 4 /* sizeof(DWORD) */);
1297 }
1298
1299 if (!tiff4 && (preview_depth==24)) {
1300 tiff_word(0x115, f); /* SamplesPerPixel */
1301 tiff_word(TIFF_SHORT, f);
1302 tiff_long(1, f);
1303 tiff_short(3, f); /* 3 components */
1304 }
1305
1306 tiff_word(0x116, f); /* RowsPerStrip */
1307 tiff_word(TIFF_LONG, f);
1308 tiff_long(1, f);
1309 tiff_long(rowsperstrip, f);
1310
1311 tiff_word(0x117, f); /* StripByteCounts */
1312 tiff_word(TIFF_LONG, f);
1313 if (stripsperimage == 1) {
1314 tiff_long(1, f);
1315 if (use_packbits)
1316 tiff_long(comp_length[0], f);
1317 else
1318 tiff_long(bwidth * rowsperstrip, f);
1319 }
1320 else {
1321 tiff_long(stripsperimage, f);
1322 tiff_long(tiff_end, f);
1323 tiff_end += (stripsperimage * 4 /* sizeof(DWORD) */);
1324 }
1325
1326 tiff_word(0x11a, f); /* XResolution */
1327 tiff_word(TIFF_RATIONAL, f);
1328 tiff_long(1, f);
1329 tiff_long(tiff_end, f);
1330 tiff_end += TIFF_RATIONAL_SIZE;
1331
1332 tiff_word(0x11b, f); /* YResolution */
1333 tiff_word(TIFF_RATIONAL, f);
1334 tiff_long(1, f);
1335 tiff_long(tiff_end, f);
1336 tiff_end += TIFF_RATIONAL_SIZE;
1337
1338 if (!tiff4) {
1339 tiff_word(0x128, f); /* ResolutionUnit */
1340 tiff_word(TIFF_SHORT, f);
1341 tiff_long(1, f);
1342 tiff_short(2, f); /* inches */
1343
1344 tiff_word(0x131, f); /* Software */
1345 tiff_word(TIFF_ASCII, f);
1346 i = (int)strlen(szGSviewName) + 1;
1347 tiff_long(i, f);
1348 tiff_long(tiff_end, f);
1349 tiff_end += i;
1350 if (tiff_end & 1) { /* pad to word boundary */
1351 soft_extra = TRUE;
1352 tiff_end++;
1353 }
1354
1355 tiff_word(0x132, f); /* DateTime */
1356 tiff_word(TIFF_ASCII, f);
1357 tiff_long(20, f);
1358 tiff_long(tiff_end, f);
1359 tiff_end += 20;
1360
1361 if (preview_depth==4 || preview_depth==8) {
1362 int palcount = 1<<preview_depth;
1363 tiff_word(0x140, f); /* ColorMap */
1364 tiff_word(TIFF_SHORT, f);
1365 tiff_long(3*palcount, f); /* size of ColorMap */
1366 tiff_long(tiff_end, f);
1367 tiff_end += 2 * 3*palcount;
1368 }
1369 }
1370
1371
1372 /* write end of ifd tag */
1373 tiff_long(ifd_next, f);
1374
1375 /* BitsPerSample for 24 bit colour */
1376 if (!tiff4 && (preview_depth==24)) {
1377 tiff_word(8, f);
1378 tiff_word(8, f);
1379 tiff_word(8, f);
1380 }
1381
1382 /* strip offsets */
1383 end = tiff_end;
1384 if (stripsperimage > 1) {
1385 int stripwidth = bwidth * rowsperstrip;
1386 for (i=0; i<stripsperimage; i++) {
1387 tiff_long(end, f);
1388 if (use_packbits)
1389 end += comp_length[i];
1390 else
1391 end += stripwidth;
1392 }
1393 }
1394
1395 /* strip byte counts (after compression) */
1396 if (stripsperimage > 1) {
1397 for (i=0; i<stripsperimage; i++) {
1398 if (use_packbits)
1399 tiff_long(comp_length[i], f);
1400 else {
1401 is = i * rowsperstrip;
1402 lastrow = min( rowsperstrip, height - is);
1403 tiff_long(lastrow * bwidth, f);
1404 }
1405 }
1406 }
1407
1408 /* XResolution rational */
1409 tiff_long((int)xdpi, f);
1410 tiff_long(1, f);
1411 /* YResolution rational */
1412 tiff_long((int)ydpi, f);
1413 tiff_long(1, f);
1414
1415 /* software and time strings */
1416 if (!tiff4) {
1417 time_t t;
1418 char now[20];
1419 struct tm* dt;
1420 gfile_write(f, szGSviewName, (int)strlen(szGSviewName)+1);
1421 if (soft_extra)
1422 gfile_write(f, &nulchar, 1);
1423 t = time(NULL);
1424 dt = localtime(&t);
1425 snprintf(now, sizeof(now), "%04d:%02d:%02d %02d:%02d:%02d",
1426 dt->tm_year+1900, dt->tm_mon+1, dt->tm_mday,
1427 dt->tm_hour, dt->tm_min, dt->tm_sec);
1428 gfile_write(f, now, 20);
1429 }
1430
1431 /* Palette */
1432 if (!tiff4 && ((preview_depth==4) || (preview_depth==8))) {
1433 int palcount = 1<<preview_depth;
1434 unsigned char r, g, b;
1435 #define PALVAL(x) ((WORD)((x<< 8) | x))
1436 for (i=0; i<palcount; i++) {
1437 image_colour(img->format, i, &r, &g, &b);
1438 tiff_word(PALVAL(r), f);
1439 }
1440 for (i=0; i<palcount; i++) {
1441 image_colour(img->format, i, &r, &g, &b);
1442 tiff_word(PALVAL(g), f);
1443 }
1444 for (i=0; i<palcount; i++) {
1445 image_colour(img->format, i, &r, &g, &b);
1446 tiff_word(PALVAL(b), f);
1447 }
1448 #undef PALVAL
1449 }
1450
1451
1452 if (topfirst)
1453 line = img->image + img->raster * (img->height - yoffset - height);
1454 else
1455 line = img->image + img->raster * (yoffset+height-1);
1456
1457 /* process each strip of bitmap */
1458 for (strip = 0; strip < stripsperimage; strip++) {
1459 int len;
1460 is = strip * rowsperstrip;
1461 lastrow = min( rowsperstrip, height - is);
1462 /* process each row of strip */
1463 for (i = 0; i < lastrow; i++) {
1464 if (preview_depth == 1) {
1465 memset(preview,0,img->raster);
1466 image_to_mono(img, preview, line);
1467 for (j=0; j<temp_bwidth; j++)
1468 preview[j] ^= 0xff;
1469 }
1470 else if (preview_depth == 24)
1471 image_to_24RGB(img, preview, line);
1472 else if (depth == preview_depth)
1473 memmove(preview, line, img->raster);
1474 if (bitoffset)
1475 shift_bits(preview, temp_bwidth, bitoffset);
1476 if (use_packbits) {
1477 len = (WORD)packbits(comp_line, preview, bwidth);
1478 gfile_write(f, comp_line, len);
1479 }
1480 else
1481 gfile_write(f, preview, bwidth);
1482 if (topfirst)
1483 line += img->raster;
1484 else
1485 line -= img->raster;
1486 }
1487 }
1488
1489 if (use_packbits) {
1490 free(comp_length);
1491 free(comp_line);
1492 }
1493 free(preview);
1494 return 0;
1495 }
1496
1497 /* Write an IMAGE as a TIFF file */
1498 /* This is typically used to copy the display bitmap to a file */
1499 int
1500 image_to_tifffile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi)
1501 {
1502 GFile *f;
1503 int code = 0;
1504 BOOL tiff4 = ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1);
1505
1506 if ((img == NULL) || (img->image == NULL))
1507 return -1;
1508
1509 f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate);
1510 if (f == (GFile *)NULL)
1511 return -1;
1512
1513 code = image_to_tiff(f, img, 0, 0, img->width, img->height,
1514 xdpi, ydpi, tiff4, !tiff4);
1515
1516 gfile_close(f);
1517 return 0;
1518 }
1519
1520 /*********************************************************/
1521
1522 int
1523 image_to_pnmfile(IMAGE* img, LPCTSTR filename, PNM_FORMAT pnm_format)
1524 {
1525 PNM_FORMAT format = pnm_format;
1526 FILE *f;
1527 int bytewidth;
1528 unsigned char *row;
1529 unsigned char *bits;
1530 int topfirst;
1531 int i;
1532 if ((img == NULL) || (img->image == NULL))
1533 return -1;
1534
1535 /* check if mono, grey or colour */
1536 if ((format != PBMRAW) && (format != PGMRAW) && (format != PPMRAW)) {
1537 switch (img->format & DISPLAY_COLORS_MASK) {
1538 case DISPLAY_COLORS_NATIVE:
1539 switch (img->format & DISPLAY_DEPTH_MASK) {
1540 case DISPLAY_DEPTH_1:
1541 format = PBMRAW;
1542 break;
1543 case DISPLAY_DEPTH_4:
1544 case DISPLAY_DEPTH_8:
1545 case DISPLAY_DEPTH_16:
1546 format = PPMRAW;
1547 break;
1548 default:
1549 return_error(-1);
1550 }
1551 break;
1552 case DISPLAY_COLORS_GRAY:
1553 switch (img->format & DISPLAY_DEPTH_MASK) {
1554 case DISPLAY_DEPTH_1:
1555 format = PBMRAW;
1556 break;
1557 case DISPLAY_DEPTH_4:
1558 case DISPLAY_DEPTH_8:
1559 /* Fixed gray palette */
1560 format = PGMRAW;
1561 break;
1562 default:
1563 return_error(-1);
1564 }
1565 break;
1566 case DISPLAY_COLORS_RGB:
1567 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
1568 return_error(-1);
1569 format = PPMRAW;
1570 break;
1571 case DISPLAY_COLORS_CMYK:
1572 /* convert */
1573 format = PPMRAW;
1574 break;
1575 }
1576 }
1577 if (format == PPMRAW)
1578 bytewidth = img->width * 3;
1579 else if (format == PGMRAW)
1580 bytewidth = img->width;
1581 else
1582 bytewidth = (img->width + 7) >> 3;
1583 row = (unsigned char *)malloc(bytewidth);
1584 if (row == NULL)
1585 return -1;
1586 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1587
1588 f = csfopen(filename, TEXT("wb"));
1589 if (f == NULL) {
1590 free(row);
1591 return -1;
1592 }
1593
1594 fprintf(f, "P%c\n", (int)(format+'0'));
1595 fprintf(f, "# Created by GSview\n");
1596 fprintf(f, "%d %d\n", img->width, img->height);
1597 if ((format == PGMRAW) || (format == PPMRAW))
1598 fprintf(f, "255\n"); /* max value */
1599 for (i=0; i<(int)img->height; i++) {
1600 if (topfirst)
1601 bits = img->image + img->raster * i;
1602 else
1603 bits = img->image + img->raster * (img->height - i - 1);
1604 if (format == PPMRAW)
1605 image_to_24RGB(img, row, bits);
1606 else if (format == PGMRAW)
1607 image_to_grey(img, row, bits);
1608 else
1609 image_to_mono(img, row, bits);
1610 fwrite(row, 1, bytewidth, f);
1611 }
1612
1613 free(row);
1614 fclose(f);
1615 return 0;
1616 }
1617
1618 typedef enum PICTOp_e {
1619 PICT_NOP = 0x0000,
1620 PICT_Clip = 0x0001,
1621 PICT_VersionOp = 0x0011,
1622 PICT_DirectBitsRect = 0x009A, /* use this for 24/32 bits/pixel */
1623 PICT_OpEndPic = 0x00ff,
1624 PICT_Version = 0x02ff,
1625 PICT_HeaderOp = 0x0c00
1626 } PICTOp;
1627
1628 /* Write PICT PixData
1629 * Return number of bytes generated.
1630 * Return -ve on error.
1631 * If file is NULL just return the number of bytes generated
1632 * without actually writing anything.
1633 */
1634 static int
1635 write_pict_pixdata(IMAGE *img, GFile *f)
1636 {
1637 int i, j;
1638 int count;
1639 int topfirst;
1640 unsigned char b;
1641 unsigned char *bits;
1642 unsigned char *row, *sep, *packed;
1643 unsigned char *p;
1644 int wcount = 0;
1645 int rowwidth = img->width * 3;
1646 /* For the purposes of calculating the QuickDraw row width,
1647 * we must use 32-bits/pixel.
1648 */
1649 int qdrowwidth = img->width * 4;
1650
1651 row = (unsigned char *)malloc(rowwidth); /* 24-bit RGB */
1652 sep = (unsigned char *)malloc(qdrowwidth); /* xRGB or RRGGBB */
1653 packed = (unsigned char *)malloc(rowwidth + rowwidth / 128 + 1);
1654 if ((row == NULL) || (sep == NULL) || (packed == NULL)) {
1655 if (row != NULL)
1656 free(row);
1657 if (sep != NULL)
1658 free(sep);
1659 if (packed != NULL)
1660 free(packed);
1661 return -1;
1662 }
1663
1664 /* With packType=4 we compress each component separately, red first */
1665 wcount = 0;
1666 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1667 for (i=0; i<(int)img->height; i++) {
1668 if (topfirst)
1669 bits = img->image + img->raster * i;
1670 else
1671 bits = img->image + img->raster * (img->height - i - 1);
1672 image_to_24RGB(img, row, bits);
1673 p = row;
1674 if (qdrowwidth < 8) {
1675 /* Never compress short rows */
1676 if (f) {
1677 for (j=0; j<(int)img->width; j++) {
1678 /* Store as xRGB */
1679 sep[4*j] = '\0';
1680 sep[4*j+1] = *p++;
1681 sep[4*j+2] = *p++;
1682 sep[4*j+3] = *p++;
1683 }
1684 gfile_write(f, sep, qdrowwidth);
1685 }
1686 wcount += 8;
1687 }
1688 else {
1689 for (j=0; j<(int)img->width; j++) {
1690 /* separate components */
1691 sep[j] = *p++;
1692 sep[j+img->width] = *p++;
1693 sep[j+img->width+img->width] = *p++;
1694 }
1695 count = packbits(packed, sep, rowwidth);
1696 if (qdrowwidth > 250) {
1697 if (f)
1698 write_bigendian_word((WORD)count, f);
1699 wcount += 2;
1700 }
1701 else {
1702 b = (unsigned char )count;
1703 if (f)
1704 gfile_write(f, &b, 1);
1705 wcount += 1;
1706 }
1707 if (f)
1708 gfile_write(f, packed, count);
1709 wcount += count;
1710 }
1711 }
1712 if (wcount & 1) {
1713 /* write out an even number of bytes for row data */
1714 b = 0;
1715 if (f)
1716 gfile_write(f, &b, 1);
1717 wcount++;
1718 }
1719
1720 return wcount;
1721 }
1722
1723
1724
1725 /* Macintosh PICT */
1726 /* Only writes 24-bit RGB */
1727 int
1728 image_to_pictfile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi)
1729 {
1730 int i;
1731 int wcount;
1732 GFile *f = NULL;
1733
1734
1735 f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate);
1736 if (f == (GFile *)NULL)
1737 return -1;
1738
1739 /* Calculate compressed data length */
1740 wcount = write_pict_pixdata(img, NULL);
1741
1742 /* PICT starts with 512 null bytes */
1743 for (i=0; i<128; i++)
1744 write_bigendian_dword(0, f);
1745
1746 /* picture size - we will correct this later */
1747 /* 10 bytes */
1748 write_bigendian_word((WORD)(wcount+124), f);
1749 /* bounding box of rectangle */
1750 write_bigendian_word(0, f); /* top */
1751 write_bigendian_word(0, f); /* left */
1752 write_bigendian_word((WORD)img->height, f); /* bottom */
1753 write_bigendian_word((WORD)img->width, f); /* right */
1754
1755 /* Imaging With QuickDraw: Appendix A - Picture Opcodes */
1756 /* 4 bytes */
1757 write_bigendian_word(PICT_VersionOp, f);
1758 write_bigendian_word(PICT_Version, f);
1759
1760 /* Imaging With QuickDraw: Listing A-6 "A Sample Version 2 Picture" */
1761 /* 24 byte header + 2 byte NOP */
1762 write_bigendian_word(PICT_HeaderOp, f);
1763 write_bigendian_word((WORD)(-2), f); /* Version 2 extended */
1764 write_bigendian_word(0, f); /* reserved */
1765 write_bigendian_dword((DWORD)(xdpi * 65536), f); /* best hRes */
1766 write_bigendian_dword((DWORD)(ydpi * 65536), f); /* best vRes */
1767 write_bigendian_word(0, f); /* top */
1768 write_bigendian_word(0, f); /* left */
1769 write_bigendian_word((WORD)img->height, f); /* bottom */
1770 write_bigendian_word((WORD)img->width, f); /* right */
1771 write_bigendian_word(0, f); /* reserved */
1772 write_bigendian_word(PICT_NOP, f);
1773 /* 40 bytes to here */
1774
1775 /* Clip */
1776 write_bigendian_word(PICT_Clip, f);
1777 write_bigendian_word(10, f); /* size */
1778 write_bigendian_word(0, f); /* top */
1779 write_bigendian_word(0, f); /* left */
1780 write_bigendian_word((WORD)img->height, f); /* bottom */
1781 write_bigendian_word((WORD)img->width, f); /* right */
1782
1783 /* Based on Imaging With QuickDraw Listing A-2 for PackBitsRect */
1784 /* but modified to match DirectBitsRect output from Photoshop */
1785 write_bigendian_word(PICT_DirectBitsRect, f);
1786 write_bigendian_dword(0xff, f); /* unknown */
1787 /* rowBytes: flags = 0x8000 for pixmap, row width */
1788 write_bigendian_word((WORD)(0x8000 | (img->width * 4)), f); /* rowBytes */
1789 write_bigendian_word(0, f); /* bounds: top */
1790 write_bigendian_word(0, f); /* bounds: left */
1791 write_bigendian_word((WORD)img->height, f); /* bounds: bottom */
1792 write_bigendian_word((WORD)img->width, f); /* bounds: right */
1793 write_bigendian_word(0, f); /* pmVersion */
1794 write_bigendian_word(4, f); /* packType: packbits by component */
1795 write_bigendian_dword(0, f); /* packSize: always 0 */
1796 write_bigendian_dword((DWORD)(xdpi * 65536), f); /* hRes: fixed */
1797 write_bigendian_dword((DWORD)(ydpi * 65536), f); /* vRes: fixed */
1798 write_bigendian_word(16, f); /* pixelType: RGBDirect */
1799 write_bigendian_word(32, f); /* pixelSize: 24-bit RGB */
1800 write_bigendian_word(3, f); /* cmpCount: 3 for RGB */
1801 write_bigendian_word(8, f); /* cmpSize: 8 bits/component */
1802 write_bigendian_dword(0, f); /* planeBytes */
1803 write_bigendian_dword(0, f); /* pmTable */
1804 write_bigendian_dword(0, f); /* pmReserved */
1805
1806 /* srcRect */
1807 write_bigendian_word(0, f); /* srcRect: top */
1808 write_bigendian_word(0, f); /* srcRect: left */
1809 write_bigendian_word((WORD)img->height, f); /* srcRect: bottom */
1810 write_bigendian_word((WORD)img->width, f); /* srcRect: right */
1811
1812 /* destRect */
1813 write_bigendian_word(0, f); /* destRect: top */
1814 write_bigendian_word(0, f); /* destRect: left */
1815 write_bigendian_word((WORD)img->height, f); /* destRect: bottom */
1816 write_bigendian_word((WORD)img->width, f); /* destRect: right */
1817
1818 /* mode */
1819 write_bigendian_word(0x40, f); /* transfer mode */
1820
1821 /* PixData */
1822 write_pict_pixdata(img, f);
1823
1824 write_bigendian_word(PICT_OpEndPic, f);
1825
1826 gfile_close(f);
1827 return 0;
1828 }
1829
1830 #ifdef HAVE_LIBPNG
1831
1832 static void
1833 image_png_flush(png_structp png_ptr)
1834 {
1835 png_FILE_p io_ptr;
1836 io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
1837 if (io_ptr != NULL)
1838 fflush(io_ptr);
1839 }
1840
1841 static void
1842 image_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
1843 {
1844 int count = fwrite(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
1845 if (count != (int)length)
1846 png_error(png_ptr, "Write Error");
1847 }
1848
1849 static void
1850 image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
1851 {
1852 int count;
1853 count = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
1854 if (count != (int)length)
1855 png_error(png_ptr, "Read Error!");
1856 }
1857
1858 int
1859 image_to_pngfile(IMAGE* img, LPCTSTR filename)
1860 {
1861 FILE *f;
1862 png_structp png_ptr;
1863 png_infop info_ptr;
1864 int colour_type;
1865 int bit_depth;
1866 int num_palette = 0;
1867 png_color palette[96];
1868 BOOL invert_mono = FALSE;
1869 BOOL topfirst;
1870 unsigned char *bits;
1871 unsigned char *row = NULL;
1872 int i;
1873
1874 if ((img == NULL) || (img->image == NULL))
1875 return -1;
1876
1877 switch (img->format & DISPLAY_COLORS_MASK) {
1878 case DISPLAY_COLORS_NATIVE:
1879 switch (img->format & DISPLAY_DEPTH_MASK) {
1880 case DISPLAY_DEPTH_1:
1881 colour_type = PNG_COLOR_TYPE_GRAY;
1882 bit_depth = 1;
1883 invert_mono = TRUE;
1884 break;
1885 case DISPLAY_DEPTH_4:
1886 colour_type = PNG_COLOR_TYPE_PALETTE;
1887 bit_depth = 4;
1888 num_palette = 16;
1889 break;
1890 case DISPLAY_DEPTH_8:
1891 colour_type = PNG_COLOR_TYPE_PALETTE;
1892 num_palette = 96;
1893 bit_depth = 8;
1894 break;
1895 case DISPLAY_DEPTH_16:
1896 /* convert */
1897 colour_type = PNG_COLOR_TYPE_RGB;
1898 bit_depth = 8;
1899 break;
1900 default:
1901 return_error(-1);
1902 }
1903 break;
1904 case DISPLAY_COLORS_GRAY:
1905 switch (img->format & DISPLAY_DEPTH_MASK) {
1906 case DISPLAY_DEPTH_1:
1907 colour_type = PNG_COLOR_TYPE_GRAY;
1908 bit_depth = 1;
1909 break;
1910 case DISPLAY_DEPTH_4:
1911 colour_type = PNG_COLOR_TYPE_GRAY;
1912 bit_depth = 4;
1913 break;
1914 case DISPLAY_DEPTH_8:
1915 colour_type = PNG_COLOR_TYPE_GRAY;
1916 bit_depth = 8;
1917 break;
1918 default:
1919 return_error(-1);
1920 }
1921 break;
1922 case DISPLAY_COLORS_RGB:
1923 if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8)
1924 return_error(-1);
1925 colour_type = PNG_COLOR_TYPE_RGB;
1926 bit_depth = 8;
1927 break;
1928 case DISPLAY_COLORS_CMYK:
1929 /* convert */
1930 colour_type = PNG_COLOR_TYPE_RGB;
1931 bit_depth = 8;
1932 break;
1933 default:
1934 return -1;
1935 }
1936
1937 if (num_palette > sizeof(palette)/sizeof(palette[0]))
1938 return -1;
1939 if (colour_type == PNG_COLOR_TYPE_RGB) {
1940 row = (unsigned char *)malloc(img->width * 3);
1941 if (row == NULL)
1942 return -1;
1943 }
1944
1945 f = csfopen(filename, TEXT("wb"));
1946 if (f == NULL) {
1947 if (row)
1948 free(row);
1949 return -1;
1950 }
1951
1952 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1953 (png_voidp)NULL, NULL, NULL);
1954 if (png_ptr == NULL) {
1955 fclose(f);
1956 if (row)
1957 free(row);
1958 return -1;
1959 }
1960
1961 info_ptr = png_create_info_struct(png_ptr);
1962 if (info_ptr == NULL) {
1963 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1964 fclose(f);
1965 return -1;
1966 }
1967
1968 if (setjmp(png_jmpbuf(png_ptr))) {
1969 png_destroy_write_struct(&png_ptr, &info_ptr);
1970 fclose(f);
1971 if (row)
1972 free(row);
1973 return -1;
1974 }
1975
1976 png_set_write_fn(png_ptr, (png_voidp)f, image_png_write_data,
1977 image_png_flush);
1978
1979 png_set_IHDR(png_ptr, info_ptr, img->width, img->height,
1980 bit_depth, colour_type, PNG_INTERLACE_NONE,
1981 PNG_COMPRESSION_TYPE_DEFAULT,
1982 PNG_FILTER_TYPE_DEFAULT);
1983
1984 if (colour_type == PNG_COLOR_TYPE_PALETTE) {
1985 for (i=0; i<num_palette; i++)
1986 image_colour(img->format, i,
1987 &palette[i].red, &palette[i].green, &palette[i].blue);
1988 png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
1989 }
1990 if (invert_mono)
1991 png_set_invert_mono(png_ptr);
1992
1993 png_write_info(png_ptr, info_ptr);
1994
1995 topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1996 for (i=0; i<(int)img->height; i++) {
1997 if (topfirst)
1998 bits = img->image + img->raster * i;
1999 else
2000 bits = img->image + img->raster * (img->height - i - 1);
2001 if (colour_type == PNG_COLOR_TYPE_RGB) {
2002 image_to_24RGB(img, row, bits);
2003 bits = row;
2004 }
2005 png_write_row(png_ptr, bits);
2006 }
2007 png_write_end(png_ptr, info_ptr);
2008 png_destroy_write_struct(&png_ptr, &info_ptr);
2009 fclose(f);
2010 if (row)
2011 free(row);
2012 return 0;
2013 }
2014
2015 IMAGE *
2016 pngfile_to_image(LPCTSTR filename)
2017 {
2018 FILE *f;
2019 png_structp png_ptr;
2020 png_infop info_ptr;
2021 png_infop end_info;
2022 unsigned char png_buf[8];
2023 png_uint_32 width;
2024 png_uint_32 height;
2025 int bit_depth;
2026 int color_type;
2027 int interlace_type;
2028 int compression_method;
2029 int filter_method;
2030 unsigned char **rows = NULL;
2031 unsigned char *bits = NULL;
2032 int nbytes;
2033 int raster;
2034 int i;
2035 IMAGE *img = NULL;
2036
2037 f = csfopen(filename, TEXT("rb"));
2038 if (f == (FILE *)NULL)
2039 return NULL;
2040 fread(png_buf, 1, sizeof(png_buf), f);
2041 if (png_sig_cmp(png_buf, 0, sizeof(png_buf))!=0) {
2042 /* Not a PNG file */
2043 fclose(f);
2044 return NULL;
2045 }
2046
2047 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
2048 (png_voidp)NULL, NULL, NULL);
2049 if (png_ptr == NULL) {
2050 fclose(f);
2051 return NULL;
2052 }
2053 png_set_read_fn(png_ptr, (png_voidp)f, image_png_read_data);
2054
2055 info_ptr = png_create_info_struct(png_ptr);
2056 if (info_ptr == NULL) {
2057 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
2058 fclose(f);
2059 return NULL;
2060 }
2061
2062 end_info = png_create_info_struct(png_ptr);
2063 if (end_info == NULL) {
2064 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
2065 fclose(f);
2066 return NULL;
2067 }
2068
2069 if (setjmp(png_jmpbuf(png_ptr))) {
2070 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
2071 fclose(f);
2072 if (rows)
2073 free(rows);
2074 if (bits)
2075 free(bits);
2076 if (img)
2077 free(img);
2078 return NULL;
2079 }
2080
2081 png_set_sig_bytes(png_ptr, sizeof(png_buf));
2082
2083 png_read_info(png_ptr, info_ptr);
2084
2085 png_get_IHDR(png_ptr, info_ptr, &width, &height,
2086 &bit_depth, &color_type, &interlace_type,
2087 &compression_method, &filter_method);
2088
2089
2090 if (color_type == PNG_COLOR_TYPE_PALETTE)
2091 png_set_palette_to_rgb(png_ptr);
2092
2093 if (color_type == PNG_COLOR_TYPE_GRAY)
2094 nbytes = 1;
2095 else
2096 nbytes = 3;
2097
2098 if ((color_type == PNG_COLOR_TYPE_GRAY) &&
2099 (bit_depth < 8))
2100 png_set_gray_1_2_4_to_8(png_ptr);
2101
2102 if (bit_depth == 16)
2103 png_set_strip_16(png_ptr);
2104
2105 if (color_type & PNG_COLOR_MASK_ALPHA)
2106 png_set_strip_alpha(png_ptr);
2107
2108
2109 /* Allocate memory, and set row pointers */
2110 raster = (width * nbytes + 3) & ~3;
2111 rows = (unsigned char **)malloc(height * sizeof(unsigned char *));
2112 if (rows == NULL)
2113 longjmp(png_jmpbuf(png_ptr),-1);
2114 bits = (unsigned char *)malloc(raster * height);
2115 if (bits == NULL)
2116 longjmp(png_jmpbuf(png_ptr),-1);
2117 for (i=0; i<(int)height; i++)
2118 rows[i] = bits + i * raster;
2119
2120 png_read_rows(png_ptr, rows, NULL, height);
2121
2122 png_read_end(png_ptr, end_info);
2123
2124 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
2125 fclose(f);
2126 if (rows)
2127 free(rows);
2128
2129 img = (IMAGE *)malloc(sizeof(IMAGE));
2130 if (img == NULL)
2131 free(bits);
2132 else {
2133 img->width = width;
2134 img->height = height;
2135 img->raster = raster;
2136 img->format = (nbytes == 1)
2137 ? (DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE |
2138 DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST)
2139 : (DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE |
2140 DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST);
2141 img->image = bits;
2142 }
2143
2144 return img;
2145 }
2146
2147 #else /* HAVE_LIBPNG */
2148 int
2149 image_to_pngfile(IMAGE* img, LPCTSTR filename)
2150 {
2151 /* not supported */
2152 return -1;
2153 }
2154
2155 IMAGE *
2156 pngfile_to_image(LPCTSTR filename)
2157 {
2158 /* not supported */
2159 return NULL;
2160 }
2161 #endif /* HAVE_LIBPNG */
2162
2163
2164 /*********************************************************/
2165