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