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