home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / GDEVGIF.C < prev    next >
C/C++ Source or Header  |  1994-07-27  |  13KB  |  452 lines

  1. /* Copyright (C) 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gdevgif.c */
  20. /* GIF output device for Ghostscript. */
  21. #include "gdevprn.h"
  22. #include "gserrors.h"
  23. #include "gdevpccm.h"
  24.  
  25. /* Thanks to Phil Conrad for donating the original version */
  26. /* of these drivers to Aladdin Enterprises. */
  27.  
  28. /* ------ The device descriptors ------ */
  29.  
  30. /*
  31.  * Default X and Y resolution.
  32.  */
  33. #define X_DPI 72
  34. #define Y_DPI 72
  35.  
  36. /* The same print_page routine currently serves for */
  37. /* both monochrome and color. */
  38. private dev_proc_open_device(gif_open);
  39. private dev_proc_print_page(gif_print_page);
  40. private dev_proc_close_device(gif_close);
  41.  
  42. /* Monochrome. */
  43.  
  44. private gx_device_procs gifmono_procs =
  45.   prn_procs(gif_open, gdev_prn_output_page, gif_close);
  46. gx_device_printer far_data gs_gifmono_device =
  47.   prn_device(gifmono_procs, "gifmono",
  48.     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
  49.     X_DPI, Y_DPI,
  50.     0,0,0,0,            /* margins */
  51.     1, gif_print_page);
  52.  
  53. /* Chunky 8-bit (SuperVGA-style) color. */
  54. /* (Uses a fixed palette of 3,3,2 bits.) */
  55.  
  56. private gx_device_procs gif8_procs =
  57.   prn_color_procs(gif_open, gdev_prn_output_page, gif_close,
  58.     pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
  59. gx_device_printer far_data gs_gif8_device =
  60.   prn_device(gif8_procs, "gif8",
  61.     DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
  62.     X_DPI, Y_DPI,
  63.     0,0,0,0,            /* margins */
  64.     8, gif_print_page);
  65.  
  66. /* ------ Private definitions ------ */
  67.  
  68. /* All two-byte quantities are stored LSB-first! */
  69. #if arch_is_big_endian
  70. #  define assign_ushort(a,v) a = ((v) >> 8) + ((v) << 8)
  71. #else
  72. #  define assign_ushort(a,v) a = (v)
  73. #endif
  74.  
  75. typedef struct gif_header_s {
  76.     byte    signature[3];    /* magic number == 'GIF' */
  77.     byte    version[3];    /* version # '87a' or '89a' */
  78.     ushort    width;        /* screen width */
  79.     ushort    height;        /* screen height */
  80.  
  81.     /*
  82.      * We would like to use a struct here, but no compiler gives us
  83.      * the necessary pragmas to specify the packing explicitly....
  84.      */
  85. #if 0
  86.     struct    {        /* bit structure of flags */
  87.     unsigned globalcolor:1;    /* global color table flag - MSB*/
  88.     unsigned colorres:3;    /* bits/color */
  89.     unsigned sort:1;    /* color table sorted */
  90.     unsigned colorsize:3;    /* 2^colorsize bytes in color table -LSB */
  91.     } flags;
  92. #else
  93. #  define globalcolor_shift 7
  94. #  define colorres_shift 4
  95. #  define sort_shift 3
  96. #  define colorsize_shift 0
  97.     byte     flags;
  98. #endif
  99.  
  100.     byte    background;    /* background color index */
  101.     byte    aspect;        /* pixel aspect ratio */
  102.                 /* ratio = (aspect + 15) / 64 */
  103. } gif_header;
  104.  
  105. typedef struct image_descriptor_s {
  106. #if 0                /* (written separately) */
  107.     byte    separator;    /* image separator == 0x2c */
  108. #endif
  109.     ushort    left_pos;    /* image left pos (pixels) */
  110.     ushort    top_pos;    /* image top  pos (pixels) */
  111.     ushort    width;        /* image width    (pixels) */
  112.     ushort    height;        /* image height   (pixels) */
  113.  
  114.     /*
  115.      * See above regarding the specification of this structure.
  116.      */
  117. #if 0
  118.     struct    {
  119.     unsigned localcolor:1;    /* local color table flag */
  120.     unsigned interlace:1;    /* image interlaced  0=no */
  121.     unsigned sort:1;    /* color table sorted 0=no*/
  122.     unsigned resv:2;
  123.     unsigned localsize:3;    /* 2^localsize+1 = color table size */
  124.     } flags;
  125. #else
  126.     byte    flags;
  127. #endif
  128.  
  129. } image_descriptor;
  130.  
  131. /********************************************************/
  132. /* LZW routines are based on:                */
  133. /* Dr. Dobbs Journal --- Oct. 1989.             */
  134. /* Article on LZW Data Compression by Mark R. Nelson     */
  135. /********************************************************/
  136.  
  137. #define MAX_BITS 12        /* this is max for GIF. */
  138.  
  139. #define TABLE_SIZE 5123        /* this is max for 12-bit codes */
  140. #define TABLE_HASH_SHIFT 2    /* size < 4095 + (4095 >> shift) */
  141.  
  142. /* State of LZW encoder */
  143. typedef struct code_entry_s {
  144.     int    code_value;
  145.     ushort    prefix_code;
  146.     byte    append_character;
  147. #if arch_sizeof_int == 4
  148.     byte    _pad;        /* pad to 8 bytes */
  149. #endif
  150. } code_entry;
  151. typedef struct lzw_encoder_s {
  152.     int    bits;
  153.     ushort    Max_Code;
  154.     ushort    Clear_code;
  155.     ushort    next_code;
  156.     FILE    *file;
  157.     code_entry    *table;
  158.     ushort    string_code;
  159.     /* State of output buffer */
  160.     byte    output_bit_buffer;
  161.     int    output_bit_count;    /* # of valid low-order bits */
  162.                     /* (between 0 and 7) in buffer */
  163.     uint    byte_count;
  164.     byte    gif_buffer[260];
  165. } lzw_encoder;
  166.  
  167. /* Initialize LZW encoder */
  168. private void lzw_set_bits(P2(register lzw_encoder _ss *, int));
  169. private void lzw_reset(P1(register lzw_encoder _ss *));
  170. private int
  171. lzw_init(register lzw_encoder _ss *pe, int bits, FILE *file)
  172. {    lzw_set_bits(pe, bits);
  173.     pe->Clear_code = (1 << bits);
  174.     pe->file = file;
  175.     pe->byte_count = 1;
  176.     pe->output_bit_count = 0;
  177.     pe->output_bit_buffer = 0;
  178.     pe->table = (code_entry *)gs_malloc(TABLE_SIZE, sizeof(code_entry), "GIF code table");
  179.  
  180.     if ( pe->table == 0 )
  181.         return_error(gs_error_VMerror);    /* can't allocate buffers */
  182.  
  183.     lzw_reset(pe);
  184.     pe->string_code = 0;
  185.     return 0;
  186. }
  187. /* Establish the width of the code in bits */
  188. private void
  189. lzw_set_bits(register lzw_encoder _ss *pe, int bits)
  190. {    pe->bits = bits;
  191.     pe->Max_Code = (1 << (bits+1)) - 1;
  192. }
  193. /* Reset the encoding table */
  194. private void
  195. lzw_reset(register lzw_encoder _ss *pe)
  196. {    int index;
  197.     for ( index = 0; index < TABLE_SIZE; index++ )
  198.         pe->table[index].code_value = -1;
  199.     pe->next_code = pe->Clear_code + 2;
  200. }
  201.  
  202. /* Put out (data) of length (bits) to GIF buffer */
  203. private void
  204. lzw_putc(register lzw_encoder _ss *pe, uint data)
  205. {    int bits = pe->bits + 1;    /* output width */
  206.     ulong buffer = pe->output_bit_buffer | ((ulong)data << pe->output_bit_count);
  207.     pe->output_bit_count += bits;
  208.     while ( pe->output_bit_count >= 8 )
  209.     {    /* putc(output_bit_buffer >> 24, file); */
  210.         pe->gif_buffer[pe->byte_count] = (byte)buffer;    /* low byte */
  211.         buffer >>= 8;
  212.         pe->output_bit_count -= 8;
  213.         pe->byte_count++;
  214.         if ( pe->byte_count == 256 )
  215.         {    pe->byte_count = 1;
  216.             pe->gif_buffer[0] = 255;  /* byte count for block */
  217.             fwrite(pe->gif_buffer, 1, 256, pe->file);
  218.         }
  219.     }
  220.     pe->output_bit_buffer = (byte)buffer;
  221. }
  222.  
  223. /* Finish encoding, and flush the buffers. */
  224. private void
  225. lzw_finish(register lzw_encoder _ss *pe)
  226. {    lzw_putc(pe, pe->string_code);    /* output last code */
  227.     lzw_putc(pe, pe->Clear_code+1);    /* output eof code */
  228.     lzw_putc(pe, 0);    /* force out last code */
  229.     if ( pe->byte_count != 1 )
  230.     {    pe->gif_buffer[0] = pe->byte_count;
  231.         fwrite(pe->gif_buffer, 1, pe->byte_count+1, pe->file);
  232.     }
  233. }
  234.  
  235. /* Terminate LZW encoder. */
  236. private void
  237. lzw_exit(register lzw_encoder _ss *pe)
  238. {    gs_free((char *)pe->table, TABLE_SIZE, sizeof(code_entry), "GIF code table");
  239. }
  240.  
  241. /* Get the next (depth) bits from the pixel buffer. */
  242. /* Note that 8 % depth == 0. */
  243. /* Free variables: bits_left, bit_buffer, next, depth, depth_mask. */
  244. #define lzw_getc()\
  245.   (bits_left == 0 ?\
  246.    (bit_buffer = *(next++)) >> (bits_left = 8 - (depth)) :\
  247.    (bit_buffer >> (bits_left -= (depth))) & (depth_mask))
  248.  
  249. /* Output 1 row of data in GIF (LZW) format. */
  250. private void
  251. lzw(byte *from, byte *end, register lzw_encoder _ss *pe, int depth)
  252. {    int bits_left = 0;
  253.     uint bit_buffer;
  254.     byte *next = from;
  255.     uint depth_mask = (1 << depth) - 1;
  256.  
  257.     if ( pe->next_code == (pe->Clear_code + 2))    /* first time through */
  258.     {    pe->string_code = lzw_getc();
  259.     }
  260.  
  261.     while ( next < end || bits_left >= depth )
  262.     {    uint    data = lzw_getc();    /* actually only a byte */
  263.  
  264.         /* Hash to find a match for the prefix+char */
  265.         /* string in the string table */
  266.  
  267.         ushort    hash_prefix = pe->string_code;
  268.         int    index = (data << 4) ^ hash_prefix;
  269.         int    hash_offset;
  270.         register code_entry *pce;
  271.  
  272.         index += index >> TABLE_HASH_SHIFT;
  273.         if ( index == 0 )
  274.             hash_offset = 1;
  275.         else
  276.             hash_offset = TABLE_SIZE - index;
  277.  
  278.         while ( 1 )
  279.         {    pce = &pe->table[index];
  280.             if ( pce->code_value == -1 )
  281.                 break;
  282.             if ( pce->prefix_code == hash_prefix && 
  283.                  pce->append_character == data )
  284.                 break;
  285.             index -= hash_offset;
  286.             if ( index < 0 )
  287.                 index += TABLE_SIZE;
  288.         }
  289.         if ( pce->code_value != -1 )
  290.             pe->string_code = pce->code_value;
  291.         else
  292.         {    /* Make a new entry */
  293.             pce->code_value = pe->next_code++;
  294.             pce->prefix_code = pe->string_code;
  295.             pce->append_character = data;
  296.  
  297.             lzw_putc(pe, pe->string_code);
  298.  
  299.             if ( pe->next_code > (pe->Max_Code + 1) )
  300.             {    /* Increment the width of the code */
  301.                 if ( pe->bits+1 >= MAX_BITS )
  302.                 {    /* output clear code first*/
  303.                     lzw_putc(pe, pe->Clear_code);
  304.                     pe->bits = (depth == 1 ? 2 : depth);
  305.                     lzw_reset(pe);
  306.                 }
  307.                 else
  308.                     pe->bits++;
  309.                 lzw_set_bits(pe, pe->bits);
  310.             }
  311.             pe->string_code = data;
  312.         }
  313.     }
  314. }
  315.  
  316.  
  317. /* Open the device.  The only reason for this routine is */
  318. /* to print the obnoxious copyright notice. */
  319. private int
  320. gif_open(gx_device *pdev)
  321. {    int code = gdev_prn_open(pdev);
  322.     if ( code < 0 ) return code;
  323.  
  324.     /* Put the message on stderr so it doesn't interfere with */
  325.     /* possible piped output. */
  326.     fprintf(stderr, "The Graphics Interchange Format(c) is\n");
  327.     fprintf(stderr, "the Copyright Property of CompuServe Incorporated.\n");
  328.     fprintf(stderr, "GIF(sm) is a Service Mark property of CompuServe Incorporated.\n");
  329.  
  330.     return 0;
  331. }
  332.  
  333.  
  334. /* Write a page to a file in GIF format. */
  335. private int
  336. gif_print_page(gx_device_printer *pdev, FILE *file)
  337. {    int raster = gdev_prn_raster(pdev);
  338.     ushort height = pdev->height;
  339.     int depth = pdev->color_info.depth;
  340.     ushort gif_width = raster * (8 / depth); /* decoders want the width */
  341.                         /* on a byte boundary */
  342.     byte *row = (byte *)gs_malloc(raster * 2, 1, "gif file buffer");
  343.     byte *end = row + raster;
  344.     gif_header header;
  345.     image_descriptor header_desc;
  346.     lzw_encoder encoder;
  347.     int y;
  348.     int code = 0;            /* return code */
  349.  
  350.     if ( row == 0 )            /* can't allocate row buffer */
  351.         return_error(gs_error_VMerror);
  352.     code = lzw_init(&encoder, (depth == 1 ? 2 : depth), file);
  353.     if ( code < 0 )
  354.       {    gs_free((char *)row, raster * 2, 1, "gif file buffer");
  355.         return code;
  356.       }
  357.  
  358.     /* Set up the header. */
  359.  
  360.     memcpy(header.signature, "GIF", 3);
  361.     memcpy(header.version, "87a", 3);
  362.     assign_ushort(header.width, gif_width);
  363.     assign_ushort(header.height, height);
  364. /*    header.flags.globalcolor = TRUE;    */
  365. /*    header.flags.colorres = depth-1;    */
  366. /*    header.flags.sort = FALSE;        */
  367. /*    header.flags.colorsize = depth-1;    */
  368.     header.flags =
  369.         (1 << globalcolor_shift) +
  370.         ((depth - 1) << colorres_shift) +
  371.         (0 << sort_shift) +
  372.         ((depth - 1) << colorsize_shift);
  373.     header.background = 0;
  374.     header.aspect = 0;
  375.     
  376.     /* Write the header, on the first page only. */
  377.  
  378.     if ( gdev_prn_file_is_new(pdev) )
  379.     {
  380.         if ( fwrite(&header, 1, 13, file) < 13 )
  381.         {    code = gs_error_ioerror;
  382.             goto gif_done;
  383.         }
  384.  
  385.         /* Write the header global color palette. */
  386.  
  387.         if ( pc_write_palette((gx_device *)pdev, 1 << depth, file) < 0 )
  388.         {    code = gs_error_ioerror;
  389.             goto gif_done;
  390.         }
  391.     }
  392.  
  393.     header_desc.left_pos = 0;
  394.     header_desc.top_pos = 0;
  395.     assign_ushort(header_desc.width, gif_width);
  396.     assign_ushort(header_desc.height, height);
  397. /*    header_desc.flags.localcolor = TRUE;    */
  398. /*    header_desc.flags.interlace = FALSE;    */
  399. /*    header_desc.flags.sort = FALSE;        */
  400. /*    header_desc.flags.localsize = depth - 1;*/
  401.  
  402.     header_desc.flags =
  403.         (1 << globalcolor_shift) +
  404.         ((depth - 1) << colorsize_shift);
  405.  
  406.     /* Write the header image descriptor. */
  407.  
  408.     fputc(0x2c,file);        /* start with separator */
  409.     if ( fwrite(&header_desc, 1, 9, file) < 9 )
  410.        {    code = gs_error_ioerror;
  411.         goto gif_done;
  412.        }
  413.   
  414.     /* Write the local color palette. */
  415.  
  416.     if ( pc_write_palette((gx_device *)pdev, 1 << depth, file) < 0 )
  417.        {    code = gs_error_ioerror;
  418.         goto gif_done;
  419.        }
  420.  
  421.     fputc(encoder.bits, file);        /* start with code size */
  422.  
  423.     lzw_putc(&encoder, encoder.Clear_code);    /* output clear code first*/
  424.  
  425.     /* Dump the contents of the image. */
  426.     for ( y = 0; y < height; y++ ) 
  427.        {    gdev_prn_copy_scan_lines(pdev, y, row, raster);
  428.         lzw(row, end, &encoder, depth);
  429.        }
  430.  
  431.     lzw_finish(&encoder);
  432.     fputc(0, file);
  433.  
  434. gif_done:
  435.     lzw_exit(&encoder);
  436.     gs_free((char *)row, raster * 2, 1, "gif file buffer");
  437.     return code;
  438. }
  439.  
  440. /* Close the device, writing an end-of-file mark. */
  441. private int
  442. gif_close(gx_device *pdev)
  443. {
  444.     FILE *file = ((gx_device_printer *)pdev)->file;
  445.  
  446.     if ( file != NULL )
  447.     {    fputc(0x3b, file);    /* EOF indicator */
  448.     }
  449.  
  450.     return gdev_prn_close(pdev);
  451. }
  452.