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

  1. /*
  2.  * jrdrle.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 read input images in Utah 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 input from
  13.  * an ordinary stdio stream.  They further assume that reading begins
  14.  * at the start of the file; input_init may need work if the
  15.  * user interface has already read some data (e.g., to determine that
  16.  * the file is indeed RLE format).
  17.  *
  18.  * These routines are invoked via the methods get_input_row
  19.  * and input_init/term.
  20.  *
  21.  * Based on code contributed by Mike Lijewski.
  22.  */
  23.  
  24. #include "jinclude.h"
  25.  
  26. #ifdef RLE_SUPPORTED
  27.  
  28. /* rle.h is provided by the Utah Raster Toolkit. */
  29.  
  30. #include <rle.h>
  31.  
  32.  
  33. /*
  34.  * load_image assumes that JSAMPLE has the same representation as rle_pixel,
  35.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  36.  */
  37.  
  38. #ifndef EIGHT_BIT_SAMPLES
  39.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  40. #endif
  41.  
  42.  
  43. /*
  44.  * We support the following types of RLE files:
  45.  *   
  46.  *   GRAYSCALE   - 8 bits, no colormap
  47.  *   PSEUDOCOLOR - 8 bits, colormap
  48.  *   TRUECOLOR   - 24 bits, colormap
  49.  *   DIRECTCOLOR - 24 bits, no colormap
  50.  *
  51.  * For now, we ignore any alpha channel in the image.
  52.  */
  53.  
  54. typedef enum { GRAYSCALE, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
  55.  
  56. static rle_kind visual;        /* actual type of input file */
  57.  
  58. /*
  59.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  60.  * to conform to JPEG's top-to-bottom order.  To do this, we read the
  61.  * incoming image into a virtual array on the first get_input_row call,
  62.  * then fetch the required row from the virtual array on subsequent calls.
  63.  */
  64.  
  65. static big_sarray_ptr image;    /* single array for GRAYSCALE/PSEUDOCOLOR */
  66. static big_sarray_ptr red_channel; /* three arrays for TRUECOLOR/DIRECTCOLOR */
  67. static big_sarray_ptr green_channel;
  68. static big_sarray_ptr blue_channel;
  69. static long cur_row_number;    /* last row# read from virtual array */
  70.  
  71. static rle_hdr header;        /* Input file information */
  72. static rle_map *colormap;    /* RLE colormap, if any */
  73.  
  74.  
  75. /*
  76.  * Read the file header; return image size and component count.
  77.  */
  78.  
  79. METHODDEF void
  80. input_init (compress_info_ptr cinfo)
  81. {
  82.   long width, height;
  83.  
  84.   /* Use RLE library routine to get the header info */
  85.   header.rle_file = cinfo->input_file;
  86.   switch (rle_get_setup(&header)) {
  87.   case RLE_SUCCESS:
  88.     /* A-OK */
  89.     break;
  90.   case RLE_NOT_RLE:
  91.     ERREXIT(cinfo->emethods, "Not an RLE file");
  92.     break;
  93.   case RLE_NO_SPACE:
  94.     ERREXIT(cinfo->emethods, "Insufficient memory for RLE header");
  95.     break;
  96.   case RLE_EMPTY:
  97.     ERREXIT(cinfo->emethods, "Empty RLE file");
  98.     break;
  99.   case RLE_EOF:
  100.     ERREXIT(cinfo->emethods, "Premature EOF in RLE header");
  101.     break;
  102.   default:
  103.     ERREXIT(cinfo->emethods, "Bogus RLE error code");
  104.     break;
  105.   }
  106.  
  107.   /* Figure out what we have, set private vars and return values accordingly */
  108.   
  109.   width  = header.xmax - header.xmin + 1;
  110.   height = header.ymax - header.ymin + 1;
  111.   header.xmin = 0;        /* realign horizontally */
  112.   header.xmax = width-1;
  113.  
  114.   cinfo->image_width      = width;
  115.   cinfo->image_height     = height;
  116.   cinfo->data_precision   = 8;  /* we can only handle 8 bit data */
  117.  
  118.   if (header.ncolors == 1 && header.ncmap == 0) {
  119.     visual     = GRAYSCALE;
  120.     TRACEMS(cinfo->emethods, 1, "Gray-scale RLE file");
  121.   } else if (header.ncolors == 1 && header.ncmap == 3) {
  122.     visual     = PSEUDOCOLOR;
  123.     colormap   = header.cmap;
  124.     TRACEMS1(cinfo->emethods, 1, "Colormapped RLE file with map of length %d",
  125.          1 << header.cmaplen);
  126.   } else if (header.ncolors == 3 && header.ncmap == 3) {
  127.     visual     = TRUECOLOR;
  128.     colormap   = header.cmap;
  129.     TRACEMS1(cinfo->emethods, 1, "Full-color RLE file with map of length %d",
  130.          1 << header.cmaplen);
  131.   } else if (header.ncolors == 3 && header.ncmap == 0) {
  132.     visual     = DIRECTCOLOR;
  133.     TRACEMS(cinfo->emethods, 1, "Full-color RLE file");
  134.   } else
  135.     ERREXIT(cinfo->emethods, "Can't handle this RLE setup");
  136.   
  137.   switch (visual) {
  138.   case GRAYSCALE:
  139.     /* request one big array to hold the grayscale image */
  140.     image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  141.     cinfo->in_color_space   = CS_GRAYSCALE;
  142.     cinfo->input_components = 1;
  143.     break;
  144.   case PSEUDOCOLOR:
  145.     /* request one big array to hold the pseudocolor image */
  146.     image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  147.     cinfo->in_color_space   = CS_RGB;
  148.     cinfo->input_components = 3;
  149.     break;
  150.   case TRUECOLOR:
  151.   case DIRECTCOLOR:
  152.     /* request three big arrays to hold the RGB channels */
  153.     red_channel   = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  154.     green_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  155.     blue_channel  = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  156.     cinfo->in_color_space   = CS_RGB;
  157.     cinfo->input_components = 3;
  158.     break;
  159.   }
  160.  
  161.   cinfo->total_passes++;    /* count file reading as separate pass */
  162. }
  163.  
  164.  
  165. /*
  166.  * Read one row of pixels.
  167.  * These are called only after load_image has read the image into
  168.  * the virtual array(s).
  169.  */
  170.  
  171.  
  172. METHODDEF void
  173. get_grayscale_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  174. /* This is used for GRAYSCALE images */
  175. {
  176.   JSAMPROW inputrows[1];    /* a pseudo JSAMPARRAY structure */
  177.  
  178.   cur_row_number--;        /* work down in array */
  179.   
  180.   inputrows[0] = *((*cinfo->emethods->access_big_sarray)
  181.             (image, cur_row_number, FALSE));
  182.  
  183.   jcopy_sample_rows(inputrows, 0, pixel_row, 0, 1, cinfo->image_width);
  184. }
  185.  
  186.  
  187. METHODDEF void
  188. get_pseudocolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  189. /* This is used for PSEUDOCOLOR images */
  190. {
  191.   long col;
  192.   JSAMPROW image_ptr, ptr0, ptr1, ptr2;
  193.   int val;
  194.  
  195.   cur_row_number--;        /* work down in array */
  196.   
  197.   image_ptr = *((*cinfo->emethods->access_big_sarray)
  198.         (image, cur_row_number, FALSE));
  199.  
  200.   ptr0 = pixel_row[0];
  201.   ptr1 = pixel_row[1];
  202.   ptr2 = pixel_row[2];
  203.   
  204.   for (col = cinfo->image_width; col > 0; col--) {
  205.     val = GETJSAMPLE(*image_ptr++);
  206.     *ptr0++ = colormap[val      ] >> 8;
  207.     *ptr1++ = colormap[val + 256] >> 8;
  208.     *ptr2++ = colormap[val + 512] >> 8;
  209.   }
  210. }
  211.  
  212.  
  213. METHODDEF void
  214. get_truecolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  215. /* This is used for TRUECOLOR images */
  216. /* The colormap consists of 3 independent lookup tables */
  217. {
  218.   long col;
  219.   JSAMPROW red_ptr, green_ptr, blue_ptr, ptr0, ptr1, ptr2;
  220.   
  221.   cur_row_number--;        /* work down in array */
  222.   
  223.   red_ptr   = *((*cinfo->emethods->access_big_sarray)
  224.         (red_channel, cur_row_number, FALSE));
  225.   green_ptr = *((*cinfo->emethods->access_big_sarray)
  226.         (green_channel, cur_row_number, FALSE));
  227.   blue_ptr  = *((*cinfo->emethods->access_big_sarray)
  228.         (blue_channel, cur_row_number, FALSE));
  229.   
  230.   ptr0 = pixel_row[0];
  231.   ptr1 = pixel_row[1];
  232.   ptr2 = pixel_row[2];
  233.   
  234.   for (col = cinfo->image_width; col > 0; col--) {
  235.     *ptr0++ = colormap[GETJSAMPLE(*red_ptr++)        ] >> 8;
  236.     *ptr1++ = colormap[GETJSAMPLE(*green_ptr++) + 256] >> 8;
  237.     *ptr2++ = colormap[GETJSAMPLE(*blue_ptr++)  + 512] >> 8;
  238.   }
  239. }
  240.  
  241.  
  242. METHODDEF void
  243. get_directcolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  244. /* This is used for DIRECTCOLOR images */
  245. {
  246.   JSAMPROW inputrows[3];    /* a pseudo JSAMPARRAY structure */
  247.  
  248.   cur_row_number--;        /* work down in array */
  249.   
  250.   inputrows[0] = *((*cinfo->emethods->access_big_sarray)
  251.             (red_channel, cur_row_number, FALSE));
  252.   inputrows[1] = *((*cinfo->emethods->access_big_sarray)
  253.             (green_channel, cur_row_number, FALSE));
  254.   inputrows[2] = *((*cinfo->emethods->access_big_sarray)
  255.             (blue_channel, cur_row_number, FALSE));
  256.  
  257.   jcopy_sample_rows(inputrows, 0, pixel_row, 0, 3, cinfo->image_width);
  258. }
  259.  
  260.  
  261. /*
  262.  * Load the color channels into separate arrays.  We have to do
  263.  * this because RLE files start at the lower left while the JPEG standard
  264.  * has them starting in the upper left.  This is called the first time
  265.  * we want to get a row of input.  What we do is load the RLE data into
  266.  * big arrays and then call the appropriate routine to read one row from
  267.  * the big arrays.  We also change cinfo->methods->get_input_row so that
  268.  * subsequent calls go straight to the row-reading routine.
  269.  */
  270.  
  271. METHODDEF void
  272. load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  273. {
  274.   long row;
  275.   rle_pixel *rle_row[3];
  276.   
  277.   /* Read the RLE data into our virtual array(s).
  278.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  279.    * and (b) we are not on a machine where FAR pointers differ from regular.
  280.    */
  281.   RLE_CLR_BIT(header, RLE_ALPHA); /* don't read the alpha channel */
  282.  
  283.   switch (visual) {
  284.   case GRAYSCALE:
  285.   case PSEUDOCOLOR:
  286.     for (row = 0; row < cinfo->image_height; row++) {
  287.       (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
  288.       /*
  289.        * Read a row of the image directly into our big array.
  290.        * Too bad this doesn't seem to return any indication of errors :-(.
  291.        */
  292.       rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  293.                     (image, row, TRUE));
  294.       rle_getrow(&header, rle_row);
  295.     }
  296.     break;
  297.   case TRUECOLOR:
  298.   case DIRECTCOLOR:
  299.     for (row = 0; row < cinfo->image_height; row++) {
  300.       (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
  301.       /*
  302.        * Read a row of the image directly into our big arrays.
  303.        * Too bad this doesn't seem to return any indication of errors :-(.
  304.        */
  305.       rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  306.                     (red_channel, row, TRUE));
  307.       rle_row[1] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  308.                     (green_channel, row, TRUE));
  309.       rle_row[2] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  310.                     (blue_channel, row, TRUE));
  311.       rle_getrow(&header, rle_row);
  312.     }
  313.     break;
  314.   }
  315.   cinfo->completed_passes++;
  316.   
  317.   /* Set up to call proper row-extraction routine in future */
  318.   switch (visual) {
  319.   case GRAYSCALE:
  320.     cinfo->methods->get_input_row = get_grayscale_row;
  321.     break;
  322.   case PSEUDOCOLOR:
  323.     cinfo->methods->get_input_row = get_pseudocolor_row;
  324.     break;
  325.   case TRUECOLOR:
  326.     cinfo->methods->get_input_row = get_truecolor_row;
  327.     break;
  328.   case DIRECTCOLOR:
  329.     cinfo->methods->get_input_row = get_directcolor_row;
  330.     break;
  331.   }
  332.  
  333.   /* And fetch the topmost (bottommost) row */
  334.   cur_row_number = cinfo->image_height;
  335.   (*cinfo->methods->get_input_row) (cinfo, pixel_row);   
  336. }
  337.  
  338.  
  339. /*
  340.  * Finish up at the end of the file.
  341.  */
  342.  
  343. METHODDEF void
  344. input_term (compress_info_ptr cinfo)
  345. {
  346.   /* no work (we let free_all release the workspace) */
  347. }
  348.  
  349.  
  350. /*
  351.  * The method selection routine for RLE format input.
  352.  * Note that this must be called by the user interface before calling
  353.  * jpeg_compress.  If multiple input formats are supported, the
  354.  * user interface is responsible for discovering the file format and
  355.  * calling the appropriate method selection routine.
  356.  */
  357.  
  358. GLOBAL void
  359. jselrrle (compress_info_ptr cinfo)
  360. {
  361.   cinfo->methods->input_init    = input_init;
  362.   cinfo->methods->get_input_row = load_image; /* until first call */
  363.   cinfo->methods->input_term    = input_term;
  364. }
  365.  
  366. #endif /* RLE_SUPPORTED */
  367.