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