ReactOS  0.4.15-dev-3720-g4cf9b79
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 
52 typedef 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 
63 typedef struct _rle_source_struct * rle_source_ptr;
64 
65 typedef 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 
81 METHODDEF(void)
82 start_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) {
142  cinfo->in_color_space = JCS_GRAYSCALE;
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,
156  width, (JDIMENSION) cinfo->input_components);
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 
182 get_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 
200 get_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 
353 METHODDEF(void)
354 finish_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 
365 jinit_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 */
GLeglImageOES image
Definition: gl.h:2204
GLint GLint GLsizei width
Definition: gl.h:1546
char JSAMPLE
Definition: jmorecfg.h:74
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:75
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
#define TRUE
Definition: types.h:120
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
JDIMENSION image_height
Definition: jpeglib.h:303
#define GETJSAMPLE(value)
Definition: jmorecfg.h:78
#define TRACEMS2(cinfo, lvl, code, p1, p2)
Definition: jerror.h:272
J_COLOR_SPACE in_color_space
Definition: jpeglib.h:305
#define SIZEOF(_ar)
Definition: calc.h:97
#define JPOOL_IMAGE
Definition: jpeglib.h:808
#define FALSE
Definition: types.h:117
int total_extra_passes
Definition: cdjpeg.h:85
int JSAMPARRAY int dest_row
Definition: jpegint.h:419
Definition: general.c:220
GLuint GLfloat * val
Definition: glext.h:7180
struct jpeg_progress_mgr pub
Definition: cdjpeg.h:83
Definition: inflate.c:139
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
#define GLOBAL(type)
Definition: jmorecfg.h:291
#define METHODDEF(type)
Definition: jmorecfg.h:287
int completed_extra_passes
Definition: cdjpeg.h:84
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
static GpImage * load_image(const BYTE *image_data, UINT image_size, BOOL valid_data, BOOL todo_load)
Definition: image.c:3239
#define NULL
Definition: types.h:112
cd_progress_ptr progress
Definition: cdjpeg.h:152
#define TRACEMS3(cinfo, lvl, code, p1, p2, p3)
Definition: jerror.h:277
unsigned int JDIMENSION
Definition: jmorecfg.h:229
struct cdjpeg_progress_mgr * cd_progress_ptr
Definition: cdjpeg.h:90
Sorry
Definition: jdcolor.c:19
struct CFHEADER header
Definition: fdi.c:101
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
JDIMENSION image_width
Definition: jpeglib.h:302