| 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 |