wrgif.c
上传用户:wuyixingx
上传日期:2007-01-08
资源大小:745k
文件大小:13k
源码类别:

图形图象

开发平台:

C/C++

  1. /*
  2.  * wrgif.c
  3.  *
  4.  * Copyright (C) 1991-1997, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in GIF format.
  9.  *
  10.  **************************************************************************
  11.  * NOTE: to avoid entanglements with Unisys' patent on LZW compression,   *
  12.  * this code has been modified to output "uncompressed GIF" files.        *
  13.  * There is no trace of the LZW algorithm in this file.                   *
  14.  **************************************************************************
  15.  *
  16.  * These routines may need modification for non-Unix environments or
  17.  * specialized applications.  As they stand, they assume output to
  18.  * an ordinary stdio stream.
  19.  */
  20. /*
  21.  * This code is loosely based on ppmtogif from the PBMPLUS distribution
  22.  * of Feb. 1991.  That file contains the following copyright notice:
  23.  *    Based on GIFENCODE by David Rowley <mgardi@watdscu.waterloo.edu>.
  24.  *    Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
  25.  *    Copyright (C) 1989 by Jef Poskanzer.
  26.  *    Permission to use, copy, modify, and distribute this software and its
  27.  *    documentation for any purpose and without fee is hereby granted, provided
  28.  *    that the above copyright notice appear in all copies and that both that
  29.  *    copyright notice and this permission notice appear in supporting
  30.  *    documentation.  This software is provided "as is" without express or
  31.  *    implied warranty.
  32.  *
  33.  * We are also required to state that
  34.  *    "The Graphics Interchange Format(c) is the Copyright property of
  35.  *    CompuServe Incorporated. GIF(sm) is a Service Mark property of
  36.  *    CompuServe Incorporated."
  37.  */
  38. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  39. #ifdef GIF_SUPPORTED
  40. /* Private version of data destination object */
  41. typedef struct {
  42.   struct djpeg_dest_struct pub; /* public fields */
  43.   j_decompress_ptr cinfo; /* back link saves passing separate parm */
  44.   /* State for packing variable-width codes into a bitstream */
  45.   int n_bits; /* current number of bits/code */
  46.   int maxcode; /* maximum code, given n_bits */
  47.   INT32 cur_accum; /* holds bits not yet output */
  48.   int cur_bits; /* # of bits in cur_accum */
  49.   /* State for GIF code assignment */
  50.   int ClearCode; /* clear code (doesn't change) */
  51.   int EOFCode; /* EOF code (ditto) */
  52.   int code_counter; /* counts output symbols */
  53.   /* GIF data packet construction buffer */
  54.   int bytesinpkt; /* # of bytes in current packet */
  55.   char packetbuf[256]; /* workspace for accumulating packet */
  56. } gif_dest_struct;
  57. typedef gif_dest_struct * gif_dest_ptr;
  58. /* Largest value that will fit in N bits */
  59. #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
  60. /*
  61.  * Routines to package finished data bytes into GIF data blocks.
  62.  * A data block consists of a count byte (1..255) and that many data bytes.
  63.  */
  64. LOCAL(void)
  65. flush_packet (gif_dest_ptr dinfo)
  66. /* flush any accumulated data */
  67. {
  68.   if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */
  69.     dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++;
  70.     if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt)
  71. != (size_t) dinfo->bytesinpkt)
  72.       ERREXIT(dinfo->cinfo, JERR_FILE_WRITE);
  73.     dinfo->bytesinpkt = 0;
  74.   }
  75. }
  76. /* Add a character to current packet; flush to disk if necessary */
  77. #define CHAR_OUT(dinfo,c)  
  78. { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c);  
  79.     if ((dinfo)->bytesinpkt >= 255)  
  80.       flush_packet(dinfo);  
  81. }
  82. /* Routine to convert variable-width codes into a byte stream */
  83. LOCAL(void)
  84. output (gif_dest_ptr dinfo, int code)
  85. /* Emit a code of n_bits bits */
  86. /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
  87. {
  88.   dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits;
  89.   dinfo->cur_bits += dinfo->n_bits;
  90.   while (dinfo->cur_bits >= 8) {
  91.     CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
  92.     dinfo->cur_accum >>= 8;
  93.     dinfo->cur_bits -= 8;
  94.   }
  95. }
  96. /* The pseudo-compression algorithm.
  97.  *
  98.  * In this module we simply output each pixel value as a separate symbol;
  99.  * thus, no compression occurs.  In fact, there is expansion of one bit per
  100.  * pixel, because we use a symbol width one bit wider than the pixel width.
  101.  *
  102.  * GIF ordinarily uses variable-width symbols, and the decoder will expect
  103.  * to ratchet up the symbol width after a fixed number of symbols.
  104.  * To simplify the logic and keep the expansion penalty down, we emit a
  105.  * GIF Clear code to reset the decoder just before the width would ratchet up.
  106.  * Thus, all the symbols in the output file will have the same bit width.
  107.  * Note that emitting the Clear codes at the right times is a mere matter of
  108.  * counting output symbols and is in no way dependent on the LZW patent.
  109.  *
  110.  * With a small basic pixel width (low color count), Clear codes will be
  111.  * needed very frequently, causing the file to expand even more.  So this
  112.  * simplistic approach wouldn't work too well on bilevel images, for example.
  113.  * But for output of JPEG conversions the pixel width will usually be 8 bits
  114.  * (129 to 256 colors), so the overhead added by Clear symbols is only about
  115.  * one symbol in every 256.
  116.  */
  117. LOCAL(void)
  118. compress_init (gif_dest_ptr dinfo, int i_bits)
  119. /* Initialize pseudo-compressor */
  120. {
  121.   /* init all the state variables */
  122.   dinfo->n_bits = i_bits;
  123.   dinfo->maxcode = MAXCODE(dinfo->n_bits);
  124.   dinfo->ClearCode = (1 << (i_bits - 1));
  125.   dinfo->EOFCode = dinfo->ClearCode + 1;
  126.   dinfo->code_counter = dinfo->ClearCode + 2;
  127.   /* init output buffering vars */
  128.   dinfo->bytesinpkt = 0;
  129.   dinfo->cur_accum = 0;
  130.   dinfo->cur_bits = 0;
  131.   /* GIF specifies an initial Clear code */
  132.   output(dinfo, dinfo->ClearCode);
  133. }
  134. LOCAL(void)
  135. compress_pixel (gif_dest_ptr dinfo, int c)
  136. /* Accept and "compress" one pixel value.
  137.  * The given value must be less than n_bits wide.
  138.  */
  139. {
  140.   /* Output the given pixel value as a symbol. */
  141.   output(dinfo, c);
  142.   /* Issue Clear codes often enough to keep the reader from ratcheting up
  143.    * its symbol size.
  144.    */
  145.   if (dinfo->code_counter < dinfo->maxcode) {
  146.     dinfo->code_counter++;
  147.   } else {
  148.     output(dinfo, dinfo->ClearCode);
  149.     dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */
  150.   }
  151. }
  152. LOCAL(void)
  153. compress_term (gif_dest_ptr dinfo)
  154. /* Clean up at end */
  155. {
  156.   /* Send an EOF code */
  157.   output(dinfo, dinfo->EOFCode);
  158.   /* Flush the bit-packing buffer */
  159.   if (dinfo->cur_bits > 0) {
  160.     CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
  161.   }
  162.   /* Flush the packet buffer */
  163.   flush_packet(dinfo);
  164. }
  165. /* GIF header construction */
  166. LOCAL(void)
  167. put_word (gif_dest_ptr dinfo, unsigned int w)
  168. /* Emit a 16-bit word, LSB first */
  169. {
  170.   putc(w & 0xFF, dinfo->pub.output_file);
  171.   putc((w >> 8) & 0xFF, dinfo->pub.output_file);
  172. }
  173. LOCAL(void)
  174. put_3bytes (gif_dest_ptr dinfo, int val)
  175. /* Emit 3 copies of same byte value --- handy subr for colormap construction */
  176. {
  177.   putc(val, dinfo->pub.output_file);
  178.   putc(val, dinfo->pub.output_file);
  179.   putc(val, dinfo->pub.output_file);
  180. }
  181. LOCAL(void)
  182. emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap)
  183. /* Output the GIF file header, including color map */
  184. /* If colormap==NULL, synthesize a gray-scale colormap */
  185. {
  186.   int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
  187.   int cshift = dinfo->cinfo->data_precision - 8;
  188.   int i;
  189.   if (num_colors > 256)
  190.     ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors);
  191.   /* Compute bits/pixel and related values */
  192.   BitsPerPixel = 1;
  193.   while (num_colors > (1 << BitsPerPixel))
  194.     BitsPerPixel++;
  195.   ColorMapSize = 1 << BitsPerPixel;
  196.   if (BitsPerPixel <= 1)
  197.     InitCodeSize = 2;
  198.   else
  199.     InitCodeSize = BitsPerPixel;
  200.   /*
  201.    * Write the GIF header.
  202.    * Note that we generate a plain GIF87 header for maximum compatibility.
  203.    */
  204.   putc('G', dinfo->pub.output_file);
  205.   putc('I', dinfo->pub.output_file);
  206.   putc('F', dinfo->pub.output_file);
  207.   putc('8', dinfo->pub.output_file);
  208.   putc('7', dinfo->pub.output_file);
  209.   putc('a', dinfo->pub.output_file);
  210.   /* Write the Logical Screen Descriptor */
  211.   put_word(dinfo, (unsigned int) dinfo->cinfo->output_width);
  212.   put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
  213.   FlagByte = 0x80; /* Yes, there is a global color table */
  214.   FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
  215.   FlagByte |= (BitsPerPixel-1); /* size of global color table */
  216.   putc(FlagByte, dinfo->pub.output_file);
  217.   putc(0, dinfo->pub.output_file); /* Background color index */
  218.   putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */
  219.   /* Write the Global Color Map */
  220.   /* If the color map is more than 8 bits precision, */
  221.   /* we reduce it to 8 bits by shifting */
  222.   for (i=0; i < ColorMapSize; i++) {
  223.     if (i < num_colors) {
  224.       if (colormap != NULL) {
  225. if (dinfo->cinfo->out_color_space == JCS_RGB) {
  226.   /* Normal case: RGB color map */
  227.   putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file);
  228.   putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file);
  229.   putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file);
  230. } else {
  231.   /* Grayscale "color map": possible if quantizing grayscale image */
  232.   put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift);
  233. }
  234.       } else {
  235. /* Create a gray-scale map of num_colors values, range 0..255 */
  236. put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1));
  237.       }
  238.     } else {
  239.       /* fill out the map to a power of 2 */
  240.       put_3bytes(dinfo, 0);
  241.     }
  242.   }
  243.   /* Write image separator and Image Descriptor */
  244.   putc(',', dinfo->pub.output_file); /* separator */
  245.   put_word(dinfo, 0); /* left/top offset */
  246.   put_word(dinfo, 0);
  247.   put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */
  248.   put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
  249.   /* flag byte: not interlaced, no local color map */
  250.   putc(0x00, dinfo->pub.output_file);
  251.   /* Write Initial Code Size byte */
  252.   putc(InitCodeSize, dinfo->pub.output_file);
  253.   /* Initialize for "compression" of image data */
  254.   compress_init(dinfo, InitCodeSize+1);
  255. }
  256. /*
  257.  * Startup: write the file header.
  258.  */
  259. METHODDEF(void)
  260. start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  261. {
  262.   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
  263.   if (cinfo->quantize_colors)
  264.     emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap);
  265.   else
  266.     emit_header(dest, 256, (JSAMPARRAY) NULL);
  267. }
  268. /*
  269.  * Write some pixel data.
  270.  * In this module rows_supplied will always be 1.
  271.  */
  272. METHODDEF(void)
  273. put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  274. JDIMENSION rows_supplied)
  275. {
  276.   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
  277.   register JSAMPROW ptr;
  278.   register JDIMENSION col;
  279.   ptr = dest->pub.buffer[0];
  280.   for (col = cinfo->output_width; col > 0; col--) {
  281.     compress_pixel(dest, GETJSAMPLE(*ptr++));
  282.   }
  283. }
  284. /*
  285.  * Finish up at the end of the file.
  286.  */
  287. METHODDEF(void)
  288. finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  289. {
  290.   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
  291.   /* Flush "compression" mechanism */
  292.   compress_term(dest);
  293.   /* Write a zero-length data block to end the series */
  294.   putc(0, dest->pub.output_file);
  295.   /* Write the GIF terminator mark */
  296.   putc(';', dest->pub.output_file);
  297.   /* Make sure we wrote the output file OK */
  298.   fflush(dest->pub.output_file);
  299.   if (ferror(dest->pub.output_file))
  300.     ERREXIT(cinfo, JERR_FILE_WRITE);
  301. }
  302. /*
  303.  * The module selection routine for GIF format output.
  304.  */
  305. GLOBAL(djpeg_dest_ptr)
  306. jinit_write_gif (j_decompress_ptr cinfo)
  307. {
  308.   gif_dest_ptr dest;
  309.   /* Create module interface object, fill in method pointers */
  310.   dest = (gif_dest_ptr)
  311.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  312.   SIZEOF(gif_dest_struct));
  313.   dest->cinfo = cinfo; /* make back link for subroutines */
  314.   dest->pub.start_output = start_output_gif;
  315.   dest->pub.put_pixel_rows = put_pixel_rows;
  316.   dest->pub.finish_output = finish_output_gif;
  317.   if (cinfo->out_color_space != JCS_GRAYSCALE &&
  318.       cinfo->out_color_space != JCS_RGB)
  319.     ERREXIT(cinfo, JERR_GIF_COLORSPACE);
  320.   /* Force quantization if color or if > 8 bits input */
  321.   if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) {
  322.     /* Force quantization to at most 256 colors */
  323.     cinfo->quantize_colors = TRUE;
  324.     if (cinfo->desired_number_of_colors > 256)
  325.       cinfo->desired_number_of_colors = 256;
  326.   }
  327.   /* Calculate output image dimensions so we can allocate space */
  328.   jpeg_calc_output_dimensions(cinfo);
  329.   if (cinfo->output_components != 1) /* safety check: just one component? */
  330.     ERREXIT(cinfo, JERR_GIF_BUG);
  331.   /* Create decompressor output buffer. */
  332.   dest->pub.buffer = (*cinfo->mem->alloc_sarray)
  333.     ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1);
  334.   dest->pub.buffer_height = 1;
  335.   return (djpeg_dest_ptr) dest;
  336. }
  337. #endif /* GIF_SUPPORTED */