source: trunk/third/jpeg/wrppm.c @ 15227

Revision 15227, 8.1 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15226, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * wrppm.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 PPM/PGM format.
9 * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
10 * The PBMPLUS library is NOT required to compile this software
11 * (but it is highly useful as a set of PPM image manipulation programs).
12 *
13 * These routines may need modification for non-Unix environments or
14 * specialized applications.  As they stand, they assume output to
15 * an ordinary stdio stream.
16 */
17
18#include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
19
20#ifdef PPM_SUPPORTED
21
22
23/*
24 * For 12-bit JPEG data, we either downscale the values to 8 bits
25 * (to write standard byte-per-sample PPM/PGM files), or output
26 * nonstandard word-per-sample PPM/PGM files.  Downscaling is done
27 * if PPM_NORAWWORD is defined (this can be done in the Makefile
28 * or in jconfig.h).
29 * (When the core library supports data precision reduction, a cleaner
30 * implementation will be to ask for that instead.)
31 */
32
33#if BITS_IN_JSAMPLE == 8
34#define PUTPPMSAMPLE(ptr,v)  *ptr++ = (char) (v)
35#define BYTESPERSAMPLE 1
36#define PPM_MAXVAL 255
37#else
38#ifdef PPM_NORAWWORD
39#define PUTPPMSAMPLE(ptr,v)  *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8))
40#define BYTESPERSAMPLE 1
41#define PPM_MAXVAL 255
42#else
43/* The word-per-sample format always puts the LSB first. */
44#define PUTPPMSAMPLE(ptr,v)                     \
45        { register int val_ = v;                \
46          *ptr++ = (char) (val_ & 0xFF);        \
47          *ptr++ = (char) ((val_ >> 8) & 0xFF); \
48        }
49#define BYTESPERSAMPLE 2
50#define PPM_MAXVAL ((1<<BITS_IN_JSAMPLE)-1)
51#endif
52#endif
53
54
55/*
56 * When JSAMPLE is the same size as char, we can just fwrite() the
57 * decompressed data to the PPM or PGM file.  On PCs, in order to make this
58 * work the output buffer must be allocated in near data space, because we are
59 * assuming small-data memory model wherein fwrite() can't reach far memory.
60 * If you need to process very wide images on a PC, you might have to compile
61 * in large-memory model, or else replace fwrite() with a putc() loop ---
62 * which will be much slower.
63 */
64
65
66/* Private version of data destination object */
67
68typedef struct {
69  struct djpeg_dest_struct pub; /* public fields */
70
71  /* Usually these two pointers point to the same place: */
72  char *iobuffer;               /* fwrite's I/O buffer */
73  JSAMPROW pixrow;              /* decompressor output buffer */
74  size_t buffer_width;          /* width of I/O buffer */
75  JDIMENSION samples_per_row;   /* JSAMPLEs per output row */
76} ppm_dest_struct;
77
78typedef ppm_dest_struct * ppm_dest_ptr;
79
80
81/*
82 * Write some pixel data.
83 * In this module rows_supplied will always be 1.
84 *
85 * put_pixel_rows handles the "normal" 8-bit case where the decompressor
86 * output buffer is physically the same as the fwrite buffer.
87 */
88
89METHODDEF(void)
90put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
91                JDIMENSION rows_supplied)
92{
93  ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
94
95  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
96}
97
98
99/*
100 * This code is used when we have to copy the data and apply a pixel
101 * format translation.  Typically this only happens in 12-bit mode.
102 */
103
104METHODDEF(void)
105copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
106                 JDIMENSION rows_supplied)
107{
108  ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
109  register char * bufferptr;
110  register JSAMPROW ptr;
111  register JDIMENSION col;
112
113  ptr = dest->pub.buffer[0];
114  bufferptr = dest->iobuffer;
115  for (col = dest->samples_per_row; col > 0; col--) {
116    PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++));
117  }
118  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
119}
120
121
122/*
123 * Write some pixel data when color quantization is in effect.
124 * We have to demap the color index values to straight data.
125 */
126
127METHODDEF(void)
128put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
129                  JDIMENSION rows_supplied)
130{
131  ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
132  register char * bufferptr;
133  register int pixval;
134  register JSAMPROW ptr;
135  register JSAMPROW color_map0 = cinfo->colormap[0];
136  register JSAMPROW color_map1 = cinfo->colormap[1];
137  register JSAMPROW color_map2 = cinfo->colormap[2];
138  register JDIMENSION col;
139
140  ptr = dest->pub.buffer[0];
141  bufferptr = dest->iobuffer;
142  for (col = cinfo->output_width; col > 0; col--) {
143    pixval = GETJSAMPLE(*ptr++);
144    PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval]));
145    PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval]));
146    PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval]));
147  }
148  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
149}
150
151
152METHODDEF(void)
153put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
154                   JDIMENSION rows_supplied)
155{
156  ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
157  register char * bufferptr;
158  register JSAMPROW ptr;
159  register JSAMPROW color_map = cinfo->colormap[0];
160  register JDIMENSION col;
161
162  ptr = dest->pub.buffer[0];
163  bufferptr = dest->iobuffer;
164  for (col = cinfo->output_width; col > 0; col--) {
165    PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]));
166  }
167  (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
168}
169
170
171/*
172 * Startup: write the file header.
173 */
174
175METHODDEF(void)
176start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
177{
178  ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
179
180  /* Emit file header */
181  switch (cinfo->out_color_space) {
182  case JCS_GRAYSCALE:
183    /* emit header for raw PGM format */
184    fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n",
185            (long) cinfo->output_width, (long) cinfo->output_height,
186            PPM_MAXVAL);
187    break;
188  case JCS_RGB:
189    /* emit header for raw PPM format */
190    fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n",
191            (long) cinfo->output_width, (long) cinfo->output_height,
192            PPM_MAXVAL);
193    break;
194  default:
195    ERREXIT(cinfo, JERR_PPM_COLORSPACE);
196  }
197}
198
199
200/*
201 * Finish up at the end of the file.
202 */
203
204METHODDEF(void)
205finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
206{
207  /* Make sure we wrote the output file OK */
208  fflush(dinfo->output_file);
209  if (ferror(dinfo->output_file))
210    ERREXIT(cinfo, JERR_FILE_WRITE);
211}
212
213
214/*
215 * The module selection routine for PPM format output.
216 */
217
218GLOBAL(djpeg_dest_ptr)
219jinit_write_ppm (j_decompress_ptr cinfo)
220{
221  ppm_dest_ptr dest;
222
223  /* Create module interface object, fill in method pointers */
224  dest = (ppm_dest_ptr)
225      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
226                                  SIZEOF(ppm_dest_struct));
227  dest->pub.start_output = start_output_ppm;
228  dest->pub.finish_output = finish_output_ppm;
229
230  /* Calculate output image dimensions so we can allocate space */
231  jpeg_calc_output_dimensions(cinfo);
232
233  /* Create physical I/O buffer.  Note we make this near on a PC. */
234  dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
235  dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char));
236  dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
237    ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);
238
239  if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 ||
240      SIZEOF(JSAMPLE) != SIZEOF(char)) {
241    /* When quantizing, we need an output buffer for colormap indexes
242     * that's separate from the physical I/O buffer.  We also need a
243     * separate buffer if pixel format translation must take place.
244     */
245    dest->pub.buffer = (*cinfo->mem->alloc_sarray)
246      ((j_common_ptr) cinfo, JPOOL_IMAGE,
247       cinfo->output_width * cinfo->output_components, (JDIMENSION) 1);
248    dest->pub.buffer_height = 1;
249    if (! cinfo->quantize_colors)
250      dest->pub.put_pixel_rows = copy_pixel_rows;
251    else if (cinfo->out_color_space == JCS_GRAYSCALE)
252      dest->pub.put_pixel_rows = put_demapped_gray;
253    else
254      dest->pub.put_pixel_rows = put_demapped_rgb;
255  } else {
256    /* We will fwrite() directly from decompressor output buffer. */
257    /* Synthesize a JSAMPARRAY pointer structure */
258    /* Cast here implies near->far pointer conversion on PCs */
259    dest->pixrow = (JSAMPROW) dest->iobuffer;
260    dest->pub.buffer = & dest->pixrow;
261    dest->pub.buffer_height = 1;
262    dest->pub.put_pixel_rows = put_pixel_rows;
263  }
264
265  return (djpeg_dest_ptr) dest;
266}
267
268#endif /* PPM_SUPPORTED */
Note: See TracBrowser for help on using the repository browser.