Mercurial > libavcodec.hg
annotate tiff.c @ 4630:1416371d4a6c libavcodec
add avcodec_get_context_defaults2() / avcodec_alloc_context2() which take CodecType as an additional parameter
also mark them as NOT part of the public API yet, so we can change their argument to CodecID if we decide to do so
author | michael |
---|---|
date | Wed, 07 Mar 2007 09:29:44 +0000 |
parents | 48952197d91f |
children | 0860efc2f02b |
rev | line source |
---|---|
4013 | 1 /* |
2 * TIFF image decoder | |
3 * Copyright (c) 2006 Konstantin Shishkov | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 * | |
21 */ | |
22 #include "avcodec.h" | |
23 #ifdef CONFIG_ZLIB | |
24 #include <zlib.h> | |
25 #endif | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
26 #include "lzw.h" |
4013 | 27 |
28 /* abridged list of TIFF tags */ | |
29 enum TiffTags{ | |
30 TIFF_WIDTH = 0x100, | |
31 TIFF_HEIGHT, | |
32 TIFF_BPP, | |
33 TIFF_COMPR, | |
34 TIFF_INVERT = 0x106, | |
35 TIFF_STRIP_OFFS = 0x111, | |
36 TIFF_ROWSPERSTRIP = 0x116, | |
37 TIFF_STRIP_SIZE, | |
4192 | 38 TIFF_PLANAR = 0x11C, |
4013 | 39 TIFF_XPOS = 0x11E, |
40 TIFF_YPOS = 0x11F, | |
4186 | 41 TIFF_PREDICTOR = 0x13D, |
42 TIFF_PAL = 0x140 | |
4013 | 43 }; |
44 | |
45 enum TiffCompr{ | |
46 TIFF_RAW = 1, | |
47 TIFF_CCITT_RLE, | |
48 TIFF_G3, | |
49 TIFF_G4, | |
50 TIFF_LZW, | |
51 TIFF_JPEG, | |
52 TIFF_NEWJPEG, | |
53 TIFF_ADOBE_DEFLATE, | |
54 TIFF_PACKBITS = 0x8005, | |
55 TIFF_DEFLATE = 0x80B2 | |
56 }; | |
57 | |
58 enum TiffTypes{ | |
59 TIFF_BYTE = 1, | |
60 TIFF_STRING, | |
61 TIFF_SHORT, | |
62 TIFF_LONG, | |
63 TIFF_LONGLONG | |
64 }; | |
65 | |
4190 | 66 /** sizes of various TIFF field types */ |
67 static const int type_sizes[6] = { | |
68 0, 1, 100, 2, 4, 8 | |
69 }; | |
70 | |
4013 | 71 typedef struct TiffContext { |
72 AVCodecContext *avctx; | |
73 AVFrame picture; | |
74 | |
75 int width, height; | |
76 unsigned int bpp; | |
77 int le; | |
78 int compr; | |
4186 | 79 int invert; |
4013 | 80 |
81 int strips, rps; | |
82 int sot; | |
83 uint8_t* stripdata; | |
84 uint8_t* stripsizes; | |
85 int stripsize, stripoff; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
86 LZWState *lzw; |
4013 | 87 } TiffContext; |
88 | |
89 static int tget_short(uint8_t **p, int le){ | |
4364 | 90 int v = le ? AV_RL16(*p) : AV_RB16(*p); |
4013 | 91 *p += 2; |
92 return v; | |
93 } | |
94 | |
95 static int tget_long(uint8_t **p, int le){ | |
4364 | 96 int v = le ? AV_RL32(*p) : AV_RB32(*p); |
4013 | 97 *p += 4; |
98 return v; | |
99 } | |
100 | |
101 static int tget(uint8_t **p, int type, int le){ | |
102 switch(type){ | |
103 case TIFF_BYTE : return *(*p)++; | |
104 case TIFF_SHORT: return tget_short(p, le); | |
105 case TIFF_LONG : return tget_long (p, le); | |
106 default : return -1; | |
107 } | |
108 } | |
109 | |
110 static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, uint8_t *src, int size, int lines){ | |
111 int c, line, pixels, code; | |
112 uint8_t *ssrc = src; | |
113 int width = s->width * (s->bpp / 8); | |
114 #ifdef CONFIG_ZLIB | |
115 uint8_t *zbuf; unsigned long outlen; | |
116 | |
117 if(s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE){ | |
118 outlen = width * lines; | |
119 zbuf = av_malloc(outlen); | |
120 if(uncompress(zbuf, &outlen, src, size) != Z_OK){ | |
121 av_log(s->avctx, AV_LOG_ERROR, "Uncompressing failed (%lu of %lu)\n", outlen, (unsigned long)width * lines); | |
122 av_free(zbuf); | |
123 return -1; | |
124 } | |
125 src = zbuf; | |
126 for(line = 0; line < lines; line++){ | |
127 memcpy(dst, src, width); | |
128 dst += stride; | |
129 src += width; | |
130 } | |
131 av_free(zbuf); | |
132 return 0; | |
133 } | |
134 #endif | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
135 if(s->compr == TIFF_LZW){ |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
136 if(ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF) < 0){ |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
137 av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n"); |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
138 return -1; |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
139 } |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
140 } |
4013 | 141 for(line = 0; line < lines; line++){ |
142 if(src - ssrc > size){ | |
143 av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); | |
144 return -1; | |
145 } | |
146 switch(s->compr){ | |
147 case TIFF_RAW: | |
148 memcpy(dst, src, s->width * (s->bpp / 8)); | |
149 src += s->width * (s->bpp / 8); | |
150 break; | |
151 case TIFF_PACKBITS: | |
152 for(pixels = 0; pixels < width;){ | |
153 code = (int8_t)*src++; | |
154 if(code >= 0){ | |
155 code++; | |
156 if(pixels + code > width){ | |
157 av_log(s->avctx, AV_LOG_ERROR, "Copy went out of bounds\n"); | |
158 return -1; | |
159 } | |
160 memcpy(dst + pixels, src, code); | |
161 src += code; | |
162 pixels += code; | |
163 }else if(code != -128){ // -127..-1 | |
164 code = (-code) + 1; | |
165 if(pixels + code > width){ | |
166 av_log(s->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); | |
167 return -1; | |
168 } | |
169 c = *src++; | |
170 memset(dst + pixels, c, code); | |
171 pixels += code; | |
172 } | |
173 } | |
174 break; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
175 case TIFF_LZW: |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
176 pixels = ff_lzw_decode(s->lzw, dst, width); |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
177 if(pixels < width){ |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
178 av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", pixels, width); |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
179 return -1; |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
180 } |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
181 break; |
4013 | 182 } |
183 dst += stride; | |
184 } | |
185 return 0; | |
186 } | |
187 | |
188 | |
189 static int tiff_decode_tag(TiffContext *s, uint8_t *start, uint8_t *buf, uint8_t *end_buf, AVFrame *pic) | |
190 { | |
191 int tag, type, count, off, value = 0; | |
192 uint8_t *src, *dst; | |
193 int i, j, ssize, soff, stride; | |
4186 | 194 int *pal, *rp, *gp, *bp; |
4013 | 195 |
196 tag = tget_short(&buf, s->le); | |
197 type = tget_short(&buf, s->le); | |
198 count = tget_long(&buf, s->le); | |
199 off = tget_long(&buf, s->le); | |
200 | |
201 if(count == 1){ | |
202 switch(type){ | |
203 case TIFF_BYTE: | |
204 case TIFF_SHORT: | |
205 buf -= 4; | |
206 value = tget(&buf, type, s->le); | |
207 buf = NULL; | |
208 break; | |
209 case TIFF_LONG: | |
210 value = off; | |
211 buf = NULL; | |
212 break; | |
213 default: | |
214 value = -1; | |
215 buf = start + off; | |
216 } | |
4190 | 217 }else if(type_sizes[type] * count <= 4){ |
218 buf -= 4; | |
4013 | 219 }else{ |
220 buf = start + off; | |
221 } | |
222 | |
223 if(buf && (buf < start || buf > end_buf)){ | |
224 av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); | |
225 return -1; | |
226 } | |
227 | |
228 switch(tag){ | |
229 case TIFF_WIDTH: | |
230 s->width = value; | |
231 break; | |
232 case TIFF_HEIGHT: | |
233 s->height = value; | |
234 break; | |
235 case TIFF_BPP: | |
236 if(count == 1) s->bpp = value; | |
237 else{ | |
238 switch(type){ | |
239 case TIFF_BYTE: | |
4183 | 240 s->bpp = (off & 0xFF) + ((off >> 8) & 0xFF) + ((off >> 16) & 0xFF) + ((off >> 24) & 0xFF); |
4013 | 241 break; |
242 case TIFF_SHORT: | |
243 case TIFF_LONG: | |
4183 | 244 s->bpp = 0; |
245 for(i = 0; i < count; i++) s->bpp += tget(&buf, type, s->le); | |
4013 | 246 break; |
247 default: | |
248 s->bpp = -1; | |
249 } | |
250 } | |
4186 | 251 switch(s->bpp){ |
252 case 8: | |
253 s->avctx->pix_fmt = PIX_FMT_PAL8; | |
254 break; | |
255 case 24: | |
256 s->avctx->pix_fmt = PIX_FMT_RGB24; | |
257 break; | |
4193 | 258 case 16: |
259 if(count == 1){ | |
260 s->avctx->pix_fmt = PIX_FMT_GRAY16BE; | |
261 }else{ | |
262 av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%i)\n", s->bpp); | |
263 return -1; | |
264 } | |
265 break; | |
4186 | 266 default: |
4191 | 267 av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%i)\n", s->bpp); |
4013 | 268 return -1; |
269 } | |
4186 | 270 if(s->width != s->avctx->width || s->height != s->avctx->height){ |
271 if(avcodec_check_dimensions(s->avctx, s->width, s->height)) | |
272 return -1; | |
273 avcodec_set_dimensions(s->avctx, s->width, s->height); | |
274 } | |
275 if(s->picture.data[0]) | |
276 s->avctx->release_buffer(s->avctx, &s->picture); | |
277 if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){ | |
278 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
279 return -1; | |
280 } | |
281 if(s->bpp == 8){ | |
282 /* make default grayscale pal */ | |
283 pal = s->picture.data[1]; | |
284 for(i = 0; i < 256; i++) | |
285 pal[i] = i * 0x010101; | |
286 } | |
4013 | 287 break; |
288 case TIFF_COMPR: | |
289 s->compr = value; | |
290 switch(s->compr){ | |
291 case TIFF_RAW: | |
292 case TIFF_PACKBITS: | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
293 case TIFF_LZW: |
4013 | 294 break; |
295 case TIFF_DEFLATE: | |
296 case TIFF_ADOBE_DEFLATE: | |
297 #ifdef CONFIG_ZLIB | |
298 break; | |
299 #else | |
300 av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n"); | |
301 return -1; | |
302 #endif | |
303 case TIFF_G3: | |
304 av_log(s->avctx, AV_LOG_ERROR, "CCITT G3 compression is not supported\n"); | |
305 return -1; | |
306 case TIFF_G4: | |
307 av_log(s->avctx, AV_LOG_ERROR, "CCITT G4 compression is not supported\n"); | |
308 return -1; | |
309 case TIFF_CCITT_RLE: | |
310 av_log(s->avctx, AV_LOG_ERROR, "CCITT RLE compression is not supported\n"); | |
311 return -1; | |
4184 | 312 case TIFF_JPEG: |
313 case TIFF_NEWJPEG: | |
314 av_log(s->avctx, AV_LOG_ERROR, "JPEG compression is not supported\n"); | |
315 return -1; | |
4013 | 316 default: |
317 av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", s->compr); | |
318 return -1; | |
319 } | |
320 break; | |
321 case TIFF_ROWSPERSTRIP: | |
4185 | 322 if(value < 1){ |
4013 | 323 av_log(s->avctx, AV_LOG_ERROR, "Incorrect value of rows per strip\n"); |
324 return -1; | |
325 } | |
326 s->rps = value; | |
327 break; | |
328 case TIFF_STRIP_OFFS: | |
329 if(count == 1){ | |
330 s->stripdata = NULL; | |
331 s->stripoff = value; | |
332 }else | |
333 s->stripdata = start + off; | |
334 s->strips = count; | |
4405
48952197d91f
Some TIFFs do not set rows per strip for single strip.
kostya
parents:
4364
diff
changeset
|
335 if(s->strips == 1) s->rps = s->height; |
4013 | 336 s->sot = type; |
337 if(s->stripdata > end_buf){ | |
338 av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); | |
339 return -1; | |
340 } | |
341 break; | |
342 case TIFF_STRIP_SIZE: | |
343 if(count == 1){ | |
344 s->stripsizes = NULL; | |
345 s->stripsize = value; | |
346 s->strips = 1; | |
347 }else{ | |
348 s->stripsizes = start + off; | |
349 } | |
350 s->strips = count; | |
351 if(s->stripsizes > end_buf){ | |
352 av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); | |
353 return -1; | |
354 } | |
355 if(!pic->data[0]){ | |
356 av_log(s->avctx, AV_LOG_ERROR, "Picture initialization missing\n"); | |
357 return -1; | |
358 } | |
359 /* now we have the data and may start decoding */ | |
360 stride = pic->linesize[0]; | |
361 dst = pic->data[0]; | |
362 for(i = 0; i < s->height; i += s->rps){ | |
363 if(s->stripsizes) | |
364 ssize = tget(&s->stripsizes, type, s->le); | |
365 else | |
366 ssize = s->stripsize; | |
367 | |
368 if(s->stripdata){ | |
369 soff = tget(&s->stripdata, s->sot, s->le); | |
370 }else | |
371 soff = s->stripoff; | |
372 src = start + soff; | |
373 if(tiff_unpack_strip(s, dst, stride, src, ssize, FFMIN(s->rps, s->height - i)) < 0) | |
374 break; | |
375 dst += s->rps * stride; | |
376 } | |
377 break; | |
378 case TIFF_PREDICTOR: | |
379 if(!pic->data[0]){ | |
380 av_log(s->avctx, AV_LOG_ERROR, "Picture initialization missing\n"); | |
381 return -1; | |
382 } | |
383 if(value == 2){ | |
4079 | 384 src = pic->data[0]; |
4013 | 385 stride = pic->linesize[0]; |
386 soff = s->bpp >> 3; | |
387 ssize = s->width * soff; | |
388 for(i = 0; i < s->height; i++) { | |
389 for(j = soff; j < ssize; j++) | |
390 src[j] += src[j - soff]; | |
391 src += stride; | |
392 } | |
393 } | |
394 break; | |
4186 | 395 case TIFF_INVERT: |
396 switch(value){ | |
397 case 0: | |
398 s->invert = 1; | |
399 break; | |
400 case 1: | |
401 s->invert = 0; | |
402 break; | |
4187
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
403 case 2: |
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
404 case 3: |
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
405 break; |
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
406 default: |
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
407 av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n", value); |
46f12596304f
Print error message for unsupported mode (RGB planar,CMYK,YCrCb)
kostya
parents:
4186
diff
changeset
|
408 return -1; |
4186 | 409 } |
410 break; | |
411 case TIFF_PAL: | |
412 if(s->avctx->pix_fmt != PIX_FMT_PAL8){ | |
413 av_log(s->avctx, AV_LOG_ERROR, "Palette met but this is not palettized format\n"); | |
414 return -1; | |
415 } | |
416 pal = s->picture.data[1]; | |
4190 | 417 off = type_sizes[type]; |
4186 | 418 rp = buf; |
419 gp = buf + count / 3 * off; | |
420 bp = buf + count / 3 * off * 2; | |
4190 | 421 off = (type_sizes[type] - 1) << 3; |
4186 | 422 for(i = 0; i < count / 3; i++){ |
423 j = (tget(&rp, type, s->le) >> off) << 16; | |
424 j |= (tget(&gp, type, s->le) >> off) << 8; | |
425 j |= tget(&bp, type, s->le) >> off; | |
426 pal[i] = j; | |
427 } | |
4192 | 428 break; |
429 case TIFF_PLANAR: | |
430 if(value == 2){ | |
431 av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n"); | |
432 return -1; | |
433 } | |
434 break; | |
4013 | 435 } |
436 return 0; | |
437 } | |
438 | |
439 static int decode_frame(AVCodecContext *avctx, | |
440 void *data, int *data_size, | |
441 uint8_t *buf, int buf_size) | |
442 { | |
443 TiffContext * const s = avctx->priv_data; | |
444 AVFrame *picture = data; | |
445 AVFrame * const p= (AVFrame*)&s->picture; | |
446 uint8_t *orig_buf = buf, *end_buf = buf + buf_size; | |
447 int id, le, off; | |
448 int i, entries; | |
449 | |
450 //parse image header | |
4364 | 451 id = AV_RL16(buf); buf += 2; |
4013 | 452 if(id == 0x4949) le = 1; |
453 else if(id == 0x4D4D) le = 0; | |
454 else{ | |
455 av_log(avctx, AV_LOG_ERROR, "TIFF header not found\n"); | |
456 return -1; | |
457 } | |
458 s->le = le; | |
4186 | 459 s->invert = 0; |
4013 | 460 // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number |
461 // that further identifies the file as a TIFF file" | |
462 if(tget_short(&buf, le) != 42){ | |
463 av_log(avctx, AV_LOG_ERROR, "The answer to life, universe and everything is not correct!\n"); | |
464 return -1; | |
465 } | |
466 /* parse image file directory */ | |
467 off = tget_long(&buf, le); | |
468 if(orig_buf + off + 14 >= end_buf){ | |
469 av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n"); | |
470 return -1; | |
471 } | |
472 buf = orig_buf + off; | |
473 entries = tget_short(&buf, le); | |
474 for(i = 0; i < entries; i++){ | |
475 if(tiff_decode_tag(s, orig_buf, buf, end_buf, p) < 0) | |
476 return -1; | |
477 buf += 12; | |
478 } | |
479 | |
4186 | 480 if(s->invert){ |
481 uint8_t *src; | |
482 int j; | |
483 | |
484 src = s->picture.data[0]; | |
485 for(j = 0; j < s->height; j++){ | |
486 for(i = 0; i < s->picture.linesize[0]; i++) | |
487 src[i] = 255 - src[i]; | |
488 src += s->picture.linesize[0]; | |
489 } | |
490 } | |
4013 | 491 *picture= *(AVFrame*)&s->picture; |
492 *data_size = sizeof(AVPicture); | |
493 | |
494 return buf_size; | |
495 } | |
496 | |
497 static int tiff_init(AVCodecContext *avctx){ | |
498 TiffContext *s = avctx->priv_data; | |
499 | |
500 s->width = 0; | |
501 s->height = 0; | |
502 s->avctx = avctx; | |
503 avcodec_get_frame_defaults((AVFrame*)&s->picture); | |
504 avctx->coded_frame= (AVFrame*)&s->picture; | |
505 s->picture.data[0] = NULL; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
506 ff_lzw_decode_open(&s->lzw); |
4013 | 507 |
508 return 0; | |
509 } | |
510 | |
511 static int tiff_end(AVCodecContext *avctx) | |
512 { | |
513 TiffContext * const s = avctx->priv_data; | |
514 | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4079
diff
changeset
|
515 ff_lzw_decode_close(&s->lzw); |
4013 | 516 if(s->picture.data[0]) |
517 avctx->release_buffer(avctx, &s->picture); | |
518 return 0; | |
519 } | |
520 | |
521 AVCodec tiff_decoder = { | |
522 "tiff", | |
523 CODEC_TYPE_VIDEO, | |
524 CODEC_ID_TIFF, | |
525 sizeof(TiffContext), | |
526 tiff_init, | |
527 NULL, | |
528 tiff_end, | |
529 decode_frame, | |
530 0, | |
531 NULL | |
532 }; |