home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / compresn / jpegv3sr / jwrrle.c < prev    next >
C/C++ Source or Header  |  1992-03-02  |  7KB  |  233 lines

  1. /*
  2.  * jwrrle.c
  3.  *
  4.  * Copyright (C) 1991, 1992, 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 RLE format.
  9.  * The Utah Raster Toolkit library is required (version 3.0).
  10.  *
  11.  * These routines may need modification for non-Unix environments or
  12.  * specialized applications.  As they stand, they assume output to
  13.  * an ordinary stdio stream.
  14.  *
  15.  * These routines are invoked via the methods put_pixel_rows, put_color_map,
  16.  * and output_init/term.
  17.  *
  18.  * Based on code contributed by Mike Lijewski.
  19.  */
  20.  
  21. #include "jinclude.h"
  22.  
  23. #ifdef RLE_SUPPORTED
  24.  
  25. /* rle.h is provided by the Utah Raster Toolkit. */
  26.  
  27. #include <rle.h>
  28.  
  29.  
  30. /*
  31.  * output_term assumes that JSAMPLE has the same representation as rle_pixel,
  32.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  33.  */
  34.  
  35. #ifndef EIGHT_BIT_SAMPLES
  36.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  37. #endif
  38.  
  39.  
  40. /*
  41.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  42.  * from JPEG's top-to-bottom order.  To do this, we save the outgoing data
  43.  * in virtual array(s) during put_pixel_row calls, then actually emit the
  44.  * RLE file during output_term.  We use one virtual array if the output is
  45.  * grayscale or colormapped, more if it is full color.
  46.  */
  47.  
  48. #define MAX_CHANS    4    /* allow up to four color components */
  49. static big_sarray_ptr channels[MAX_CHANS]; /* Virtual arrays for saved data */
  50.  
  51. static long cur_output_row;    /* next row# to write to virtual array(s) */
  52.  
  53.  
  54. /*
  55.  * For now, if we emit an RLE color map then it is always 256 entries long,
  56.  * though not all of the entries need be used.
  57.  */
  58.  
  59. #define CMAPBITS    8
  60. #define CMAPLENGTH    (1<<(CMAPBITS))
  61.  
  62. static rle_map *output_colormap; /* RLE-style color map, or NULL if none */
  63. static int number_colors;    /* Number of colors actually used */
  64.  
  65.  
  66. /*
  67.  * Write the file header.
  68.  *
  69.  * In this module it's easier to wait till output_term to actually write
  70.  * anything; here we just request the big arrays we'll need.
  71.  */
  72.  
  73. METHODDEF void
  74. output_init (decompress_info_ptr cinfo)
  75. {
  76.   short ci;
  77.   
  78.   if (cinfo->final_out_comps > MAX_CHANS)
  79.     ERREXIT1(cinfo->emethods, "Cannot handle %d output channels for RLE",
  80.          cinfo->final_out_comps);
  81.   
  82.   for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  83.     channels[ci] = (*cinfo->emethods->request_big_sarray)
  84.             (cinfo->image_width, cinfo->image_height, 1L);
  85.   }
  86.   
  87.   output_colormap = NULL;    /* No output colormap as yet */
  88.   number_colors = 0;
  89.   cur_output_row = 0;        /* Start filling virtual arrays at row 0 */
  90.  
  91.   cinfo->total_passes++;    /* count file writing as separate pass */
  92. }
  93.  
  94.  
  95. /*
  96.  * Write some pixel data.
  97.  *
  98.  * This routine just saves the data away in virtual arrays.
  99.  */
  100.  
  101. METHODDEF void
  102. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  103.         JSAMPIMAGE pixel_data)
  104. {
  105.   JSAMPROW outputrow[1];    /* a pseudo JSAMPARRAY structure */
  106.   int row;
  107.   short ci;
  108.   
  109.   for (row = 0; row < num_rows; row++) {
  110.     for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  111.       outputrow[0] = *((*cinfo->emethods->access_big_sarray)
  112.             (channels[ci], cur_output_row, TRUE));
  113.       jcopy_sample_rows(pixel_data[ci], row, outputrow, 0,
  114.             1, cinfo->image_width);
  115.     }
  116.     cur_output_row++;
  117.   }
  118. }
  119.  
  120.  
  121. /*
  122.  * Write the color map.
  123.  *
  124.  *  For RLE output we just save the colormap for the output stage.
  125.  */
  126.  
  127. METHODDEF void
  128. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  129. {
  130.   size_t cmapsize;
  131.   short ci;
  132.   int i;
  133.  
  134.   if (num_colors > CMAPLENGTH)
  135.     ERREXIT1(cinfo->emethods, "Cannot handle %d colormap entries for RLE",
  136.          num_colors);
  137.  
  138.   /* Allocate storage for RLE-style cmap, zero any extra entries */
  139.   cmapsize = cinfo->color_out_comps * CMAPLENGTH * SIZEOF(rle_map);
  140.   output_colormap = (rle_map *) (*cinfo->emethods->alloc_small) (cmapsize);
  141.   MEMZERO((void *) output_colormap, cmapsize);
  142.  
  143.   /* Save away data in RLE format --- note 8-bit left shift! */
  144.   /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
  145.   for (ci = 0; ci < cinfo->color_out_comps; ci++) {
  146.     for (i = 0; i < num_colors; i++) {
  147.       output_colormap[ci * CMAPLENGTH + i] = GETJSAMPLE(colormap[ci][i]) << 8;
  148.     }
  149.   }
  150.   number_colors = num_colors;
  151. }
  152.  
  153.  
  154. /*
  155.  * Finish up at the end of the file.
  156.  *
  157.  * Here is where we really output the RLE file.
  158.  */
  159.  
  160. METHODDEF void
  161. output_term (decompress_info_ptr cinfo)
  162. {
  163.   rle_hdr header;        /* Output file information */
  164.   rle_pixel *output_rows[MAX_CHANS];
  165.   char cmapcomment[80];
  166.   short ci;
  167.   long row;
  168.  
  169.   /* Initialize the header info */
  170.   MEMZERO((void *) &header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */
  171.   header.rle_file = cinfo->output_file;
  172.   header.xmin     = 0;
  173.   header.xmax     = cinfo->image_width  - 1;
  174.   header.ymin     = 0;
  175.   header.ymax     = cinfo->image_height - 1;
  176.   header.alpha    = 0;
  177.   header.ncolors  = cinfo->final_out_comps;
  178.   for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  179.     RLE_SET_BIT(header, ci);
  180.   }
  181.   if (number_colors > 0) {
  182.     header.ncmap   = cinfo->color_out_comps;
  183.     header.cmaplen = CMAPBITS;
  184.     header.cmap    = output_colormap;
  185.     /* Add a comment to the output image with the true colormap length. */
  186.     sprintf(cmapcomment, "color_map_length=%d", number_colors);
  187.     rle_putcom(cmapcomment, &header);
  188.   }
  189.   /* Emit the RLE header and color map (if any) */
  190.   rle_put_setup(&header);
  191.  
  192.   /* Now output the RLE data from our virtual array(s).
  193.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  194.    * and (b) we are not on a machine where FAR pointers differ from regular.
  195.    */
  196.   for (row = cinfo->image_height-1; row >= 0; row--) {
  197.     (*cinfo->methods->progress_monitor) (cinfo, cinfo->image_height-row-1,
  198.                      cinfo->image_height);
  199.     for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  200.       output_rows[ci] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  201.                     (channels[ci], row, FALSE));
  202.     }
  203.     rle_putrow(output_rows, (int) cinfo->image_width, &header);
  204.   }
  205.   cinfo->completed_passes++;
  206.  
  207.   /* Emit file trailer */
  208.   rle_puteof(&header);
  209.   fflush(cinfo->output_file);
  210.   if (ferror(cinfo->output_file))
  211.     ERREXIT(cinfo->emethods, "Output file write error");
  212.  
  213.   /* Release memory */
  214.   /* no work (we let free_all release the workspace) */
  215. }
  216.  
  217.  
  218. /*
  219.  * The method selection routine for RLE format output.
  220.  * This should be called from d_ui_method_selection if RLE output is wanted.
  221.  */
  222.  
  223. GLOBAL void
  224. jselwrle (decompress_info_ptr cinfo)
  225. {
  226.   cinfo->methods->output_init    = output_init;
  227.   cinfo->methods->put_color_map  = put_color_map;
  228.   cinfo->methods->put_pixel_rows = put_pixel_rows;
  229.   cinfo->methods->output_term    = output_term;
  230. }
  231.  
  232. #endif /* RLE_SUPPORTED */
  233.