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