rdrle.c
上传用户:wuyixingx
上传日期:2007-01-08
资源大小:745k
文件大小:12k
源码类别:

图形图象

开发平台:

C/C++

  1. /*
  2.  * rdrle.c
  3.  *
  4.  * Copyright (C) 1991-1996, 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.1 or later).
  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; start_input 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.  * Based on code contributed by Mike Lijewski,
  19.  * with updates from Robert Hutchinson.
  20.  */
  21. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  22. #ifdef RLE_SUPPORTED
  23. /* rle.h is provided by the Utah Raster Toolkit. */
  24. #include <rle.h>
  25. /*
  26.  * We assume that JSAMPLE has the same representation as rle_pixel,
  27.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  28.  */
  29. #if BITS_IN_JSAMPLE != 8
  30.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  31. #endif
  32. /*
  33.  * We support the following types of RLE files:
  34.  *   
  35.  *   GRAYSCALE   - 8 bits, no colormap
  36.  *   MAPPEDGRAY  - 8 bits, 1 channel colomap
  37.  *   PSEUDOCOLOR - 8 bits, 3 channel colormap
  38.  *   TRUECOLOR   - 24 bits, 3 channel colormap
  39.  *   DIRECTCOLOR - 24 bits, no colormap
  40.  *
  41.  * For now, we ignore any alpha channel in the image.
  42.  */
  43. typedef enum
  44.   { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
  45. /*
  46.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  47.  * to conform to JPEG's top-to-bottom order.  To do this, we read the
  48.  * incoming image into a virtual array on the first get_pixel_rows call,
  49.  * then fetch the required row from the virtual array on subsequent calls.
  50.  */
  51. typedef struct _rle_source_struct * rle_source_ptr;
  52. typedef struct _rle_source_struct {
  53.   struct cjpeg_source_struct pub; /* public fields */
  54.   rle_kind visual;              /* actual type of input file */
  55.   jvirt_sarray_ptr image;       /* virtual array to hold the image */
  56.   JDIMENSION row; /* current row # in the virtual array */
  57.   rle_hdr header;               /* Input file information */
  58.   rle_pixel** rle_row;          /* holds a row returned by rle_getrow() */
  59. } rle_source_struct;
  60. /*
  61.  * Read the file header; return image size and component count.
  62.  */
  63. METHODDEF(void)
  64. start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  65. {
  66.   rle_source_ptr source = (rle_source_ptr) sinfo;
  67.   JDIMENSION width, height;
  68. #ifdef PROGRESS_REPORT
  69.   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  70. #endif
  71.   /* Use RLE library routine to get the header info */
  72.   source->header = *rle_hdr_init(NULL);
  73.   source->header.rle_file = source->pub.input_file;
  74.   switch (rle_get_setup(&(source->header))) {
  75.   case RLE_SUCCESS:
  76.     /* A-OK */
  77.     break;
  78.   case RLE_NOT_RLE:
  79.     ERREXIT(cinfo, JERR_RLE_NOT);
  80.     break;
  81.   case RLE_NO_SPACE:
  82.     ERREXIT(cinfo, JERR_RLE_MEM);
  83.     break;
  84.   case RLE_EMPTY:
  85.     ERREXIT(cinfo, JERR_RLE_EMPTY);
  86.     break;
  87.   case RLE_EOF:
  88.     ERREXIT(cinfo, JERR_RLE_EOF);
  89.     break;
  90.   default:
  91.     ERREXIT(cinfo, JERR_RLE_BADERROR);
  92.     break;
  93.   }
  94.   /* Figure out what we have, set private vars and return values accordingly */
  95.   
  96.   width  = source->header.xmax - source->header.xmin + 1;
  97.   height = source->header.ymax - source->header.ymin + 1;
  98.   source->header.xmin = 0; /* realign horizontally */
  99.   source->header.xmax = width-1;
  100.   cinfo->image_width      = width;
  101.   cinfo->image_height     = height;
  102.   cinfo->data_precision   = 8;  /* we can only handle 8 bit data */
  103.   if (source->header.ncolors == 1 && source->header.ncmap == 0) {
  104.     source->visual     = GRAYSCALE;
  105.     TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
  106.   } else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
  107.     source->visual     = MAPPEDGRAY;
  108.     TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
  109.              1 << source->header.cmaplen);
  110.   } else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
  111.     source->visual     = PSEUDOCOLOR;
  112.     TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
  113.      1 << source->header.cmaplen);
  114.   } else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
  115.     source->visual     = TRUECOLOR;
  116.     TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
  117.      1 << source->header.cmaplen);
  118.   } else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
  119.     source->visual     = DIRECTCOLOR;
  120.     TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
  121.   } else
  122.     ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
  123.   
  124.   if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
  125.     cinfo->in_color_space   = JCS_GRAYSCALE;
  126.     cinfo->input_components = 1;
  127.   } else {
  128.     cinfo->in_color_space   = JCS_RGB;
  129.     cinfo->input_components = 3;
  130.   }
  131.   /*
  132.    * A place to hold each scanline while it's converted.
  133.    * (GRAYSCALE scanlines don't need converting)
  134.    */
  135.   if (source->visual != GRAYSCALE) {
  136.     source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
  137.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  138.        (JDIMENSION) width, (JDIMENSION) cinfo->input_components);
  139.   }
  140.   /* request a virtual array to hold the image */
  141.   source->image = (*cinfo->mem->request_virt_sarray)
  142.     ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
  143.      (JDIMENSION) (width * source->header.ncolors),
  144.      (JDIMENSION) height, (JDIMENSION) 1);
  145. #ifdef PROGRESS_REPORT
  146.   if (progress != NULL) {
  147.     /* count file input as separate pass */
  148.     progress->total_extra_passes++;
  149.   }
  150. #endif
  151.   source->pub.buffer_height = 1;
  152. }
  153. /*
  154.  * Read one row of pixels.
  155.  * Called only after load_image has read the image into the virtual array.
  156.  * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
  157.  */
  158. METHODDEF(JDIMENSION)
  159. get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  160. {
  161.   rle_source_ptr source = (rle_source_ptr) sinfo;
  162.   source->row--;
  163.   source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  164.     ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
  165.   return 1;
  166. }
  167. /*
  168.  * Read one row of pixels.
  169.  * Called only after load_image has read the image into the virtual array.
  170.  * Used for PSEUDOCOLOR images.
  171.  */
  172. METHODDEF(JDIMENSION)
  173. get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  174. {
  175.   rle_source_ptr source = (rle_source_ptr) sinfo;
  176.   JSAMPROW src_row, dest_row;
  177.   JDIMENSION col;
  178.   rle_map *colormap;
  179.   int val;
  180.   colormap = source->header.cmap;
  181.   dest_row = source->pub.buffer[0];
  182.   source->row--;
  183.   src_row = * (*cinfo->mem->access_virt_sarray)
  184.     ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
  185.   for (col = cinfo->image_width; col > 0; col--) {
  186.     val = GETJSAMPLE(*src_row++);
  187.     *dest_row++ = (JSAMPLE) (colormap[val      ] >> 8);
  188.     *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8);
  189.     *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8);
  190.   }
  191.   return 1;
  192. }
  193. /*
  194.  * Load the image into a virtual array.  We have to do this because RLE
  195.  * files start at the lower left while the JPEG standard has them starting
  196.  * in the upper left.  This is called the first time we want to get a row
  197.  * of input.  What we do is load the RLE data into the array and then call
  198.  * the appropriate routine to read one row from the array.  Before returning,
  199.  * we set source->pub.get_pixel_rows so that subsequent calls go straight to
  200.  * the appropriate row-reading routine.
  201.  */
  202. METHODDEF(JDIMENSION)
  203. load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  204. {
  205.   rle_source_ptr source = (rle_source_ptr) sinfo;
  206.   JDIMENSION row, col;
  207.   JSAMPROW  scanline, red_ptr, green_ptr, blue_ptr;
  208.   rle_pixel **rle_row;
  209.   rle_map *colormap;
  210.   char channel;
  211. #ifdef PROGRESS_REPORT
  212.   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  213. #endif
  214.   colormap = source->header.cmap;
  215.   rle_row = source->rle_row;
  216.   /* Read the RLE data into our virtual array.
  217.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  218.    * and (b) we are not on a machine where FAR pointers differ from regular.
  219.    */
  220.   RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
  221. #ifdef PROGRESS_REPORT
  222.   if (progress != NULL) {
  223.     progress->pub.pass_limit = cinfo->image_height;
  224.     progress->pub.pass_counter = 0;
  225.     (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  226.   }
  227. #endif
  228.   switch (source->visual) {
  229.   case GRAYSCALE:
  230.   case PSEUDOCOLOR:
  231.     for (row = 0; row < cinfo->image_height; row++) {
  232.       rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
  233.          ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
  234.       rle_getrow(&source->header, rle_row);
  235. #ifdef PROGRESS_REPORT
  236.       if (progress != NULL) {
  237.         progress->pub.pass_counter++;
  238.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  239.       }
  240. #endif
  241.     }
  242.     break;
  243.   case MAPPEDGRAY:
  244.   case TRUECOLOR:
  245.     for (row = 0; row < cinfo->image_height; row++) {
  246.       scanline = * (*cinfo->mem->access_virt_sarray)
  247.         ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
  248.       rle_row = source->rle_row;
  249.       rle_getrow(&source->header, rle_row);
  250.       for (col = 0; col < cinfo->image_width; col++) {
  251.         for (channel = 0; channel < source->header.ncolors; channel++) {
  252.           *scanline++ = (JSAMPLE)
  253.             (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8);
  254.         }
  255.       }
  256. #ifdef PROGRESS_REPORT
  257.       if (progress != NULL) {
  258.         progress->pub.pass_counter++;
  259.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  260.       }
  261. #endif
  262.     }
  263.     break;
  264.   case DIRECTCOLOR:
  265.     for (row = 0; row < cinfo->image_height; row++) {
  266.       scanline = * (*cinfo->mem->access_virt_sarray)
  267.         ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
  268.       rle_getrow(&source->header, rle_row);
  269.       red_ptr   = rle_row[0];
  270.       green_ptr = rle_row[1];
  271.       blue_ptr  = rle_row[2];
  272.       for (col = cinfo->image_width; col > 0; col--) {
  273.         *scanline++ = *red_ptr++;
  274.         *scanline++ = *green_ptr++;
  275.         *scanline++ = *blue_ptr++;
  276.       }
  277. #ifdef PROGRESS_REPORT
  278.       if (progress != NULL) {
  279.         progress->pub.pass_counter++;
  280.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  281.       }
  282. #endif
  283.     }
  284.   }
  285. #ifdef PROGRESS_REPORT
  286.   if (progress != NULL)
  287.     progress->completed_extra_passes++;
  288. #endif
  289.   /* Set up to call proper row-extraction routine in future */
  290.   if (source->visual == PSEUDOCOLOR) {
  291.     source->pub.buffer = source->rle_row;
  292.     source->pub.get_pixel_rows = get_pseudocolor_row;
  293.   } else {
  294.     source->pub.get_pixel_rows = get_rle_row;
  295.   }
  296.   source->row = cinfo->image_height;
  297.   /* And fetch the topmost (bottommost) row */
  298.   return (*source->pub.get_pixel_rows) (cinfo, sinfo);   
  299. }
  300. /*
  301.  * Finish up at the end of the file.
  302.  */
  303. METHODDEF(void)
  304. finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  305. {
  306.   /* no work */
  307. }
  308. /*
  309.  * The module selection routine for RLE format input.
  310.  */
  311. GLOBAL(cjpeg_source_ptr)
  312. jinit_read_rle (j_compress_ptr cinfo)
  313. {
  314.   rle_source_ptr source;
  315.   /* Create module interface object */
  316.   source = (rle_source_ptr)
  317.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  318.                                   SIZEOF(rle_source_struct));
  319.   /* Fill in method ptrs */
  320.   source->pub.start_input = start_input_rle;
  321.   source->pub.finish_input = finish_input_rle;
  322.   source->pub.get_pixel_rows = load_image;
  323.   return (cjpeg_source_ptr) source;
  324. }
  325. #endif /* RLE_SUPPORTED */