170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * rdrle.c
370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Copyright (C) 1991-1996, Thomas G. Lane.
570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file is part of the Independent JPEG Group's software.
670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For conditions of distribution and use, see the accompanying README file.
770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file contains routines to read input images in Utah RLE format.
970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The Utah Raster Toolkit library is required (version 3.1 or later).
1070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
1170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These routines may need modification for non-Unix environments or
1270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * specialized applications.  As they stand, they assume input from
1370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * an ordinary stdio stream.  They further assume that reading begins
1470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * at the start of the file; start_input may need work if the
1570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * user interface has already read some data (e.g., to determine that
1670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the file is indeed RLE format).
1770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
1870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Based on code contributed by Mike Lijewski,
1970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * with updates from Robert Hutchinson.
2070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
2170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
2370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef RLE_SUPPORTED
2570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* rle.h is provided by the Utah Raster Toolkit. */
2770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <rle.h>
2970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
3070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
3170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * We assume that JSAMPLE has the same representation as rle_pixel,
3270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
3370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
3470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
3570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#if BITS_IN_JSAMPLE != 8
3670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
3770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
3870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
3970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
4070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * We support the following types of RLE files:
4170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
4270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   GRAYSCALE   - 8 bits, no colormap
4370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   MAPPEDGRAY  - 8 bits, 1 channel colomap
4470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   PSEUDOCOLOR - 8 bits, 3 channel colormap
4570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   TRUECOLOR   - 24 bits, 3 channel colormap
4670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   DIRECTCOLOR - 24 bits, no colormap
4770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
4870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For now, we ignore any alpha channel in the image.
4970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
5070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef enum
5270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
5370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
5570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
5670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Since RLE stores scanlines bottom-to-top, we have to invert the image
5770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * to conform to JPEG's top-to-bottom order.  To do this, we read the
5870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * incoming image into a virtual array on the first get_pixel_rows call,
5970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * then fetch the required row from the virtual array on subsequent calls.
6070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
6170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef struct _rle_source_struct * rle_source_ptr;
6370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef struct _rle_source_struct {
6570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  struct cjpeg_source_struct pub; /* public fields */
6670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_kind visual;              /* actual type of input file */
6870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jvirt_sarray_ptr image;       /* virtual array to hold the image */
6970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION row;		/* current row # in the virtual array */
7070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_hdr header;               /* Input file information */
7170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_pixel** rle_row;          /* holds a row returned by rle_getrow() */
7270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} rle_source_struct;
7470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
7770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Read the file header; return image size and component count.
7870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
7970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
8070a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void)
8170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestart_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
8270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
8370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_source_ptr source = (rle_source_ptr) sinfo;
8470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION width, height;
8570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
8670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
8770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
8870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
8970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Use RLE library routine to get the header info */
9070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->header = *rle_hdr_init(NULL);
9170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->header.rle_file = source->pub.input_file;
9270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  switch (rle_get_setup(&(source->header))) {
9370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case RLE_SUCCESS:
9470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* A-OK */
9570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
9670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case RLE_NOT_RLE:
9770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_NOT);
9870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
9970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case RLE_NO_SPACE:
10070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_MEM);
10170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
10270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case RLE_EMPTY:
10370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_EMPTY);
10470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
10570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case RLE_EOF:
10670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_EOF);
10770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
10870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  default:
10970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_BADERROR);
11070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
11170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
11270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Figure out what we have, set private vars and return values accordingly */
11470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  width  = source->header.xmax - source->header.xmin + 1;
11670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  height = source->header.ymax - source->header.ymin + 1;
11770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->header.xmin = 0;		/* realign horizontally */
11870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->header.xmax = width-1;
11970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
12070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cinfo->image_width      = width;
12170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cinfo->image_height     = height;
12270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cinfo->data_precision   = 8;  /* we can only handle 8 bit data */
12370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
12470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (source->header.ncolors == 1 && source->header.ncmap == 0) {
12570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->visual     = GRAYSCALE;
12670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
12770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
12870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->visual     = MAPPEDGRAY;
12970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
13070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine             1 << source->header.cmaplen);
13170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
13270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->visual     = PSEUDOCOLOR;
13370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
13470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     1 << source->header.cmaplen);
13570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
13670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->visual     = TRUECOLOR;
13770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
13870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     1 << source->header.cmaplen);
13970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
14070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->visual     = DIRECTCOLOR;
14170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
14270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else
14370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
14470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
14570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
14670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    cinfo->in_color_space   = JCS_GRAYSCALE;
14770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    cinfo->input_components = 1;
14870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else {
14970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    cinfo->in_color_space   = JCS_RGB;
15070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    cinfo->input_components = 3;
15170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
15270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
15370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /*
15470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * A place to hold each scanline while it's converted.
15570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * (GRAYSCALE scanlines don't need converting)
15670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
15770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (source->visual != GRAYSCALE) {
15870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
15970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      ((j_common_ptr) cinfo, JPOOL_IMAGE,
16070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine       (JDIMENSION) width, (JDIMENSION) cinfo->input_components);
16170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
16270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
16370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* request a virtual array to hold the image */
16470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->image = (*cinfo->mem->request_virt_sarray)
16570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
16670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     (JDIMENSION) (width * source->header.ncolors),
16770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     (JDIMENSION) height, (JDIMENSION) 1);
16870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
16970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
17070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (progress != NULL) {
17170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* count file input as separate pass */
17270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    progress->total_extra_passes++;
17370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
17470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
17570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
17670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->pub.buffer_height = 1;
17770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
17870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
17970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
18170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Read one row of pixels.
18270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Called only after load_image has read the image into the virtual array.
18370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
18470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
18570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18670a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(JDIMENSION)
18770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineget_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
18870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
18970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_source_ptr source = (rle_source_ptr) sinfo;
19070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->row--;
19270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->pub.buffer = (*cinfo->mem->access_virt_sarray)
19370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
19470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  return 1;
19670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
19770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
19970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Read one row of pixels.
20070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Called only after load_image has read the image into the virtual array.
20170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Used for PSEUDOCOLOR images.
20270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
20370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
20470a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(JDIMENSION)
20570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineget_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
20670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
20770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_source_ptr source = (rle_source_ptr) sinfo;
20870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JSAMPROW src_row, dest_row;
20970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION col;
21070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_map *colormap;
21170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int val;
21270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
21370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  colormap = source->header.cmap;
21470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  dest_row = source->pub.buffer[0];
21570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->row--;
21670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  src_row = * (*cinfo->mem->access_virt_sarray)
21770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
21870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
21970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (col = cinfo->image_width; col > 0; col--) {
22070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    val = GETJSAMPLE(*src_row++);
22170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    *dest_row++ = (JSAMPLE) (colormap[val      ] >> 8);
22270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8);
22370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8);
22470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
22570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
22670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  return 1;
22770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
22870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
22970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
23070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
23170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Load the image into a virtual array.  We have to do this because RLE
23270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * files start at the lower left while the JPEG standard has them starting
23370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * in the upper left.  This is called the first time we want to get a row
23470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * of input.  What we do is load the RLE data into the array and then call
23570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the appropriate routine to read one row from the array.  Before returning,
23670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * we set source->pub.get_pixel_rows so that subsequent calls go straight to
23770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the appropriate row-reading routine.
23870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
23970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
24070a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(JDIMENSION)
24170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
24270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
24370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_source_ptr source = (rle_source_ptr) sinfo;
24470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION row, col;
24570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JSAMPROW  scanline, red_ptr, green_ptr, blue_ptr;
24670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_pixel **rle_row;
24770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_map *colormap;
24870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  char channel;
24970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
25070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
25170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
25270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
25370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  colormap = source->header.cmap;
25470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_row = source->rle_row;
25570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
25670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Read the RLE data into our virtual array.
25770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
25870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * and (b) we are not on a machine where FAR pointers differ from regular.
25970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
26070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
26170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
26270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
26370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (progress != NULL) {
26470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    progress->pub.pass_limit = cinfo->image_height;
26570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    progress->pub.pass_counter = 0;
26670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
26770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
26870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
26970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
27070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  switch (source->visual) {
27170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
27270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case GRAYSCALE:
27370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case PSEUDOCOLOR:
27470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (row = 0; row < cinfo->image_height; row++) {
27570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
27670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine         ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
27770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      rle_getrow(&source->header, rle_row);
27870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
27970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (progress != NULL) {
28070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        progress->pub.pass_counter++;
28170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
28270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
28370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
28470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
28570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
28670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
28770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case MAPPEDGRAY:
28870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case TRUECOLOR:
28970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (row = 0; row < cinfo->image_height; row++) {
29070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      scanline = * (*cinfo->mem->access_virt_sarray)
29170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
29270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      rle_row = source->rle_row;
29370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      rle_getrow(&source->header, rle_row);
29470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
29570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (col = 0; col < cinfo->image_width; col++) {
29670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        for (channel = 0; channel < source->header.ncolors; channel++) {
29770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine          *scanline++ = (JSAMPLE)
29870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine            (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8);
29970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        }
30070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
30170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
30270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
30370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (progress != NULL) {
30470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        progress->pub.pass_counter++;
30570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
30670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
30770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
30870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
30970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
31070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
31170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case DIRECTCOLOR:
31270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (row = 0; row < cinfo->image_height; row++) {
31370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      scanline = * (*cinfo->mem->access_virt_sarray)
31470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
31570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      rle_getrow(&source->header, rle_row);
31670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
31770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      red_ptr   = rle_row[0];
31870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      green_ptr = rle_row[1];
31970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      blue_ptr  = rle_row[2];
32070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
32170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (col = cinfo->image_width; col > 0; col--) {
32270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        *scanline++ = *red_ptr++;
32370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        *scanline++ = *green_ptr++;
32470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        *scanline++ = *blue_ptr++;
32570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
32670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
32770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
32870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (progress != NULL) {
32970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        progress->pub.pass_counter++;
33070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine        (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
33170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
33270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
33370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
33470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
33570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
33670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef PROGRESS_REPORT
33770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (progress != NULL)
33870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    progress->completed_extra_passes++;
33970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
34070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
34170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Set up to call proper row-extraction routine in future */
34270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (source->visual == PSEUDOCOLOR) {
34370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->pub.buffer = source->rle_row;
34470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->pub.get_pixel_rows = get_pseudocolor_row;
34570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else {
34670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    source->pub.get_pixel_rows = get_rle_row;
34770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
34870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->row = cinfo->image_height;
34970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* And fetch the topmost (bottommost) row */
35170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  return (*source->pub.get_pixel_rows) (cinfo, sinfo);
35270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
35370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
35670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Finish up at the end of the file.
35770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
35870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void)
36070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinefinish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
36170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
36270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* no work */
36370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
36470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
36570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
36670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
36770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The module selection routine for RLE format input.
36870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
36970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
37070a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(cjpeg_source_ptr)
37170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejinit_read_rle (j_compress_ptr cinfo)
37270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
37370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  rle_source_ptr source;
37470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
37570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Create module interface object */
37670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source = (rle_source_ptr)
37770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
37870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine                                  SIZEOF(rle_source_struct));
37970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Fill in method ptrs */
38070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->pub.start_input = start_input_rle;
38170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->pub.finish_input = finish_input_rle;
38270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  source->pub.get_pixel_rows = load_image;
38370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
38470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  return (cjpeg_source_ptr) source;
38570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
38670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
38770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif /* RLE_SUPPORTED */
388