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