Mercurial > libavcodec.hg
annotate pngdec.c @ 7352:c2318e551ff5 libavcodec
When picking a "high utility centroid" do not pick one
that has no corresponding points. Not only it is the
worst possible pick, but also the code was written
without this case in mind.
author | vitor |
---|---|
date | Wed, 23 Jul 2008 03:55:37 +0000 |
parents | 6c1244ad5620 |
children | 04423b2f6e0b |
rev | line source |
---|---|
2342 | 1 /* |
2 * PNG image format | |
3 * Copyright (c) 2003 Fabrice Bellard. | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
2342 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
2342 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2342 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3777
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2342 | 20 */ |
21 #include "avcodec.h" | |
5067 | 22 #include "bytestream.h" |
5337 | 23 #include "png.h" |
6384 | 24 #include "dsputil.h" |
2342 | 25 |
26 /* TODO: | |
27 * - add 2, 4 and 16 bit depth support | |
28 */ | |
29 | |
30 #include <zlib.h> | |
31 | |
32 //#define DEBUG | |
33 | |
5339 | 34 typedef struct PNGDecContext { |
6384 | 35 DSPContext dsp; |
36 | |
6245 | 37 const uint8_t *bytestream; |
38 const uint8_t *bytestream_start; | |
39 const uint8_t *bytestream_end; | |
5339 | 40 AVFrame picture; |
41 | |
42 int state; | |
43 int width, height; | |
44 int bit_depth; | |
45 int color_type; | |
46 int compression_type; | |
47 int interlace_type; | |
48 int filter_type; | |
49 int channels; | |
50 int bits_per_pixel; | |
51 int bpp; | |
52 | |
53 uint8_t *image_buf; | |
54 int image_linesize; | |
55 uint32_t palette[256]; | |
56 uint8_t *crow_buf; | |
57 uint8_t *last_row; | |
58 uint8_t *tmp_row; | |
59 int pass; | |
60 int crow_size; /* compressed row size (include filter type) */ | |
61 int row_size; /* decompressed row size */ | |
62 int pass_row_size; /* decompress row size of the current pass */ | |
63 int y; | |
64 z_stream zstream; | |
65 } PNGDecContext; | |
66 | |
2342 | 67 /* Mask to determine which y pixels can be written in a pass */ |
68 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = { | |
69 0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55, | |
70 }; | |
71 | |
72 /* Mask to determine which pixels to overwrite while displaying */ | |
2967 | 73 static const uint8_t png_pass_dsp_mask[NB_PASSES] = { |
2342 | 74 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff |
75 }; | |
76 | |
77 /* NOTE: we try to construct a good looking image at each pass. width | |
5355 | 78 is the original image width. We also do pixel format conversion at |
2342 | 79 this stage */ |
2967 | 80 static void png_put_interlaced_row(uint8_t *dst, int width, |
81 int bits_per_pixel, int pass, | |
2342 | 82 int color_type, const uint8_t *src) |
83 { | |
84 int x, mask, dsp_mask, j, src_x, b, bpp; | |
85 uint8_t *d; | |
86 const uint8_t *s; | |
2967 | 87 |
5337 | 88 mask = ff_png_pass_mask[pass]; |
2342 | 89 dsp_mask = png_pass_dsp_mask[pass]; |
90 switch(bits_per_pixel) { | |
91 case 1: | |
5097 | 92 /* we must initialize the line to zero before writing to it */ |
2342 | 93 if (pass == 0) |
94 memset(dst, 0, (width + 7) >> 3); | |
95 src_x = 0; | |
96 for(x = 0; x < width; x++) { | |
97 j = (x & 7); | |
98 if ((dsp_mask << j) & 0x80) { | |
99 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1; | |
100 dst[x >> 3] |= b << (7 - j); | |
101 } | |
102 if ((mask << j) & 0x80) | |
103 src_x++; | |
104 } | |
105 break; | |
106 default: | |
107 bpp = bits_per_pixel >> 3; | |
108 d = dst; | |
109 s = src; | |
110 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
111 for(x = 0; x < width; x++) { | |
112 j = x & 7; | |
113 if ((dsp_mask << j) & 0x80) { | |
114 *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2]; | |
115 } | |
116 d += bpp; | |
117 if ((mask << j) & 0x80) | |
118 s += bpp; | |
119 } | |
120 } else { | |
121 for(x = 0; x < width; x++) { | |
122 j = x & 7; | |
123 if ((dsp_mask << j) & 0x80) { | |
124 memcpy(d, s, bpp); | |
125 } | |
126 d += bpp; | |
127 if ((mask << j) & 0x80) | |
128 s += bpp; | |
129 } | |
130 } | |
131 break; | |
132 } | |
133 } | |
134 | |
6384 | 135 void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) |
136 { | |
137 int i; | |
138 for(i = 0; i < w; i++) { | |
139 int a, b, c, p, pa, pb, pc; | |
140 | |
141 a = dst[i - bpp]; | |
142 b = top[i]; | |
143 c = top[i - bpp]; | |
144 | |
145 p = b - c; | |
146 pc = a - c; | |
147 | |
148 pa = abs(p); | |
149 pb = abs(pc); | |
150 pc = abs(p + pc); | |
151 | |
152 if (pa <= pb && pa <= pc) | |
153 p = a; | |
154 else if (pb <= pc) | |
155 p = b; | |
156 else | |
157 p = c; | |
158 dst[i] = p + src[i]; | |
159 } | |
160 } | |
161 | |
162 #define UNROLL1(bpp, op) {\ | |
163 r = dst[0];\ | |
164 if(bpp >= 2) g = dst[1];\ | |
165 if(bpp >= 3) b = dst[2];\ | |
166 if(bpp >= 4) a = dst[3];\ | |
167 for(; i < size; i+=bpp) {\ | |
168 dst[i+0] = r = op(r, src[i+0], last[i+0]);\ | |
169 if(bpp == 1) continue;\ | |
170 dst[i+1] = g = op(g, src[i+1], last[i+1]);\ | |
171 if(bpp == 2) continue;\ | |
172 dst[i+2] = b = op(b, src[i+2], last[i+2]);\ | |
173 if(bpp == 3) continue;\ | |
174 dst[i+3] = a = op(a, src[i+3], last[i+3]);\ | |
175 }\ | |
176 } | |
177 | |
178 #define UNROLL_FILTER(op)\ | |
179 if(bpp == 1) UNROLL1(1, op)\ | |
180 else if(bpp == 2) UNROLL1(2, op)\ | |
181 else if(bpp == 3) UNROLL1(3, op)\ | |
182 else if(bpp == 4) UNROLL1(4, op)\ | |
183 | |
2342 | 184 /* NOTE: 'dst' can be equal to 'last' */ |
6384 | 185 static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type, |
2342 | 186 uint8_t *src, uint8_t *last, int size, int bpp) |
187 { | |
6384 | 188 int i, p, r, g, b, a; |
2342 | 189 |
190 switch(filter_type) { | |
191 case PNG_FILTER_VALUE_NONE: | |
192 memcpy(dst, src, size); | |
193 break; | |
194 case PNG_FILTER_VALUE_SUB: | |
195 for(i = 0; i < bpp; i++) { | |
196 dst[i] = src[i]; | |
197 } | |
6384 | 198 if(bpp == 4) { |
199 p = *(int*)dst; | |
200 for(; i < size; i+=bpp) { | |
201 int s = *(int*)(src+i); | |
202 p = ((s&0x7f7f7f7f) + (p&0x7f7f7f7f)) ^ ((s^p)&0x80808080); | |
203 *(int*)(dst+i) = p; | |
204 } | |
205 } else { | |
206 #define OP_SUB(x,s,l) x+s | |
207 UNROLL_FILTER(OP_SUB); | |
2342 | 208 } |
209 break; | |
210 case PNG_FILTER_VALUE_UP: | |
6384 | 211 dsp->add_bytes_l2(dst, src, last, size); |
2342 | 212 break; |
213 case PNG_FILTER_VALUE_AVG: | |
214 for(i = 0; i < bpp; i++) { | |
215 p = (last[i] >> 1); | |
216 dst[i] = p + src[i]; | |
217 } | |
6384 | 218 #define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff |
219 UNROLL_FILTER(OP_AVG); | |
2342 | 220 break; |
221 case PNG_FILTER_VALUE_PAETH: | |
222 for(i = 0; i < bpp; i++) { | |
223 p = last[i]; | |
224 dst[i] = p + src[i]; | |
225 } | |
6384 | 226 if(bpp > 1 && size > 4) { |
227 // would write off the end of the array if we let it process the last pixel with bpp=3 | |
228 int w = bpp==4 ? size : size-3; | |
229 dsp->add_png_paeth_prediction(dst+i, src+i, last+i, w-i, bpp); | |
230 i = w; | |
2342 | 231 } |
6384 | 232 ff_add_png_paeth_prediction(dst+i, src+i, last+i, size-i, bpp); |
2342 | 233 break; |
234 } | |
235 } | |
236 | |
6406 | 237 static av_always_inline void convert_to_rgb32_loco(uint8_t *dst, const uint8_t *src, int width, int loco) |
2342 | 238 { |
239 int j; | |
240 unsigned int r, g, b, a; | |
241 | |
242 for(j = 0;j < width; j++) { | |
243 r = src[0]; | |
244 g = src[1]; | |
245 b = src[2]; | |
246 a = src[3]; | |
6406 | 247 if(loco) { |
248 r = (r+g)&0xff; | |
249 b = (b+g)&0xff; | |
250 } | |
2342 | 251 *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b; |
252 dst += 4; | |
253 src += 4; | |
254 } | |
255 } | |
256 | |
6406 | 257 static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width, int loco) |
258 { | |
259 if(loco) | |
260 convert_to_rgb32_loco(dst, src, width, 1); | |
261 else | |
262 convert_to_rgb32_loco(dst, src, width, 0); | |
263 } | |
264 | |
265 static void deloco_rgb24(uint8_t *dst, int size) | |
266 { | |
267 int i; | |
268 for(i=0; i<size; i+=3) { | |
269 int g = dst[i+1]; | |
270 dst[i+0] += g; | |
271 dst[i+2] += g; | |
272 } | |
273 } | |
274 | |
2342 | 275 /* process exactly one decompressed row */ |
5339 | 276 static void png_handle_row(PNGDecContext *s) |
2342 | 277 { |
278 uint8_t *ptr, *last_row; | |
279 int got_line; | |
2967 | 280 |
2342 | 281 if (!s->interlace_type) { |
282 ptr = s->image_buf + s->image_linesize * s->y; | |
283 /* need to swap bytes correctly for RGB_ALPHA */ | |
284 if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
6384 | 285 png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, |
2342 | 286 s->last_row, s->row_size, s->bpp); |
6406 | 287 convert_to_rgb32(ptr, s->tmp_row, s->width, s->filter_type == PNG_FILTER_TYPE_LOCO); |
6394 | 288 FFSWAP(uint8_t*, s->last_row, s->tmp_row); |
2342 | 289 } else { |
290 /* in normal case, we avoid one copy */ | |
291 if (s->y == 0) | |
292 last_row = s->last_row; | |
293 else | |
294 last_row = ptr - s->image_linesize; | |
2967 | 295 |
6384 | 296 png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, |
2342 | 297 last_row, s->row_size, s->bpp); |
298 } | |
6406 | 299 /* loco lags by 1 row so that it doesn't interfere with top prediction */ |
300 if (s->filter_type == PNG_FILTER_TYPE_LOCO && | |
301 s->color_type == PNG_COLOR_TYPE_RGB && s->y > 0) | |
302 deloco_rgb24(ptr - s->image_linesize, s->row_size); | |
2342 | 303 s->y++; |
304 if (s->y == s->height) { | |
305 s->state |= PNG_ALLIMAGE; | |
6406 | 306 if (s->filter_type == PNG_FILTER_TYPE_LOCO && |
307 s->color_type == PNG_COLOR_TYPE_RGB) | |
308 deloco_rgb24(ptr, s->row_size); | |
2342 | 309 } |
310 } else { | |
311 got_line = 0; | |
312 for(;;) { | |
313 ptr = s->image_buf + s->image_linesize * s->y; | |
5337 | 314 if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) { |
2342 | 315 /* if we already read one row, it is time to stop to |
316 wait for the next one */ | |
317 if (got_line) | |
318 break; | |
6384 | 319 png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, |
2342 | 320 s->last_row, s->pass_row_size, s->bpp); |
6394 | 321 FFSWAP(uint8_t*, s->last_row, s->tmp_row); |
2342 | 322 got_line = 1; |
323 } | |
324 if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) { | |
4515 | 325 /* NOTE: RGB32 is handled directly in png_put_interlaced_row */ |
2967 | 326 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass, |
2342 | 327 s->color_type, s->last_row); |
328 } | |
329 s->y++; | |
330 if (s->y == s->height) { | |
331 for(;;) { | |
332 if (s->pass == NB_PASSES - 1) { | |
333 s->state |= PNG_ALLIMAGE; | |
334 goto the_end; | |
335 } else { | |
336 s->pass++; | |
337 s->y = 0; | |
5337 | 338 s->pass_row_size = ff_png_pass_row_size(s->pass, |
2967 | 339 s->bits_per_pixel, |
2342 | 340 s->width); |
341 s->crow_size = s->pass_row_size + 1; | |
342 if (s->pass_row_size != 0) | |
343 break; | |
344 /* skip pass if empty row */ | |
345 } | |
346 } | |
347 } | |
348 } | |
349 the_end: ; | |
350 } | |
351 } | |
352 | |
5339 | 353 static int png_decode_idat(PNGDecContext *s, int length) |
2342 | 354 { |
355 int ret; | |
356 s->zstream.avail_in = length; | |
357 s->zstream.next_in = s->bytestream; | |
358 s->bytestream += length; | |
2967 | 359 |
2342 | 360 if(s->bytestream > s->bytestream_end) |
361 return -1; | |
362 | |
363 /* decode one line if possible */ | |
364 while (s->zstream.avail_in > 0) { | |
365 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); | |
366 if (ret != Z_OK && ret != Z_STREAM_END) { | |
367 return -1; | |
368 } | |
369 if (s->zstream.avail_out == 0) { | |
370 if (!(s->state & PNG_ALLIMAGE)) { | |
371 png_handle_row(s); | |
372 } | |
373 s->zstream.avail_out = s->crow_size; | |
374 s->zstream.next_out = s->crow_buf; | |
375 } | |
376 } | |
377 return 0; | |
378 } | |
379 | |
2967 | 380 static int decode_frame(AVCodecContext *avctx, |
2342 | 381 void *data, int *data_size, |
6245 | 382 const uint8_t *buf, int buf_size) |
2342 | 383 { |
5339 | 384 PNGDecContext * const s = avctx->priv_data; |
2342 | 385 AVFrame *picture = data; |
7236 | 386 AVFrame * const p= &s->picture; |
2342 | 387 uint32_t tag, length; |
388 int ret, crc; | |
389 | |
390 s->bytestream_start= | |
391 s->bytestream= buf; | |
392 s->bytestream_end= buf + buf_size; | |
393 | |
394 /* check signature */ | |
6406 | 395 if (memcmp(s->bytestream, ff_pngsig, 8) != 0 && |
396 memcmp(s->bytestream, ff_mngsig, 8) != 0) | |
2342 | 397 return -1; |
398 s->bytestream+= 8; | |
399 s->y= | |
400 s->state=0; | |
5339 | 401 // memset(s, 0, sizeof(PNGDecContext)); |
2342 | 402 /* init the zlib */ |
5337 | 403 s->zstream.zalloc = ff_png_zalloc; |
404 s->zstream.zfree = ff_png_zfree; | |
2342 | 405 s->zstream.opaque = NULL; |
406 ret = inflateInit(&s->zstream); | |
407 if (ret != Z_OK) | |
408 return -1; | |
409 for(;;) { | |
2347
c6280d48be02
When bswap_32 is a macro, png images fail to decode properly, patch by (Milan Cutka <cutka>at<szm>dot<sk>)
michael
parents:
2342
diff
changeset
|
410 int tag32; |
2342 | 411 if (s->bytestream >= s->bytestream_end) |
412 goto fail; | |
5067 | 413 length = bytestream_get_be32(&s->bytestream); |
2342 | 414 if (length > 0x7fffffff) |
415 goto fail; | |
5067 | 416 tag32 = bytestream_get_be32(&s->bytestream); |
2347
c6280d48be02
When bswap_32 is a macro, png images fail to decode properly, patch by (Milan Cutka <cutka>at<szm>dot<sk>)
michael
parents:
2342
diff
changeset
|
417 tag = bswap_32(tag32); |
2342 | 418 #ifdef DEBUG |
3177 | 419 av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n", |
2342 | 420 (tag & 0xff), |
421 ((tag >> 8) & 0xff), | |
422 ((tag >> 16) & 0xff), | |
423 ((tag >> 24) & 0xff), length); | |
424 #endif | |
425 switch(tag) { | |
426 case MKTAG('I', 'H', 'D', 'R'): | |
427 if (length != 13) | |
428 goto fail; | |
5067 | 429 s->width = bytestream_get_be32(&s->bytestream); |
430 s->height = bytestream_get_be32(&s->bytestream); | |
2422 | 431 if(avcodec_check_dimensions(avctx, s->width, s->height)){ |
432 s->width= s->height= 0; | |
433 goto fail; | |
434 } | |
2342 | 435 s->bit_depth = *s->bytestream++; |
436 s->color_type = *s->bytestream++; | |
437 s->compression_type = *s->bytestream++; | |
438 s->filter_type = *s->bytestream++; | |
439 s->interlace_type = *s->bytestream++; | |
5067 | 440 crc = bytestream_get_be32(&s->bytestream); |
2342 | 441 s->state |= PNG_IHDR; |
442 #ifdef DEBUG | |
3177 | 443 av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n", |
2967 | 444 s->width, s->height, s->bit_depth, s->color_type, |
2342 | 445 s->compression_type, s->filter_type, s->interlace_type); |
446 #endif | |
447 break; | |
448 case MKTAG('I', 'D', 'A', 'T'): | |
449 if (!(s->state & PNG_IHDR)) | |
450 goto fail; | |
451 if (!(s->state & PNG_IDAT)) { | |
452 /* init image info */ | |
453 avctx->width = s->width; | |
454 avctx->height = s->height; | |
455 | |
5337 | 456 s->channels = ff_png_get_nb_channels(s->color_type); |
2342 | 457 s->bits_per_pixel = s->bit_depth * s->channels; |
458 s->bpp = (s->bits_per_pixel + 7) >> 3; | |
459 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3; | |
460 | |
2967 | 461 if (s->bit_depth == 8 && |
2342 | 462 s->color_type == PNG_COLOR_TYPE_RGB) { |
463 avctx->pix_fmt = PIX_FMT_RGB24; | |
2967 | 464 } else if (s->bit_depth == 8 && |
2342 | 465 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { |
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4379
diff
changeset
|
466 avctx->pix_fmt = PIX_FMT_RGB32; |
2967 | 467 } else if (s->bit_depth == 8 && |
2342 | 468 s->color_type == PNG_COLOR_TYPE_GRAY) { |
469 avctx->pix_fmt = PIX_FMT_GRAY8; | |
4067 | 470 } else if (s->bit_depth == 16 && |
471 s->color_type == PNG_COLOR_TYPE_GRAY) { | |
472 avctx->pix_fmt = PIX_FMT_GRAY16BE; | |
2967 | 473 } else if (s->bit_depth == 1 && |
2342 | 474 s->color_type == PNG_COLOR_TYPE_GRAY) { |
475 avctx->pix_fmt = PIX_FMT_MONOBLACK; | |
476 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) { | |
477 avctx->pix_fmt = PIX_FMT_PAL8; | |
478 } else { | |
479 goto fail; | |
480 } | |
481 if(p->data[0]) | |
482 avctx->release_buffer(avctx, p); | |
2967 | 483 |
2342 | 484 p->reference= 0; |
485 if(avctx->get_buffer(avctx, p) < 0){ | |
486 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
487 goto fail; | |
488 } | |
489 p->pict_type= FF_I_TYPE; | |
490 p->key_frame= 1; | |
491 p->interlaced_frame = !!s->interlace_type; | |
492 | |
493 /* compute the compressed row size */ | |
494 if (!s->interlace_type) { | |
495 s->crow_size = s->row_size + 1; | |
496 } else { | |
497 s->pass = 0; | |
5337 | 498 s->pass_row_size = ff_png_pass_row_size(s->pass, |
2967 | 499 s->bits_per_pixel, |
2342 | 500 s->width); |
501 s->crow_size = s->pass_row_size + 1; | |
502 } | |
503 #ifdef DEBUG | |
3177 | 504 av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n", |
2342 | 505 s->row_size, s->crow_size); |
506 #endif | |
507 s->image_buf = p->data[0]; | |
508 s->image_linesize = p->linesize[0]; | |
509 /* copy the palette if needed */ | |
510 if (s->color_type == PNG_COLOR_TYPE_PALETTE) | |
511 memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t)); | |
512 /* empty row is used if differencing to the first row */ | |
513 s->last_row = av_mallocz(s->row_size); | |
514 if (!s->last_row) | |
515 goto fail; | |
516 if (s->interlace_type || | |
517 s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { | |
518 s->tmp_row = av_malloc(s->row_size); | |
519 if (!s->tmp_row) | |
520 goto fail; | |
521 } | |
522 /* compressed row */ | |
523 s->crow_buf = av_malloc(s->row_size + 1); | |
524 if (!s->crow_buf) | |
525 goto fail; | |
526 s->zstream.avail_out = s->crow_size; | |
527 s->zstream.next_out = s->crow_buf; | |
528 } | |
529 s->state |= PNG_IDAT; | |
530 if (png_decode_idat(s, length) < 0) | |
531 goto fail; | |
532 /* skip crc */ | |
5067 | 533 crc = bytestream_get_be32(&s->bytestream); |
2342 | 534 break; |
535 case MKTAG('P', 'L', 'T', 'E'): | |
536 { | |
537 int n, i, r, g, b; | |
2967 | 538 |
2342 | 539 if ((length % 3) != 0 || length > 256 * 3) |
540 goto skip_tag; | |
541 /* read the palette */ | |
542 n = length / 3; | |
543 for(i=0;i<n;i++) { | |
544 r = *s->bytestream++; | |
545 g = *s->bytestream++; | |
546 b = *s->bytestream++; | |
547 s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b; | |
548 } | |
549 for(;i<256;i++) { | |
550 s->palette[i] = (0xff << 24); | |
551 } | |
552 s->state |= PNG_PLTE; | |
5067 | 553 crc = bytestream_get_be32(&s->bytestream); |
2342 | 554 } |
555 break; | |
556 case MKTAG('t', 'R', 'N', 'S'): | |
557 { | |
558 int v, i; | |
559 | |
560 /* read the transparency. XXX: Only palette mode supported */ | |
561 if (s->color_type != PNG_COLOR_TYPE_PALETTE || | |
562 length > 256 || | |
563 !(s->state & PNG_PLTE)) | |
564 goto skip_tag; | |
565 for(i=0;i<length;i++) { | |
566 v = *s->bytestream++; | |
567 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); | |
568 } | |
5067 | 569 crc = bytestream_get_be32(&s->bytestream); |
2342 | 570 } |
571 break; | |
572 case MKTAG('I', 'E', 'N', 'D'): | |
573 if (!(s->state & PNG_ALLIMAGE)) | |
574 goto fail; | |
5067 | 575 crc = bytestream_get_be32(&s->bytestream); |
2342 | 576 goto exit_loop; |
577 default: | |
578 /* skip tag */ | |
579 skip_tag: | |
580 s->bytestream += length + 4; | |
581 break; | |
582 } | |
583 } | |
584 exit_loop: | |
7236 | 585 *picture= s->picture; |
586 *data_size = sizeof(AVFrame); | |
2342 | 587 |
588 ret = s->bytestream - s->bytestream_start; | |
589 the_end: | |
590 inflateEnd(&s->zstream); | |
591 av_freep(&s->crow_buf); | |
592 av_freep(&s->last_row); | |
593 av_freep(&s->tmp_row); | |
594 return ret; | |
595 fail: | |
596 ret = -1; | |
597 goto the_end; | |
598 } | |
599 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6406
diff
changeset
|
600 static av_cold int png_dec_init(AVCodecContext *avctx){ |
5339 | 601 PNGDecContext *s = avctx->priv_data; |
602 | |
7236 | 603 avcodec_get_frame_defaults(&s->picture); |
604 avctx->coded_frame= &s->picture; | |
6384 | 605 dsputil_init(&s->dsp, avctx); |
5339 | 606 |
607 return 0; | |
608 } | |
609 | |
2342 | 610 AVCodec png_decoder = { |
611 "png", | |
612 CODEC_TYPE_VIDEO, | |
613 CODEC_ID_PNG, | |
5339 | 614 sizeof(PNGDecContext), |
615 png_dec_init, | |
2342 | 616 NULL, |
617 NULL, //decode_end, | |
618 decode_frame, | |
619 0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/, | |
6722 | 620 NULL, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6722
diff
changeset
|
621 .long_name = NULL_IF_CONFIG_SMALL("PNG image"), |
2342 | 622 }; |