"Fossies" - the Fresh Open Source Software Archive

Member "epstool-3.08/src/cbmp.c" (10 Jun 2005, 55715 Bytes) of package /linux/misc/old/ghost/ghostgum/epstool-3.08-os2.zip:


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