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