ReactOS 0.4.16-dev-91-g764881a
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
29typedef unsigned char U_CHAR;
30#define UCH(x) ((int) (x))
31#else /* !HAVE_UNSIGNED_CHAR */
32typedef 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
46typedef struct _tga_source_struct * tga_source_ptr;
47
48typedef 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
79static 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
88LOCAL(int)
89read_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
101LOCAL(void)
102read_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
123METHODDEF(void)
124read_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
134METHODDEF(void)
135read_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
171get_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
187get_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
213get_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
241get_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
275get_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
301preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
302{
303 tga_source_ptr source = (tga_source_ptr) sinfo;
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
333METHODDEF(void)
334start_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;
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 */
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
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
473METHODDEF(void)
474finish_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
485jinit_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 */
unsigned char UINT8
#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
static int read_byte(struct input_stream *in, unsigned char *byte)
Definition: gifformat.c:1933
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
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble t
Definition: gl.h:2047
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum GLenum GLuint components
Definition: glext.h:9620
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
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
_Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE *_File)
#define EOF
Definition: stdio.h:24
#define TRACEMS2(cinfo, lvl, code, p1, p2)
Definition: jerror.h:272
unsigned int JDIMENSION
Definition: jmorecfg.h:229
char JSAMPLE
Definition: jmorecfg.h:74
#define JMETHOD(type, methodname, arglist)
Definition: jmorecfg.h:308
#define LOCAL(type)
Definition: jmorecfg.h:289
#define METHODDEF(type)
Definition: jmorecfg.h:287
#define GLOBAL(type)
Definition: jmorecfg.h:291
int source_row
Definition: jpegint.h:419
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
@ JCS_GRAYSCALE
Definition: jpeglib.h:222
@ JCS_RGB
Definition: jpeglib.h:223
JSAMPROW * JSAMPARRAY
Definition: jpeglib.h:76
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:75
#define JPOOL_IMAGE
Definition: jpeglib.h:808
#define c
Definition: ke_i.h:80
#define for
Definition: utility.h:88
static PVOID ptr
Definition: dispmode.c:27
#define long
Definition: qsort.c:33
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
static FILE * infile
Definition: rdjpgcom.c:65
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
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
#define ReadOK(tif, buf, size)
Definition: tiffiop.h:252