Back to index

plt-scheme  4.2.1
wrtarga.c
Go to the documentation of this file.
00001 /*
00002  * wrtarga.c
00003  *
00004  * Copyright (C) 1991-1996, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains routines to write output images in Targa format.
00009  *
00010  * These routines may need modification for non-Unix environments or
00011  * specialized applications.  As they stand, they assume output to
00012  * an ordinary stdio stream.
00013  *
00014  * Based on code contributed by Lee Daniel Crocker.
00015  */
00016 
00017 #include "cdjpeg.h"         /* Common decls for cjpeg/djpeg applications */
00018 
00019 #ifdef TARGA_SUPPORTED
00020 
00021 
00022 /*
00023  * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
00024  * This is not yet implemented.
00025  */
00026 
00027 #if BITS_IN_JSAMPLE != 8
00028   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
00029 #endif
00030 
00031 /*
00032  * The output buffer needs to be writable by fwrite().  On PCs, we must
00033  * allocate the buffer in near data space, because we are assuming small-data
00034  * memory model, wherein fwrite() can't reach far memory.  If you need to
00035  * process very wide images on a PC, you might have to compile in large-memory
00036  * model, or else replace fwrite() with a putc() loop --- which will be much
00037  * slower.
00038  */
00039 
00040 
00041 /* Private version of data destination object */
00042 
00043 typedef struct {
00044   struct djpeg_dest_struct pub;    /* public fields */
00045 
00046   char *iobuffer;           /* physical I/O buffer */
00047   JDIMENSION buffer_width;  /* width of one row */
00048 } tga_dest_struct;
00049 
00050 typedef tga_dest_struct * tga_dest_ptr;
00051 
00052 
00053 LOCAL(void)
00054 write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
00055 /* Create and write a Targa header */
00056 {
00057   char targaheader[18];
00058 
00059   /* Set unused fields of header to 0 */
00060   MEMZERO(targaheader, SIZEOF(targaheader));
00061 
00062   if (num_colors > 0) {
00063     targaheader[1] = 1;            /* color map type 1 */
00064     targaheader[5] = (char) (num_colors & 0xFF);
00065     targaheader[6] = (char) (num_colors >> 8);
00066     targaheader[7] = 24;    /* 24 bits per cmap entry */
00067   }
00068 
00069   targaheader[12] = (char) (cinfo->output_width & 0xFF);
00070   targaheader[13] = (char) (cinfo->output_width >> 8);
00071   targaheader[14] = (char) (cinfo->output_height & 0xFF);
00072   targaheader[15] = (char) (cinfo->output_height >> 8);
00073   targaheader[17] = 0x20;   /* Top-down, non-interlaced */
00074 
00075   if (cinfo->out_color_space == JCS_GRAYSCALE) {
00076     targaheader[2] = 3;            /* image type = uncompressed gray-scale */
00077     targaheader[16] = 8;    /* bits per pixel */
00078   } else {                  /* must be RGB */
00079     if (num_colors > 0) {
00080       targaheader[2] = 1;   /* image type = colormapped RGB */
00081       targaheader[16] = 8;
00082     } else {
00083       targaheader[2] = 2;   /* image type = uncompressed RGB */
00084       targaheader[16] = 24;
00085     }
00086   }
00087 
00088   if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
00089     ERREXIT(cinfo, JERR_FILE_WRITE);
00090 }
00091 
00092 
00093 /*
00094  * Write some pixel data.
00095  * In this module rows_supplied will always be 1.
00096  */
00097 
00098 METHODDEF(void)
00099 put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00100               JDIMENSION rows_supplied)
00101 /* used for unquantized full-color output */
00102 {
00103   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
00104   register JSAMPROW inptr;
00105   register char * outptr;
00106   register JDIMENSION col;
00107 
00108   inptr = dest->pub.buffer[0];
00109   outptr = dest->iobuffer;
00110   for (col = cinfo->output_width; col > 0; col--) {
00111     outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
00112     outptr[1] = (char) GETJSAMPLE(inptr[1]);
00113     outptr[2] = (char) GETJSAMPLE(inptr[0]);
00114     inptr += 3, outptr += 3;
00115   }
00116   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
00117 }
00118 
00119 METHODDEF(void)
00120 put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00121               JDIMENSION rows_supplied)
00122 /* used for grayscale OR quantized color output */
00123 {
00124   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
00125   register JSAMPROW inptr;
00126   register char * outptr;
00127   register JDIMENSION col;
00128 
00129   inptr = dest->pub.buffer[0];
00130   outptr = dest->iobuffer;
00131   for (col = cinfo->output_width; col > 0; col--) {
00132     *outptr++ = (char) GETJSAMPLE(*inptr++);
00133   }
00134   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
00135 }
00136 
00137 
00138 /*
00139  * Write some demapped pixel data when color quantization is in effect.
00140  * For Targa, this is only applied to grayscale data.
00141  */
00142 
00143 METHODDEF(void)
00144 put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00145                  JDIMENSION rows_supplied)
00146 {
00147   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
00148   register JSAMPROW inptr;
00149   register char * outptr;
00150   register JSAMPROW color_map0 = cinfo->colormap[0];
00151   register JDIMENSION col;
00152 
00153   inptr = dest->pub.buffer[0];
00154   outptr = dest->iobuffer;
00155   for (col = cinfo->output_width; col > 0; col--) {
00156     *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
00157   }
00158   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
00159 }
00160 
00161 
00162 /*
00163  * Startup: write the file header.
00164  */
00165 
00166 METHODDEF(void)
00167 start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00168 {
00169   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
00170   int num_colors, i;
00171   FILE *outfile;
00172 
00173   if (cinfo->out_color_space == JCS_GRAYSCALE) {
00174     /* Targa doesn't have a mapped grayscale format, so we will */
00175     /* demap quantized gray output.  Never emit a colormap. */
00176     write_header(cinfo, dinfo, 0);
00177     if (cinfo->quantize_colors)
00178       dest->pub.put_pixel_rows = put_demapped_gray;
00179     else
00180       dest->pub.put_pixel_rows = put_gray_rows;
00181   } else if (cinfo->out_color_space == JCS_RGB) {
00182     if (cinfo->quantize_colors) {
00183       /* We only support 8-bit colormap indexes, so only 256 colors */
00184       num_colors = cinfo->actual_number_of_colors;
00185       if (num_colors > 256)
00186        ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
00187       write_header(cinfo, dinfo, num_colors);
00188       /* Write the colormap.  Note Targa uses BGR byte order */
00189       outfile = dest->pub.output_file;
00190       for (i = 0; i < num_colors; i++) {
00191        putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
00192        putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
00193        putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
00194       }
00195       dest->pub.put_pixel_rows = put_gray_rows;
00196     } else {
00197       write_header(cinfo, dinfo, 0);
00198       dest->pub.put_pixel_rows = put_pixel_rows;
00199     }
00200   } else {
00201     ERREXIT(cinfo, JERR_TGA_COLORSPACE);
00202   }
00203 }
00204 
00205 
00206 /*
00207  * Finish up at the end of the file.
00208  */
00209 
00210 METHODDEF(void)
00211 finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00212 {
00213   /* Make sure we wrote the output file OK */
00214   fflush(dinfo->output_file);
00215   if (ferror(dinfo->output_file))
00216     ERREXIT(cinfo, JERR_FILE_WRITE);
00217 }
00218 
00219 
00220 /*
00221  * The module selection routine for Targa format output.
00222  */
00223 
00224 GLOBAL(djpeg_dest_ptr)
00225 jinit_write_targa (j_decompress_ptr cinfo)
00226 {
00227   tga_dest_ptr dest;
00228 
00229   /* Create module interface object, fill in method pointers */
00230   dest = (tga_dest_ptr)
00231       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00232                               SIZEOF(tga_dest_struct));
00233   dest->pub.start_output = start_output_tga;
00234   dest->pub.finish_output = finish_output_tga;
00235 
00236   /* Calculate output image dimensions so we can allocate space */
00237   jpeg_calc_output_dimensions(cinfo);
00238 
00239   /* Create I/O buffer.  Note we make this near on a PC. */
00240   dest->buffer_width = cinfo->output_width * cinfo->output_components;
00241   dest->iobuffer = (char *)
00242     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00243                             (size_t) (dest->buffer_width * SIZEOF(char)));
00244 
00245   /* Create decompressor output buffer. */
00246   dest->pub.buffer = (*cinfo->mem->alloc_sarray)
00247     ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
00248   dest->pub.buffer_height = 1;
00249 
00250   return (djpeg_dest_ptr) dest;
00251 }
00252 
00253 #endif /* TARGA_SUPPORTED */