ReactOS  0.4.14-dev-999-g61c8d34
rdtarga.c
Go to the documentation of this file.
1 /*
2  * rdtarga.c
3  *
4  * Copyright (C) 1991-1996, Thomas G. Lane.
5  * Modified 2017-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 Targa format.
10  *
11  * These routines may need modification for non-Unix environments or
12  * specialized applications. As they stand, they assume input from
13  * an ordinary stdio stream. They further assume that reading begins
14  * at the start of the file; start_input may need work if the
15  * user interface has already read some data (e.g., to determine that
16  * the file is indeed Targa format).
17  *
18  * Based on code contributed by Lee Daniel Crocker.
19  */
20 
21 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
22 
23 #ifdef TARGA_SUPPORTED
24 
25 
26 /* Macros to deal with unsigned chars as efficiently as compiler allows */
27 
28 #ifdef HAVE_UNSIGNED_CHAR
29 typedef unsigned char U_CHAR;
30 #define UCH(x) ((int) (x))
31 #else /* !HAVE_UNSIGNED_CHAR */
32 typedef char U_CHAR;
33 #ifdef CHAR_IS_UNSIGNED
34 #define UCH(x) ((int) (x))
35 #else
36 #define UCH(x) ((int) (x) & 0xFF)
37 #endif
38 #endif /* HAVE_UNSIGNED_CHAR */
39 
40 
41 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
42 
43 
44 /* Private version of data source object */
45 
46 typedef struct _tga_source_struct * tga_source_ptr;
47 
48 typedef struct _tga_source_struct {
49  struct cjpeg_source_struct pub; /* public fields */
50 
51  j_compress_ptr cinfo; /* back link saves passing separate parm */
52 
53  JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
54 
55  jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
56  JDIMENSION current_row; /* Current logical row number to read */
57 
58  /* Pointer to routine to extract next Targa pixel from input file */
59  JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
60 
61  /* Result of read_pixel is delivered here: */
62  U_CHAR tga_pixel[4];
63 
64  int pixel_size; /* Bytes per Targa pixel (1 to 4) */
65  int cmap_length; /* colormap length */
66 
67  /* State info for reading RLE-coded pixels; both counts must be init to 0 */
68  int block_count; /* # of pixels remaining in RLE block */
69  int dup_pixel_count; /* # of times to duplicate previous pixel */
70 
71  /* This saves the correct pixel-row-expansion method for preload_image */
72  JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
74 } tga_source_struct;
75 
76 
77 /* For expanding 5-bit pixel values to 8-bit with best rounding */
78 
79 static const UINT8 c5to8bits[32] = {
80  0, 8, 16, 25, 33, 41, 49, 58,
81  66, 74, 82, 90, 99, 107, 115, 123,
82  132, 140, 148, 156, 165, 173, 181, 189,
83  197, 206, 214, 222, 230, 239, 247, 255
84 };
85 
86 
87 
88 LOCAL(int)
89 read_byte (tga_source_ptr sinfo)
90 /* Read next byte from Targa file */
91 {
92  register FILE *infile = sinfo->pub.input_file;
93  register int c;
94 
95  if ((c = getc(infile)) == EOF)
96  ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
97  return c;
98 }
99 
100 
101 LOCAL(void)
102 read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
103 /* Read the colormap from a Targa file */
104 {
105  int i;
106 
107  /* Presently only handles 24-bit BGR format */
108  if (mapentrysize != 24)
109  ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
110 
111  for (i = 0; i < cmaplen; i++) {
112  sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
113  sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
114  sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
115  }
116 }
117 
118 
119 /*
120  * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
121  */
122 
123 METHODDEF(void)
124 read_non_rle_pixel (tga_source_ptr sinfo)
125 /* Read one Targa pixel from the input file; no RLE expansion */
126 {
127  register int i;
128 
129  for (i = 0; i < sinfo->pixel_size; i++) {
130  sinfo->tga_pixel[i] = (U_CHAR) read_byte(sinfo);
131  }
132 }
133 
134 METHODDEF(void)
135 read_rle_pixel (tga_source_ptr sinfo)
136 /* Read one Targa pixel from the input file, expanding RLE data as needed */
137 {
138  register int i;
139 
140  /* Duplicate previously read pixel? */
141  if (sinfo->dup_pixel_count > 0) {
142  sinfo->dup_pixel_count--;
143  return;
144  }
145 
146  /* Time to read RLE block header? */
147  if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
148  i = read_byte(sinfo);
149  if (i & 0x80) { /* Start of duplicate-pixel block? */
150  sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
151  sinfo->block_count = 0; /* then read new block header */
152  } else {
153  sinfo->block_count = i & 0x7F; /* number of pixels after this one */
154  }
155  }
156 
157  /* Read next pixel */
158  for (i = 0; i < sinfo->pixel_size; i++) {
159  sinfo->tga_pixel[i] = (U_CHAR) read_byte(sinfo);
160  }
161 }
162 
163 
164 /*
165  * Read one row of pixels.
166  *
167  * We provide several different versions depending on input file format.
168  */
169 
171 get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
172 /* This version is for reading 8-bit grayscale pixels */
173 {
174  tga_source_ptr source = (tga_source_ptr) sinfo;
175  register JSAMPROW ptr;
176  register JDIMENSION col;
177 
178  ptr = source->pub.buffer[0];
179  for (col = cinfo->image_width; col > 0; col--) {
180  (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
181  *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
182  }
183  return 1;
184 }
185 
187 get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
188 /* This version is for reading 8-bit colormap indexes */
189 {
190  tga_source_ptr source = (tga_source_ptr) sinfo;
191  register JSAMPROW ptr;
192  register JSAMPARRAY colormap;
193  register JDIMENSION col;
194  register int t;
195  int cmaplen;
196 
197  ptr = source->pub.buffer[0];
198  colormap = source->colormap;
199  cmaplen = source->cmap_length;
200  for (col = cinfo->image_width; col > 0; col--) {
201  (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
202  t = UCH(source->tga_pixel[0]);
203  if (t >= cmaplen)
204  ERREXIT(cinfo, JERR_TGA_BADPARMS);
205  *ptr++ = colormap[0][t];
206  *ptr++ = colormap[1][t];
207  *ptr++ = colormap[2][t];
208  }
209  return 1;
210 }
211 
213 get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
214 /* This version is for reading 16-bit pixels */
215 {
216  tga_source_ptr source = (tga_source_ptr) sinfo;
217  register int t;
218  register JSAMPROW ptr;
219  register JDIMENSION col;
220 
221  ptr = source->pub.buffer[0];
222  for (col = cinfo->image_width; col > 0; col--) {
223  (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
224  t = UCH(source->tga_pixel[0]);
225  t += UCH(source->tga_pixel[1]) << 8;
226  /* We expand 5 bit data to 8 bit sample width.
227  * The format of the 16-bit (LSB first) input word is
228  * xRRRRRGGGGGBBBBB
229  */
230  ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
231  t >>= 5;
232  ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
233  t >>= 5;
234  ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
235  ptr += 3;
236  }
237  return 1;
238 }
239 
241 get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
242 /* This version is for reading 24-bit pixels */
243 {
244  tga_source_ptr source = (tga_source_ptr) sinfo;
245  register JSAMPROW ptr;
246  register JDIMENSION col;
247 
248  ptr = source->pub.buffer[0];
249  for (col = cinfo->image_width; col > 0; col--) {
250  (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
251  *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
252  *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
253  *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
254  }
255  return 1;
256 }
257 
258 /*
259  * Targa also defines a 32-bit pixel format with order B,G,R,A.
260  * We presently ignore the attribute byte, so the code for reading
261  * these pixels is identical to the 24-bit routine above.
262  * This works because the actual pixel length is only known to read_pixel.
263  */
264 
265 #define get_32bit_row get_24bit_row
266 
267 
268 /*
269  * This method is for re-reading the input data in standard top-down
270  * row order. The entire image has already been read into whole_image
271  * with proper conversion of pixel format, but it's in a funny row order.
272  */
273 
275 get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
276 {
277  tga_source_ptr source = (tga_source_ptr) sinfo;
279 
280  /* Compute row of source that maps to current_row of normal order */
281  /* For now, assume image is bottom-up and not interlaced. */
282  /* NEEDS WORK to support interlaced images! */
283  source_row = cinfo->image_height - source->current_row - 1;
284 
285  /* Fetch that row from virtual array */
286  source->pub.buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
287  source->whole_image, source_row, (JDIMENSION) 1, FALSE);
288 
289  source->current_row++;
290  return 1;
291 }
292 
293 
294 /*
295  * This method loads the image into whole_image during the first call on
296  * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
297  * get_memory_row on subsequent calls.
298  */
299 
301 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
302 {
303  tga_source_ptr source = (tga_source_ptr) sinfo;
304  JDIMENSION row;
305  cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
306 
307  /* Read the data into a virtual array in input-file row order. */
308  for (row = 0; row < cinfo->image_height; row++) {
309  if (progress != NULL) {
310  progress->pub.pass_counter = (long) row;
311  progress->pub.pass_limit = (long) cinfo->image_height;
312  (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
313  }
314  source->pub.buffer = (*cinfo->mem->access_virt_sarray)
315  ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
316  (*source->get_pixel_rows) (cinfo, sinfo);
317  }
318  if (progress != NULL)
320 
321  /* Set up to read from the virtual array in unscrambled order */
322  source->pub.get_pixel_rows = get_memory_row;
323  source->current_row = 0;
324  /* And read the first row */
325  return get_memory_row(cinfo, sinfo);
326 }
327 
328 
329 /*
330  * Read the file header; return image size and component count.
331  */
332 
333 METHODDEF(void)
334 start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
335 {
336  tga_source_ptr source = (tga_source_ptr) sinfo;
337  U_CHAR targaheader[18];
338  int idlen, cmaptype, subtype, flags, interlace_type, components;
339  unsigned int width, height, maplen;
340  boolean is_bottom_up;
341 
342 #define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \
343  (((unsigned int) UCH(targaheader[offset+1])) << 8))
344 
345  if (! ReadOK(source->pub.input_file, targaheader, 18))
346  ERREXIT(cinfo, JERR_INPUT_EOF);
347 
348  /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
349  if (targaheader[16] == 15)
350  targaheader[16] = 16;
351 
352  idlen = UCH(targaheader[0]);
353  cmaptype = UCH(targaheader[1]);
354  subtype = UCH(targaheader[2]);
355  maplen = GET_2B(5);
356  width = GET_2B(12);
357  height = GET_2B(14);
358  source->pixel_size = UCH(targaheader[16]) >> 3;
359  flags = UCH(targaheader[17]); /* Image Descriptor byte */
360 
361  is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
362  interlace_type = flags >> 6; /* bits 6/7 are interlace code */
363 
364  if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
365  width <= 0 || height <= 0 ||
366  source->pixel_size < 1 || source->pixel_size > 4 ||
367  (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
368  interlace_type != 0) /* currently don't allow interlaced image */
369  ERREXIT(cinfo, JERR_TGA_BADPARMS);
370 
371  if (subtype > 8) {
372  /* It's an RLE-coded file */
373  source->read_pixel = read_rle_pixel;
374  source->block_count = source->dup_pixel_count = 0;
375  subtype -= 8;
376  } else {
377  /* Non-RLE file */
378  source->read_pixel = read_non_rle_pixel;
379  }
380 
381  /* Now should have subtype 1, 2, or 3 */
382  components = 3; /* until proven different */
383  cinfo->in_color_space = JCS_RGB;
384 
385  switch (subtype) {
386  case 1: /* Colormapped image */
387  if (source->pixel_size == 1 && cmaptype == 1)
388  source->get_pixel_rows = get_8bit_row;
389  else
390  ERREXIT(cinfo, JERR_TGA_BADPARMS);
391  TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
392  break;
393  case 2: /* RGB image */
394  switch (source->pixel_size) {
395  case 2:
396  source->get_pixel_rows = get_16bit_row;
397  break;
398  case 3:
399  source->get_pixel_rows = get_24bit_row;
400  break;
401  case 4:
402  source->get_pixel_rows = get_32bit_row;
403  break;
404  default:
405  ERREXIT(cinfo, JERR_TGA_BADPARMS);
406  }
407  TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
408  break;
409  case 3: /* Grayscale image */
410  components = 1;
411  cinfo->in_color_space = JCS_GRAYSCALE;
412  if (source->pixel_size == 1)
413  source->get_pixel_rows = get_8bit_gray_row;
414  else
415  ERREXIT(cinfo, JERR_TGA_BADPARMS);
416  TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
417  break;
418  default:
419  ERREXIT(cinfo, JERR_TGA_BADPARMS);
420  }
421 
422  if (is_bottom_up) {
423  /* Create a virtual array to buffer the upside-down image. */
424  source->whole_image = (*cinfo->mem->request_virt_sarray)
425  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
427  if (cinfo->progress != NULL) {
428  cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
429  progress->total_extra_passes++; /* count file input as separate pass */
430  }
431  /* source->pub.buffer will point to the virtual array. */
432  source->pub.buffer_height = 1; /* in case anyone looks at it */
433  source->pub.get_pixel_rows = preload_image;
434  } else {
435  /* Don't need a virtual array, but do need a one-row input buffer. */
436  source->whole_image = NULL;
437  source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,
439  source->pub.buffer_height = 1;
440  source->pub.get_pixel_rows = source->get_pixel_rows;
441  }
442 
443  while (idlen--) /* Throw away ID field */
444  (void) read_byte(source);
445 
446  if (maplen > 0) {
447  if (maplen > 256 || GET_2B(3) != 0)
448  ERREXIT(cinfo, JERR_TGA_BADCMAP);
449  /* Allocate space to store the colormap */
450  source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,
451  JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
452  source->cmap_length = (int) maplen;
453  /* and read it from the file */
454  read_colormap(source, (int) maplen, UCH(targaheader[7]));
455  } else {
456  if (cmaptype) /* but you promised a cmap! */
457  ERREXIT(cinfo, JERR_TGA_BADPARMS);
458  source->colormap = NULL;
459  source->cmap_length = 0;
460  }
461 
462  cinfo->input_components = components;
463  cinfo->data_precision = 8;
464  cinfo->image_width = width;
465  cinfo->image_height = height;
466 }
467 
468 
469 /*
470  * Finish up at the end of the file.
471  */
472 
473 METHODDEF(void)
474 finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
475 {
476  /* no work */
477 }
478 
479 
480 /*
481  * The module selection routine for Targa format input.
482  */
483 
485 jinit_read_targa (j_compress_ptr cinfo)
486 {
487  tga_source_ptr source;
488 
489  /* Create module interface object */
490  source = (tga_source_ptr) (*cinfo->mem->alloc_small)
491  ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(tga_source_struct));
492  source->cinfo = cinfo; /* make back link for subroutines */
493  /* Fill in method ptrs, except get_pixel_rows which start_input sets */
494  source->pub.start_input = start_input_tga;
495  source->pub.finish_input = finish_input_tga;
496 
497  return &source->pub;
498 }
499 
500 #endif /* TARGA_SUPPORTED */
GLint GLint GLsizei width
Definition: gl.h:1546
static int read_byte(struct input_stream *in, unsigned char *byte)
Definition: gifformat.c:1933
#define TRUE
Definition: types.h:120
char JSAMPLE
Definition: jmorecfg.h:74
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:75
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
GLdouble GLdouble t
Definition: gl.h:2047
JDIMENSION image_height
Definition: jpeglib.h:303
_Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE *_File)
static FILE * infile
Definition: rdjpgcom.c:65
#define TRACEMS2(cinfo, lvl, code, p1, p2)
Definition: jerror.h:272
J_COLOR_SPACE in_color_space
Definition: jpeglib.h:305
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define SIZEOF(_ar)
Definition: calc.h:97
#define JPOOL_IMAGE
Definition: jpeglib.h:808
int total_extra_passes
Definition: cdjpeg.h:85
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
Definition: general.c:220
#define LOCAL(type)
Definition: jmorecfg.h:289
int source_row
Definition: jpegint.h:419
#define JMETHOD(type, methodname, arglist)
Definition: jmorecfg.h:308
const GLubyte * c
Definition: glext.h:8905
#define for
Definition: utility.h:88
GLbitfield flags
Definition: glext.h:7161
struct jpeg_progress_mgr pub
Definition: cdjpeg.h:83
GLenum GLenum GLuint components
Definition: glext.h:9620
JSAMPROW * JSAMPARRAY
Definition: jpeglib.h:76
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
#define long
Definition: qsort.c:33
cd_progress_ptr progress
Definition: cdjpeg.h:152
#define EOF
Definition: stdio.h:24
#define ReadOK(tif, buf, size)
Definition: tiffiop.h:252
unsigned int JDIMENSION
Definition: jmorecfg.h:229
struct cdjpeg_progress_mgr * cd_progress_ptr
Definition: cdjpeg.h:90
#define c
Definition: ke_i.h:80
unsigned char UINT8
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
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
JDIMENSION image_width
Definition: jpeglib.h:302