"Fossies" - the Fresh Open Source Software Archive

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