PageRenderTime 38ms CodeModel.GetById 15ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibJPEG/wrtarga.c

https://bitbucket.org/cabalistic/ogredeps/
C | 253 lines | 151 code | 44 blank | 58 comment | 24 complexity | aca4ae26407d3a990bcd9950cf9085b2 MD5 | raw file
  1/*
  2 * wrtarga.c
  3 *
  4 * Copyright (C) 1991-1996, 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 Targa format.
  9 *
 10 * These routines may need modification for non-Unix environments or
 11 * specialized applications.  As they stand, they assume output to
 12 * an ordinary stdio stream.
 13 *
 14 * Based on code contributed by Lee Daniel Crocker.
 15 */
 16
 17#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
 18
 19#ifdef TARGA_SUPPORTED
 20
 21
 22/*
 23 * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
 24 * This is not yet implemented.
 25 */
 26
 27#if BITS_IN_JSAMPLE != 8
 28  Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
 29#endif
 30
 31/*
 32 * The output buffer needs to be writable by fwrite().  On PCs, we must
 33 * allocate the buffer in near data space, because we are assuming small-data
 34 * memory model, wherein fwrite() can't reach far memory.  If you need to
 35 * process very wide images on a PC, you might have to compile in large-memory
 36 * model, or else replace fwrite() with a putc() loop --- which will be much
 37 * slower.
 38 */
 39
 40
 41/* Private version of data destination object */
 42
 43typedef struct {
 44  struct djpeg_dest_struct pub;	/* public fields */
 45
 46  char *iobuffer;		/* physical I/O buffer */
 47  JDIMENSION buffer_width;	/* width of one row */
 48} tga_dest_struct;
 49
 50typedef tga_dest_struct * tga_dest_ptr;
 51
 52
 53LOCAL(void)
 54write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
 55/* Create and write a Targa header */
 56{
 57  char targaheader[18];
 58
 59  /* Set unused fields of header to 0 */
 60  MEMZERO(targaheader, SIZEOF(targaheader));
 61
 62  if (num_colors > 0) {
 63    targaheader[1] = 1;		/* color map type 1 */
 64    targaheader[5] = (char) (num_colors & 0xFF);
 65    targaheader[6] = (char) (num_colors >> 8);
 66    targaheader[7] = 24;	/* 24 bits per cmap entry */
 67  }
 68
 69  targaheader[12] = (char) (cinfo->output_width & 0xFF);
 70  targaheader[13] = (char) (cinfo->output_width >> 8);
 71  targaheader[14] = (char) (cinfo->output_height & 0xFF);
 72  targaheader[15] = (char) (cinfo->output_height >> 8);
 73  targaheader[17] = 0x20;	/* Top-down, non-interlaced */
 74
 75  if (cinfo->out_color_space == JCS_GRAYSCALE) {
 76    targaheader[2] = 3;		/* image type = uncompressed gray-scale */
 77    targaheader[16] = 8;	/* bits per pixel */
 78  } else {			/* must be RGB */
 79    if (num_colors > 0) {
 80      targaheader[2] = 1;	/* image type = colormapped RGB */
 81      targaheader[16] = 8;
 82    } else {
 83      targaheader[2] = 2;	/* image type = uncompressed RGB */
 84      targaheader[16] = 24;
 85    }
 86  }
 87
 88  if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
 89    ERREXIT(cinfo, JERR_FILE_WRITE);
 90}
 91
 92
 93/*
 94 * Write some pixel data.
 95 * In this module rows_supplied will always be 1.
 96 */
 97
 98METHODDEF(void)
 99put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
100		JDIMENSION rows_supplied)
101/* used for unquantized full-color output */
102{
103  tga_dest_ptr dest = (tga_dest_ptr) dinfo;
104  register JSAMPROW inptr;
105  register char * outptr;
106  register JDIMENSION col;
107
108  inptr = dest->pub.buffer[0];
109  outptr = dest->iobuffer;
110  for (col = cinfo->output_width; col > 0; col--) {
111    outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
112    outptr[1] = (char) GETJSAMPLE(inptr[1]);
113    outptr[2] = (char) GETJSAMPLE(inptr[0]);
114    inptr += 3, outptr += 3;
115  }
116  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
117}
118
119METHODDEF(void)
120put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
121	       JDIMENSION rows_supplied)
122/* used for grayscale OR quantized color output */
123{
124  tga_dest_ptr dest = (tga_dest_ptr) dinfo;
125  register JSAMPROW inptr;
126  register char * outptr;
127  register JDIMENSION col;
128
129  inptr = dest->pub.buffer[0];
130  outptr = dest->iobuffer;
131  for (col = cinfo->output_width; col > 0; col--) {
132    *outptr++ = (char) GETJSAMPLE(*inptr++);
133  }
134  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
135}
136
137
138/*
139 * Write some demapped pixel data when color quantization is in effect.
140 * For Targa, this is only applied to grayscale data.
141 */
142
143METHODDEF(void)
144put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
145		   JDIMENSION rows_supplied)
146{
147  tga_dest_ptr dest = (tga_dest_ptr) dinfo;
148  register JSAMPROW inptr;
149  register char * outptr;
150  register JSAMPROW color_map0 = cinfo->colormap[0];
151  register JDIMENSION col;
152
153  inptr = dest->pub.buffer[0];
154  outptr = dest->iobuffer;
155  for (col = cinfo->output_width; col > 0; col--) {
156    *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
157  }
158  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
159}
160
161
162/*
163 * Startup: write the file header.
164 */
165
166METHODDEF(void)
167start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
168{
169  tga_dest_ptr dest = (tga_dest_ptr) dinfo;
170  int num_colors, i;
171  FILE *outfile;
172
173  if (cinfo->out_color_space == JCS_GRAYSCALE) {
174    /* Targa doesn't have a mapped grayscale format, so we will */
175    /* demap quantized gray output.  Never emit a colormap. */
176    write_header(cinfo, dinfo, 0);
177    if (cinfo->quantize_colors)
178      dest->pub.put_pixel_rows = put_demapped_gray;
179    else
180      dest->pub.put_pixel_rows = put_gray_rows;
181  } else if (cinfo->out_color_space == JCS_RGB) {
182    if (cinfo->quantize_colors) {
183      /* We only support 8-bit colormap indexes, so only 256 colors */
184      num_colors = cinfo->actual_number_of_colors;
185      if (num_colors > 256)
186	ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
187      write_header(cinfo, dinfo, num_colors);
188      /* Write the colormap.  Note Targa uses BGR byte order */
189      outfile = dest->pub.output_file;
190      for (i = 0; i < num_colors; i++) {
191	putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
192	putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
193	putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
194      }
195      dest->pub.put_pixel_rows = put_gray_rows;
196    } else {
197      write_header(cinfo, dinfo, 0);
198      dest->pub.put_pixel_rows = put_pixel_rows;
199    }
200  } else {
201    ERREXIT(cinfo, JERR_TGA_COLORSPACE);
202  }
203}
204
205
206/*
207 * Finish up at the end of the file.
208 */
209
210METHODDEF(void)
211finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
212{
213  /* Make sure we wrote the output file OK */
214  fflush(dinfo->output_file);
215  if (ferror(dinfo->output_file))
216    ERREXIT(cinfo, JERR_FILE_WRITE);
217}
218
219
220/*
221 * The module selection routine for Targa format output.
222 */
223
224GLOBAL(djpeg_dest_ptr)
225jinit_write_targa (j_decompress_ptr cinfo)
226{
227  tga_dest_ptr dest;
228
229  /* Create module interface object, fill in method pointers */
230  dest = (tga_dest_ptr)
231      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
232				  SIZEOF(tga_dest_struct));
233  dest->pub.start_output = start_output_tga;
234  dest->pub.finish_output = finish_output_tga;
235
236  /* Calculate output image dimensions so we can allocate space */
237  jpeg_calc_output_dimensions(cinfo);
238
239  /* Create I/O buffer.  Note we make this near on a PC. */
240  dest->buffer_width = cinfo->output_width * cinfo->output_components;
241  dest->iobuffer = (char *)
242    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
243				(size_t) (dest->buffer_width * SIZEOF(char)));
244
245  /* Create decompressor output buffer. */
246  dest->pub.buffer = (*cinfo->mem->alloc_sarray)
247    ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
248  dest->pub.buffer_height = 1;
249
250  return (djpeg_dest_ptr) dest;
251}
252
253#endif /* TARGA_SUPPORTED */