home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / jpeg / jpegv4a.tar / jwrppm.c < prev    next >
C/C++ Source or Header  |  1993-02-06  |  9KB  |  338 lines

  1. /*
  2.  * jwrppm.c
  3.  *
  4.  * Copyright (C) 1991, 1992, 1993, 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.  *
  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.  * These routines are invoked via the methods put_pixel_rows, put_color_map,
  15.  * and output_init/term.
  16.  */
  17.  
  18. #include "jinclude.h"
  19.  
  20. #ifdef PPM_SUPPORTED
  21.  
  22.  
  23. /*
  24.  * Haven't yet got around to making this work with text-format output,
  25.  * hence cannot handle pixels wider than 8 bits.
  26.  */
  27.  
  28. #ifndef EIGHT_BIT_SAMPLES
  29.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  30. #endif
  31.  
  32.  
  33. /*
  34.  * On most systems, writing individual bytes with putc() is drastically less
  35.  * efficient than buffering a row at a time for fwrite().  But we must
  36.  * allocate the row buffer in near data space on PCs, because we are assuming
  37.  * small-data memory model, wherein fwrite() can't reach far memory.  If you
  38.  * need to process very wide images on a PC, you may have to use the putc()
  39.  * approach.  Also, there are still a few systems around wherein fwrite() is
  40.  * actually implemented as a putc() loop, in which case this buffer is a waste
  41.  * of space.  So the putc() method can be used by defining USE_PUTC_OUTPUT.
  42.  */
  43.  
  44. #ifndef USE_PUTC_OUTPUT
  45. static char * row_buffer;    /* holds 1 pixel row's worth of output */
  46. #endif
  47.  
  48.  
  49. /*
  50.  * Write the file header.
  51.  */
  52.  
  53. METHODDEF void
  54. output_init (decompress_info_ptr cinfo)
  55. {
  56.   if (cinfo->out_color_space == CS_GRAYSCALE) {
  57.     /* emit header for raw PGM format */
  58.     fprintf(cinfo->output_file, "P5\n%ld %ld\n%d\n",
  59.         cinfo->image_width, cinfo->image_height, 255);
  60. #ifndef USE_PUTC_OUTPUT
  61.     /* allocate space for row buffer: 1 byte/pixel */
  62.     row_buffer = (char *) (*cinfo->emethods->alloc_small)
  63.             ((size_t) (SIZEOF(char) * cinfo->image_width));
  64. #endif
  65.   } else if (cinfo->out_color_space == CS_RGB) {
  66.     /* emit header for raw PPM format */
  67.     fprintf(cinfo->output_file, "P6\n%ld %ld\n%d\n",
  68.         cinfo->image_width, cinfo->image_height, 255);
  69. #ifndef USE_PUTC_OUTPUT
  70.     /* allocate space for row buffer: 3 bytes/pixel */
  71.     row_buffer = (char *) (*cinfo->emethods->alloc_small)
  72.             ((size_t) (3 * SIZEOF(char) * cinfo->image_width));
  73. #endif
  74.   } else {
  75.     ERREXIT(cinfo->emethods, "PPM output must be grayscale or RGB");
  76.   }
  77. }
  78.  
  79.  
  80. /*
  81.  * Write some pixel data.
  82.  */
  83.  
  84. #ifdef USE_PUTC_OUTPUT
  85.  
  86. METHODDEF void
  87. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  88.         JSAMPIMAGE pixel_data)
  89. {
  90.   register FILE * outfile = cinfo->output_file;
  91.   register JSAMPROW ptr0, ptr1, ptr2;
  92.   register long col;
  93.   long width = cinfo->image_width;
  94.   int row;
  95.   
  96.   for (row = 0; row < num_rows; row++) {
  97.     ptr0 = pixel_data[0][row];
  98.     ptr1 = pixel_data[1][row];
  99.     ptr2 = pixel_data[2][row];
  100.     for (col = width; col > 0; col--) {
  101.       putc(GETJSAMPLE(*ptr0), outfile);
  102.       ptr0++;
  103.       putc(GETJSAMPLE(*ptr1), outfile);
  104.       ptr1++;
  105.       putc(GETJSAMPLE(*ptr2), outfile);
  106.       ptr2++;
  107.     }
  108.   }
  109. }
  110.  
  111. METHODDEF void
  112. put_gray_rows (decompress_info_ptr cinfo, int num_rows,
  113.            JSAMPIMAGE pixel_data)
  114. {
  115.   register FILE * outfile = cinfo->output_file;
  116.   register JSAMPROW ptr0;
  117.   register long col;
  118.   long width = cinfo->image_width;
  119.   int row;
  120.   
  121.   for (row = 0; row < num_rows; row++) {
  122.     ptr0 = pixel_data[0][row];
  123.     for (col = width; col > 0; col--) {
  124.       putc(GETJSAMPLE(*ptr0), outfile);
  125.       ptr0++;
  126.     }
  127.   }
  128. }
  129.  
  130. #else /* use row buffering */
  131.  
  132. METHODDEF void
  133. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  134.         JSAMPIMAGE pixel_data)
  135. {
  136.   FILE * outfile = cinfo->output_file;
  137.   register JSAMPROW ptr0, ptr1, ptr2;
  138.   register char * row_bufferptr;
  139.   register long col;
  140.   long width = cinfo->image_width;
  141.   int row;
  142.   
  143.   for (row = 0; row < num_rows; row++) {
  144.     ptr0 = pixel_data[0][row];
  145.     ptr1 = pixel_data[1][row];
  146.     ptr2 = pixel_data[2][row];
  147.     row_bufferptr = row_buffer;
  148.     for (col = width; col > 0; col--) {
  149.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
  150.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr1++);
  151.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr2++);
  152.     }
  153.     (void) JFWRITE(outfile, row_buffer, 3*width);
  154.   }
  155. }
  156.  
  157. METHODDEF void
  158. put_gray_rows (decompress_info_ptr cinfo, int num_rows,
  159.            JSAMPIMAGE pixel_data)
  160. {
  161.   FILE * outfile = cinfo->output_file;
  162.   register JSAMPROW ptr0;
  163.   register char * row_bufferptr;
  164.   register long col;
  165.   long width = cinfo->image_width;
  166.   int row;
  167.   
  168.   for (row = 0; row < num_rows; row++) {
  169.     ptr0 = pixel_data[0][row];
  170.     row_bufferptr = row_buffer;
  171.     for (col = width; col > 0; col--) {
  172.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
  173.     }
  174.     (void) JFWRITE(outfile, row_buffer, width);
  175.   }
  176. }
  177.  
  178. #endif /* USE_PUTC_OUTPUT */
  179.  
  180.  
  181. /*
  182.  * Write some pixel data when color quantization is in effect.
  183.  */
  184.  
  185. #ifdef USE_PUTC_OUTPUT
  186.  
  187. METHODDEF void
  188. put_demapped_rgb (decompress_info_ptr cinfo, int num_rows,
  189.           JSAMPIMAGE pixel_data)
  190. {
  191.   register FILE * outfile = cinfo->output_file;
  192.   register JSAMPROW ptr;
  193.   register JSAMPROW color_map0 = cinfo->colormap[0];
  194.   register JSAMPROW color_map1 = cinfo->colormap[1];
  195.   register JSAMPROW color_map2 = cinfo->colormap[2];
  196.   register int pixval;
  197.   register long col;
  198.   long width = cinfo->image_width;
  199.   int row;
  200.   
  201.   for (row = 0; row < num_rows; row++) {
  202.     ptr = pixel_data[0][row];
  203.     for (col = width; col > 0; col--) {
  204.       pixval = GETJSAMPLE(*ptr++);
  205.       putc(GETJSAMPLE(color_map0[pixval]), outfile);
  206.       putc(GETJSAMPLE(color_map1[pixval]), outfile);
  207.       putc(GETJSAMPLE(color_map2[pixval]), outfile);
  208.     }
  209.   }
  210. }
  211.  
  212. METHODDEF void
  213. put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
  214.            JSAMPIMAGE pixel_data)
  215. {
  216.   register FILE * outfile = cinfo->output_file;
  217.   register JSAMPROW ptr;
  218.   register JSAMPROW color_map0 = cinfo->colormap[0];
  219.   register int pixval;
  220.   register long col;
  221.   long width = cinfo->image_width;
  222.   int row;
  223.   
  224.   for (row = 0; row < num_rows; row++) {
  225.     ptr = pixel_data[0][row];
  226.     for (col = width; col > 0; col--) {
  227.       pixval = GETJSAMPLE(*ptr++);
  228.       putc(GETJSAMPLE(color_map0[pixval]), outfile);
  229.     }
  230.   }
  231. }
  232.  
  233. #else /* use row buffering */
  234.  
  235. METHODDEF void
  236. put_demapped_rgb (decompress_info_ptr cinfo, int num_rows,
  237.           JSAMPIMAGE pixel_data)
  238. {
  239.   FILE * outfile = cinfo->output_file;
  240.   register JSAMPROW ptr;
  241.   register char * row_bufferptr;
  242.   register JSAMPROW color_map0 = cinfo->colormap[0];
  243.   register JSAMPROW color_map1 = cinfo->colormap[1];
  244.   register JSAMPROW color_map2 = cinfo->colormap[2];
  245.   register int pixval;
  246.   register long col;
  247.   long width = cinfo->image_width;
  248.   int row;
  249.   
  250.   for (row = 0; row < num_rows; row++) {
  251.     ptr = pixel_data[0][row];
  252.     row_bufferptr = row_buffer;
  253.     for (col = width; col > 0; col--) {
  254.       pixval = GETJSAMPLE(*ptr++);
  255.       *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
  256.       *row_bufferptr++ = (char) GETJSAMPLE(color_map1[pixval]);
  257.       *row_bufferptr++ = (char) GETJSAMPLE(color_map2[pixval]);
  258.     }
  259.     (void) JFWRITE(outfile, row_buffer, 3*width);
  260.   }
  261. }
  262.  
  263. METHODDEF void
  264. put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
  265.            JSAMPIMAGE pixel_data)
  266. {
  267.   FILE * outfile = cinfo->output_file;
  268.   register JSAMPROW ptr;
  269.   register char * row_bufferptr;
  270.   register JSAMPROW color_map0 = cinfo->colormap[0];
  271.   register int pixval;
  272.   register long col;
  273.   long width = cinfo->image_width;
  274.   int row;
  275.   
  276.   for (row = 0; row < num_rows; row++) {
  277.     ptr = pixel_data[0][row];
  278.     row_bufferptr = row_buffer;
  279.     for (col = width; col > 0; col--) {
  280.       pixval = GETJSAMPLE(*ptr++);
  281.       *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
  282.     }
  283.     (void) JFWRITE(outfile, row_buffer, width);
  284.   }
  285. }
  286.  
  287. #endif /* USE_PUTC_OUTPUT */
  288.  
  289.  
  290. /*
  291.  * Write the color map.
  292.  * For PPM output, we just remember to demap the output data!
  293.  */
  294.  
  295. METHODDEF void
  296. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  297. {
  298.   if (cinfo->out_color_space == CS_RGB)
  299.     cinfo->methods->put_pixel_rows = put_demapped_rgb;
  300.   else
  301.     cinfo->methods->put_pixel_rows = put_demapped_gray;
  302. }
  303.  
  304.  
  305. /*
  306.  * Finish up at the end of the file.
  307.  */
  308.  
  309. METHODDEF void
  310. output_term (decompress_info_ptr cinfo)
  311. {
  312.   /* No work except to make sure we wrote the output file OK; */
  313.   /* we let free_all release any workspace */
  314.   fflush(cinfo->output_file);
  315.   if (ferror(cinfo->output_file))
  316.     ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?");
  317. }
  318.  
  319.  
  320. /*
  321.  * The method selection routine for PPM format output.
  322.  * This should be called from d_ui_method_selection if PPM output is wanted.
  323.  */
  324.  
  325. GLOBAL void
  326. jselwppm (decompress_info_ptr cinfo)
  327. {
  328.   cinfo->methods->output_init = output_init;
  329.   cinfo->methods->put_color_map = put_color_map;
  330.   if (cinfo->out_color_space == CS_RGB)
  331.     cinfo->methods->put_pixel_rows = put_pixel_rows;
  332.   else
  333.     cinfo->methods->put_pixel_rows = put_gray_rows;
  334.   cinfo->methods->output_term = output_term;
  335. }
  336.  
  337. #endif /* PPM_SUPPORTED */
  338.