blob: 37bd286ae1dadda0c4678d88a50ede90d70928d5 [file] [log] [blame]
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +00001/*
2 * rdtarga.c
3 *
DRC5033f3e2014-05-18 18:33:44 +00004 * This file was part of the Independent JPEG Group's software:
Thomas G. Lane489583f1996-02-07 00:00:00 +00005 * Copyright (C) 1991-1996, Thomas G. Lane.
DRCd00d7d82018-10-05 16:13:07 -05006 * Modified 2017 by Guido Vollbeding.
7 * libjpeg-turbo Modifications:
8 * Copyright (C) 2018, D. R. Commander.
DRC7e3acc02015-10-10 10:25:46 -05009 * For conditions of distribution and use, see the accompanying README.ijg
10 * file.
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000011 *
12 * This file contains routines to read input images in Targa format.
13 *
14 * These routines may need modification for non-Unix environments or
15 * specialized applications. As they stand, they assume input from
16 * an ordinary stdio stream. They further assume that reading begins
17 * at the start of the file; start_input may need work if the
18 * user interface has already read some data (e.g., to determine that
19 * the file is indeed Targa format).
20 *
21 * Based on code contributed by Lee Daniel Crocker.
22 */
23
DRCe5eaf372014-05-09 18:00:32 +000024#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000025
26#ifdef TARGA_SUPPORTED
27
28
29/* Macros to deal with unsigned chars as efficiently as compiler allows */
30
31#ifdef HAVE_UNSIGNED_CHAR
32typedef unsigned char U_CHAR;
DRC19c791c2018-03-08 10:55:20 -060033#define UCH(x) ((int)(x))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000034#else /* !HAVE_UNSIGNED_CHAR */
DRC61976bd2014-04-20 19:13:10 +000035#ifdef __CHAR_UNSIGNED__
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000036typedef char U_CHAR;
DRC19c791c2018-03-08 10:55:20 -060037#define UCH(x) ((int)(x))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000038#else
39typedef char U_CHAR;
DRC19c791c2018-03-08 10:55:20 -060040#define UCH(x) ((int)(x) & 0xFF)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000041#endif
42#endif /* HAVE_UNSIGNED_CHAR */
43
44
DRC19c791c2018-03-08 10:55:20 -060045#define ReadOK(file, buffer, len) \
46 (JFREAD(file, buffer, len) == ((size_t)(len)))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000047
48
49/* Private version of data source object */
50
DRCbd498032016-02-19 08:53:33 -060051typedef struct _tga_source_struct *tga_source_ptr;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000052
53typedef struct _tga_source_struct {
54 struct cjpeg_source_struct pub; /* public fields */
55
DRCe5eaf372014-05-09 18:00:32 +000056 j_compress_ptr cinfo; /* back link saves passing separate parm */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000057
DRCe5eaf372014-05-09 18:00:32 +000058 JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000059
DRCe5eaf372014-05-09 18:00:32 +000060 jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
61 JDIMENSION current_row; /* Current logical row number to read */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000062
63 /* Pointer to routine to extract next Targa pixel from input file */
DRCbc56b752014-05-16 10:43:44 +000064 void (*read_pixel) (tga_source_ptr sinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000065
66 /* Result of read_pixel is delivered here: */
67 U_CHAR tga_pixel[4];
68
DRCe5eaf372014-05-09 18:00:32 +000069 int pixel_size; /* Bytes per Targa pixel (1 to 4) */
DRCd00d7d82018-10-05 16:13:07 -050070 int cmap_length; /* colormap length */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000071
72 /* State info for reading RLE-coded pixels; both counts must be init to 0 */
DRCe5eaf372014-05-09 18:00:32 +000073 int block_count; /* # of pixels remaining in RLE block */
74 int dup_pixel_count; /* # of times to duplicate previous pixel */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000075
76 /* This saves the correct pixel-row-expansion method for preload_image */
DRCbc56b752014-05-16 10:43:44 +000077 JDIMENSION (*get_pixel_rows) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000078} tga_source_struct;
79
80
81/* For expanding 5-bit pixel values to 8-bit with best rounding */
82
83static const UINT8 c5to8bits[32] = {
Thomas G. Lanebc79e061995-08-02 00:00:00 +000084 0, 8, 16, 25, 33, 41, 49, 58,
85 66, 74, 82, 90, 99, 107, 115, 123,
86 132, 140, 148, 156, 165, 173, 181, 189,
87 197, 206, 214, 222, 230, 239, 247, 255
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000088};
89
90
91
Thomas G. Lane489583f1996-02-07 00:00:00 +000092LOCAL(int)
DRC19c791c2018-03-08 10:55:20 -060093read_byte(tga_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000094/* Read next byte from Targa file */
95{
96 register FILE *infile = sinfo->pub.input_file;
97 register int c;
98
99 if ((c = getc(infile)) == EOF)
100 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
101 return c;
102}
103
104
Thomas G. Lane489583f1996-02-07 00:00:00 +0000105LOCAL(void)
DRC19c791c2018-03-08 10:55:20 -0600106read_colormap(tga_source_ptr sinfo, int cmaplen, int mapentrysize)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000107/* Read the colormap from a Targa file */
108{
109 int i;
110
111 /* Presently only handles 24-bit BGR format */
112 if (mapentrysize != 24)
113 ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
114
115 for (i = 0; i < cmaplen; i++) {
DRC19c791c2018-03-08 10:55:20 -0600116 sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo);
117 sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo);
118 sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000119 }
120}
121
122
123/*
124 * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
125 */
126
Thomas G. Lane489583f1996-02-07 00:00:00 +0000127METHODDEF(void)
DRC19c791c2018-03-08 10:55:20 -0600128read_non_rle_pixel(tga_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000129/* Read one Targa pixel from the input file; no RLE expansion */
130{
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000131 register int i;
132
133 for (i = 0; i < sinfo->pixel_size; i++) {
DRC909a8cf2018-06-12 16:08:26 -0500134 sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000135 }
136}
137
138
Thomas G. Lane489583f1996-02-07 00:00:00 +0000139METHODDEF(void)
DRC19c791c2018-03-08 10:55:20 -0600140read_rle_pixel(tga_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000141/* Read one Targa pixel from the input file, expanding RLE data as needed */
142{
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000143 register int i;
144
145 /* Duplicate previously read pixel? */
146 if (sinfo->dup_pixel_count > 0) {
147 sinfo->dup_pixel_count--;
148 return;
149 }
150
151 /* Time to read RLE block header? */
152 if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
153 i = read_byte(sinfo);
DRCe5eaf372014-05-09 18:00:32 +0000154 if (i & 0x80) { /* Start of duplicate-pixel block? */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000155 sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
DRCe5eaf372014-05-09 18:00:32 +0000156 sinfo->block_count = 0; /* then read new block header */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000157 } else {
158 sinfo->block_count = i & 0x7F; /* number of pixels after this one */
159 }
160 }
161
162 /* Read next pixel */
163 for (i = 0; i < sinfo->pixel_size; i++) {
DRC909a8cf2018-06-12 16:08:26 -0500164 sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000165 }
166}
167
168
169/*
170 * Read one row of pixels.
171 *
172 * We provide several different versions depending on input file format.
173 */
174
175
Thomas G. Lane489583f1996-02-07 00:00:00 +0000176METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600177get_8bit_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000178/* This version is for reading 8-bit grayscale pixels */
179{
DRC19c791c2018-03-08 10:55:20 -0600180 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000181 register JSAMPROW ptr;
182 register JDIMENSION col;
DRC61976bd2014-04-20 19:13:10 +0000183
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000184 ptr = source->pub.buffer[0];
185 for (col = cinfo->image_width; col > 0; col--) {
186 (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
DRC19c791c2018-03-08 10:55:20 -0600187 *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000188 }
189 return 1;
190}
191
Thomas G. Lane489583f1996-02-07 00:00:00 +0000192METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600193get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000194/* This version is for reading 8-bit colormap indexes */
195{
DRC19c791c2018-03-08 10:55:20 -0600196 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000197 register int t;
198 register JSAMPROW ptr;
199 register JDIMENSION col;
200 register JSAMPARRAY colormap = source->colormap;
DRCd00d7d82018-10-05 16:13:07 -0500201 int cmaplen = source->cmap_length;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000202
203 ptr = source->pub.buffer[0];
204 for (col = cinfo->image_width; col > 0; col--) {
205 (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
206 t = UCH(source->tga_pixel[0]);
DRCd00d7d82018-10-05 16:13:07 -0500207 if (t >= cmaplen)
208 ERREXIT(cinfo, JERR_TGA_BADPARMS);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000209 *ptr++ = colormap[0][t];
210 *ptr++ = colormap[1][t];
211 *ptr++ = colormap[2][t];
212 }
213 return 1;
214}
215
Thomas G. Lane489583f1996-02-07 00:00:00 +0000216METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600217get_16bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000218/* This version is for reading 16-bit pixels */
219{
DRC19c791c2018-03-08 10:55:20 -0600220 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000221 register int t;
222 register JSAMPROW ptr;
223 register JDIMENSION col;
DRC61976bd2014-04-20 19:13:10 +0000224
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000225 ptr = source->pub.buffer[0];
226 for (col = cinfo->image_width; col > 0; col--) {
227 (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
228 t = UCH(source->tga_pixel[0]);
229 t += UCH(source->tga_pixel[1]) << 8;
230 /* We expand 5 bit data to 8 bit sample width.
231 * The format of the 16-bit (LSB first) input word is
232 * xRRRRRGGGGGBBBBB
233 */
DRC19c791c2018-03-08 10:55:20 -0600234 ptr[2] = (JSAMPLE)c5to8bits[t & 0x1F];
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000235 t >>= 5;
DRC19c791c2018-03-08 10:55:20 -0600236 ptr[1] = (JSAMPLE)c5to8bits[t & 0x1F];
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000237 t >>= 5;
DRC19c791c2018-03-08 10:55:20 -0600238 ptr[0] = (JSAMPLE)c5to8bits[t & 0x1F];
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000239 ptr += 3;
240 }
241 return 1;
242}
243
Thomas G. Lane489583f1996-02-07 00:00:00 +0000244METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600245get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000246/* This version is for reading 24-bit pixels */
247{
DRC19c791c2018-03-08 10:55:20 -0600248 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000249 register JSAMPROW ptr;
250 register JDIMENSION col;
DRC61976bd2014-04-20 19:13:10 +0000251
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000252 ptr = source->pub.buffer[0];
253 for (col = cinfo->image_width; col > 0; col--) {
254 (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
DRC19c791c2018-03-08 10:55:20 -0600255 *ptr++ = (JSAMPLE)UCH(source->tga_pixel[2]); /* change BGR to RGB order */
256 *ptr++ = (JSAMPLE)UCH(source->tga_pixel[1]);
257 *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000258 }
259 return 1;
260}
261
262/*
263 * Targa also defines a 32-bit pixel format with order B,G,R,A.
264 * We presently ignore the attribute byte, so the code for reading
265 * these pixels is identical to the 24-bit routine above.
266 * This works because the actual pixel length is only known to read_pixel.
267 */
268
269#define get_32bit_row get_24bit_row
270
271
272/*
273 * This method is for re-reading the input data in standard top-down
274 * row order. The entire image has already been read into whole_image
275 * with proper conversion of pixel format, but it's in a funny row order.
276 */
277
Thomas G. Lane489583f1996-02-07 00:00:00 +0000278METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600279get_memory_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000280{
DRC19c791c2018-03-08 10:55:20 -0600281 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000282 JDIMENSION source_row;
283
284 /* Compute row of source that maps to current_row of normal order */
285 /* For now, assume image is bottom-up and not interlaced. */
286 /* NEEDS WORK to support interlaced images! */
287 source_row = cinfo->image_height - source->current_row - 1;
288
289 /* Fetch that row from virtual array */
290 source->pub.buffer = (*cinfo->mem->access_virt_sarray)
DRC19c791c2018-03-08 10:55:20 -0600291 ((j_common_ptr)cinfo, source->whole_image,
292 source_row, (JDIMENSION)1, FALSE);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000293
294 source->current_row++;
295 return 1;
296}
297
298
299/*
300 * This method loads the image into whole_image during the first call on
301 * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
302 * get_memory_row on subsequent calls.
303 */
304
Thomas G. Lane489583f1996-02-07 00:00:00 +0000305METHODDEF(JDIMENSION)
DRC19c791c2018-03-08 10:55:20 -0600306preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000307{
DRC19c791c2018-03-08 10:55:20 -0600308 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000309 JDIMENSION row;
DRC19c791c2018-03-08 10:55:20 -0600310 cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000311
312 /* Read the data into a virtual array in input-file row order. */
313 for (row = 0; row < cinfo->image_height; row++) {
314 if (progress != NULL) {
DRC19c791c2018-03-08 10:55:20 -0600315 progress->pub.pass_counter = (long)row;
316 progress->pub.pass_limit = (long)cinfo->image_height;
317 (*progress->pub.progress_monitor) ((j_common_ptr)cinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000318 }
319 source->pub.buffer = (*cinfo->mem->access_virt_sarray)
DRC19c791c2018-03-08 10:55:20 -0600320 ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000321 (*source->get_pixel_rows) (cinfo, sinfo);
322 }
323 if (progress != NULL)
324 progress->completed_extra_passes++;
325
326 /* Set up to read from the virtual array in unscrambled order */
327 source->pub.get_pixel_rows = get_memory_row;
328 source->current_row = 0;
329 /* And read the first row */
330 return get_memory_row(cinfo, sinfo);
331}
332
333
334/*
335 * Read the file header; return image size and component count.
336 */
337
Thomas G. Lane489583f1996-02-07 00:00:00 +0000338METHODDEF(void)
DRC19c791c2018-03-08 10:55:20 -0600339start_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000340{
DRC19c791c2018-03-08 10:55:20 -0600341 tga_source_ptr source = (tga_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000342 U_CHAR targaheader[18];
343 int idlen, cmaptype, subtype, flags, interlace_type, components;
344 unsigned int width, height, maplen;
345 boolean is_bottom_up;
346
DRC19c791c2018-03-08 10:55:20 -0600347#define GET_2B(offset) ((unsigned int)UCH(targaheader[offset]) + \
348 (((unsigned int)UCH(targaheader[offset + 1])) << 8))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000349
DRC19c791c2018-03-08 10:55:20 -0600350 if (!ReadOK(source->pub.input_file, targaheader, 18))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000351 ERREXIT(cinfo, JERR_INPUT_EOF);
352
353 /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
354 if (targaheader[16] == 15)
355 targaheader[16] = 16;
356
357 idlen = UCH(targaheader[0]);
358 cmaptype = UCH(targaheader[1]);
359 subtype = UCH(targaheader[2]);
360 maplen = GET_2B(5);
361 width = GET_2B(12);
362 height = GET_2B(14);
363 source->pixel_size = UCH(targaheader[16]) >> 3;
DRCe5eaf372014-05-09 18:00:32 +0000364 flags = UCH(targaheader[17]); /* Image Descriptor byte */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000365
DRCe5eaf372014-05-09 18:00:32 +0000366 is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
367 interlace_type = flags >> 6; /* bits 6/7 are interlace code */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000368
DRCe5eaf372014-05-09 18:00:32 +0000369 if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000370 source->pixel_size < 1 || source->pixel_size > 4 ||
371 (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
Frank Bossen82923eb2014-12-29 18:38:36 +0100372 interlace_type != 0 || /* currently don't allow interlaced image */
373 width == 0 || height == 0) /* image width/height must be non-zero */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000374 ERREXIT(cinfo, JERR_TGA_BADPARMS);
DRC61976bd2014-04-20 19:13:10 +0000375
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000376 if (subtype > 8) {
377 /* It's an RLE-coded file */
378 source->read_pixel = read_rle_pixel;
379 source->block_count = source->dup_pixel_count = 0;
380 subtype -= 8;
381 } else {
382 /* Non-RLE file */
383 source->read_pixel = read_non_rle_pixel;
384 }
385
386 /* Now should have subtype 1, 2, or 3 */
DRCe5eaf372014-05-09 18:00:32 +0000387 components = 3; /* until proven different */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000388 cinfo->in_color_space = JCS_RGB;
389
390 switch (subtype) {
DRCe5eaf372014-05-09 18:00:32 +0000391 case 1: /* Colormapped image */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000392 if (source->pixel_size == 1 && cmaptype == 1)
393 source->get_pixel_rows = get_8bit_row;
394 else
395 ERREXIT(cinfo, JERR_TGA_BADPARMS);
396 TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
397 break;
DRCe5eaf372014-05-09 18:00:32 +0000398 case 2: /* RGB image */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000399 switch (source->pixel_size) {
400 case 2:
401 source->get_pixel_rows = get_16bit_row;
402 break;
403 case 3:
404 source->get_pixel_rows = get_24bit_row;
405 break;
406 case 4:
407 source->get_pixel_rows = get_32bit_row;
408 break;
409 default:
410 ERREXIT(cinfo, JERR_TGA_BADPARMS);
411 break;
412 }
413 TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
414 break;
DRCe5eaf372014-05-09 18:00:32 +0000415 case 3: /* Grayscale image */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000416 components = 1;
417 cinfo->in_color_space = JCS_GRAYSCALE;
418 if (source->pixel_size == 1)
419 source->get_pixel_rows = get_8bit_gray_row;
420 else
421 ERREXIT(cinfo, JERR_TGA_BADPARMS);
422 TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
423 break;
424 default:
425 ERREXIT(cinfo, JERR_TGA_BADPARMS);
426 break;
427 }
428
429 if (is_bottom_up) {
430 /* Create a virtual array to buffer the upside-down image. */
431 source->whole_image = (*cinfo->mem->request_virt_sarray)
DRC19c791c2018-03-08 10:55:20 -0600432 ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
433 (JDIMENSION)width * components, (JDIMENSION)height, (JDIMENSION)1);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000434 if (cinfo->progress != NULL) {
DRC19c791c2018-03-08 10:55:20 -0600435 cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000436 progress->total_extra_passes++; /* count file input as separate pass */
437 }
438 /* source->pub.buffer will point to the virtual array. */
439 source->pub.buffer_height = 1; /* in case anyone looks at it */
440 source->pub.get_pixel_rows = preload_image;
441 } else {
442 /* Don't need a virtual array, but do need a one-row input buffer. */
443 source->whole_image = NULL;
444 source->pub.buffer = (*cinfo->mem->alloc_sarray)
DRC19c791c2018-03-08 10:55:20 -0600445 ((j_common_ptr)cinfo, JPOOL_IMAGE,
446 (JDIMENSION)width * components, (JDIMENSION)1);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000447 source->pub.buffer_height = 1;
448 source->pub.get_pixel_rows = source->get_pixel_rows;
449 }
DRC61976bd2014-04-20 19:13:10 +0000450
DRCe5eaf372014-05-09 18:00:32 +0000451 while (idlen--) /* Throw away ID field */
DRC19c791c2018-03-08 10:55:20 -0600452 (void)read_byte(source);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000453
454 if (maplen > 0) {
455 if (maplen > 256 || GET_2B(3) != 0)
456 ERREXIT(cinfo, JERR_TGA_BADCMAP);
457 /* Allocate space to store the colormap */
458 source->colormap = (*cinfo->mem->alloc_sarray)
DRC19c791c2018-03-08 10:55:20 -0600459 ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)maplen, (JDIMENSION)3);
DRCd00d7d82018-10-05 16:13:07 -0500460 source->cmap_length = (int)maplen;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000461 /* and read it from the file */
DRC19c791c2018-03-08 10:55:20 -0600462 read_colormap(source, (int)maplen, UCH(targaheader[7]));
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000463 } else {
DRCe5eaf372014-05-09 18:00:32 +0000464 if (cmaptype) /* but you promised a cmap! */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000465 ERREXIT(cinfo, JERR_TGA_BADPARMS);
466 source->colormap = NULL;
DRCd00d7d82018-10-05 16:13:07 -0500467 source->cmap_length = 0;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000468 }
469
470 cinfo->input_components = components;
471 cinfo->data_precision = 8;
472 cinfo->image_width = width;
473 cinfo->image_height = height;
474}
475
476
477/*
478 * Finish up at the end of the file.
479 */
480
Thomas G. Lane489583f1996-02-07 00:00:00 +0000481METHODDEF(void)
DRC19c791c2018-03-08 10:55:20 -0600482finish_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000483{
484 /* no work */
485}
486
487
488/*
489 * The module selection routine for Targa format input.
490 */
491
Thomas G. Lane489583f1996-02-07 00:00:00 +0000492GLOBAL(cjpeg_source_ptr)
DRC19c791c2018-03-08 10:55:20 -0600493jinit_read_targa(j_compress_ptr cinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000494{
495 tga_source_ptr source;
496
497 /* Create module interface object */
498 source = (tga_source_ptr)
DRC19c791c2018-03-08 10:55:20 -0600499 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
500 sizeof(tga_source_struct));
DRCe5eaf372014-05-09 18:00:32 +0000501 source->cinfo = cinfo; /* make back link for subroutines */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000502 /* Fill in method ptrs, except get_pixel_rows which start_input sets */
503 source->pub.start_input = start_input_tga;
504 source->pub.finish_input = finish_input_tga;
505
DRC19c791c2018-03-08 10:55:20 -0600506 return (cjpeg_source_ptr)source;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000507}
508
509#endif /* TARGA_SUPPORTED */