Statistics
| Branch: | Revision:

ffmpeg / libavcodec / pngdec.c @ b958a7f1

History | View | Annotate | Download (16.7 KB)

1
/*
2
 * PNG image format
3
 * Copyright (c) 2003 Fabrice Bellard.
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
#include "avcodec.h"
22
#include "bytestream.h"
23
#include "png.h"
24

    
25
/* TODO:
26
 * - add 2, 4 and 16 bit depth support
27
 */
28

    
29
#include <zlib.h>
30

    
31
//#define DEBUG
32

    
33
/* Mask to determine which y pixels can be written in a pass */
34
static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
35
    0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
36
};
37

    
38
/* Mask to determine which pixels to overwrite while displaying */
39
static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
40
    0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
41
};
42

    
43
/* NOTE: we try to construct a good looking image at each pass. width
44
   is the original image width. We also do pixel format convertion at
45
   this stage */
46
static void png_put_interlaced_row(uint8_t *dst, int width,
47
                                   int bits_per_pixel, int pass,
48
                                   int color_type, const uint8_t *src)
49
{
50
    int x, mask, dsp_mask, j, src_x, b, bpp;
51
    uint8_t *d;
52
    const uint8_t *s;
53

    
54
    mask = ff_png_pass_mask[pass];
55
    dsp_mask = png_pass_dsp_mask[pass];
56
    switch(bits_per_pixel) {
57
    case 1:
58
        /* we must initialize the line to zero before writing to it */
59
        if (pass == 0)
60
            memset(dst, 0, (width + 7) >> 3);
61
        src_x = 0;
62
        for(x = 0; x < width; x++) {
63
            j = (x & 7);
64
            if ((dsp_mask << j) & 0x80) {
65
                b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
66
                dst[x >> 3] |= b << (7 - j);
67
            }
68
            if ((mask << j) & 0x80)
69
                src_x++;
70
        }
71
        break;
72
    default:
73
        bpp = bits_per_pixel >> 3;
74
        d = dst;
75
        s = src;
76
        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
77
            for(x = 0; x < width; x++) {
78
                j = x & 7;
79
                if ((dsp_mask << j) & 0x80) {
80
                    *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
81
                }
82
                d += bpp;
83
                if ((mask << j) & 0x80)
84
                    s += bpp;
85
            }
86
        } else {
87
            for(x = 0; x < width; x++) {
88
                j = x & 7;
89
                if ((dsp_mask << j) & 0x80) {
90
                    memcpy(d, s, bpp);
91
                }
92
                d += bpp;
93
                if ((mask << j) & 0x80)
94
                    s += bpp;
95
            }
96
        }
97
        break;
98
    }
99
}
100

    
101
/* XXX: optimize */
102
/* NOTE: 'dst' can be equal to 'last' */
103
static void png_filter_row(uint8_t *dst, int filter_type,
104
                           uint8_t *src, uint8_t *last, int size, int bpp)
105
{
106
    int i, p;
107

    
108
    switch(filter_type) {
109
    case PNG_FILTER_VALUE_NONE:
110
        memcpy(dst, src, size);
111
        break;
112
    case PNG_FILTER_VALUE_SUB:
113
        for(i = 0; i < bpp; i++) {
114
            dst[i] = src[i];
115
        }
116
        for(i = bpp; i < size; i++) {
117
            p = dst[i - bpp];
118
            dst[i] = p + src[i];
119
        }
120
        break;
121
    case PNG_FILTER_VALUE_UP:
122
        for(i = 0; i < size; i++) {
123
            p = last[i];
124
            dst[i] = p + src[i];
125
        }
126
        break;
127
    case PNG_FILTER_VALUE_AVG:
128
        for(i = 0; i < bpp; i++) {
129
            p = (last[i] >> 1);
130
            dst[i] = p + src[i];
131
        }
132
        for(i = bpp; i < size; i++) {
133
            p = ((dst[i - bpp] + last[i]) >> 1);
134
            dst[i] = p + src[i];
135
        }
136
        break;
137
    case PNG_FILTER_VALUE_PAETH:
138
        for(i = 0; i < bpp; i++) {
139
            p = last[i];
140
            dst[i] = p + src[i];
141
        }
142
        for(i = bpp; i < size; i++) {
143
            int a, b, c, pa, pb, pc;
144

    
145
            a = dst[i - bpp];
146
            b = last[i];
147
            c = last[i - bpp];
148

    
149
            p = b - c;
150
            pc = a - c;
151

    
152
            pa = abs(p);
153
            pb = abs(pc);
154
            pc = abs(p + pc);
155

    
156
            if (pa <= pb && pa <= pc)
157
                p = a;
158
            else if (pb <= pc)
159
                p = b;
160
            else
161
                p = c;
162
            dst[i] = p + src[i];
163
        }
164
        break;
165
    }
166
}
167

    
168
static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width)
169
{
170
    int j;
171
    unsigned int r, g, b, a;
172

    
173
    for(j = 0;j < width; j++) {
174
        r = src[0];
175
        g = src[1];
176
        b = src[2];
177
        a = src[3];
178
        *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
179
        dst += 4;
180
        src += 4;
181
    }
182
}
183

    
184
/* process exactly one decompressed row */
185
static void png_handle_row(PNGContext *s)
186
{
187
    uint8_t *ptr, *last_row;
188
    int got_line;
189

    
190
    if (!s->interlace_type) {
191
        ptr = s->image_buf + s->image_linesize * s->y;
192
        /* need to swap bytes correctly for RGB_ALPHA */
193
        if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
194
            png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
195
                           s->last_row, s->row_size, s->bpp);
196
            memcpy(s->last_row, s->tmp_row, s->row_size);
197
            convert_to_rgb32(ptr, s->tmp_row, s->width);
198
        } else {
199
            /* in normal case, we avoid one copy */
200
            if (s->y == 0)
201
                last_row = s->last_row;
202
            else
203
                last_row = ptr - s->image_linesize;
204

    
205
            png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
206
                           last_row, s->row_size, s->bpp);
207
        }
208
        s->y++;
209
        if (s->y == s->height) {
210
            s->state |= PNG_ALLIMAGE;
211
        }
212
    } else {
213
        got_line = 0;
214
        for(;;) {
215
            ptr = s->image_buf + s->image_linesize * s->y;
216
            if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
217
                /* if we already read one row, it is time to stop to
218
                   wait for the next one */
219
                if (got_line)
220
                    break;
221
                png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
222
                               s->last_row, s->pass_row_size, s->bpp);
223
                memcpy(s->last_row, s->tmp_row, s->pass_row_size);
224
                got_line = 1;
225
            }
226
            if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
227
                /* NOTE: RGB32 is handled directly in png_put_interlaced_row */
228
                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
229
                                       s->color_type, s->last_row);
230
            }
231
            s->y++;
232
            if (s->y == s->height) {
233
                for(;;) {
234
                    if (s->pass == NB_PASSES - 1) {
235
                        s->state |= PNG_ALLIMAGE;
236
                        goto the_end;
237
                    } else {
238
                        s->pass++;
239
                        s->y = 0;
240
                        s->pass_row_size = ff_png_pass_row_size(s->pass,
241
                                                             s->bits_per_pixel,
242
                                                             s->width);
243
                        s->crow_size = s->pass_row_size + 1;
244
                        if (s->pass_row_size != 0)
245
                            break;
246
                        /* skip pass if empty row */
247
                    }
248
                }
249
            }
250
        }
251
    the_end: ;
252
    }
253
}
254

    
255
static int png_decode_idat(PNGContext *s, int length)
256
{
257
    int ret;
258
    s->zstream.avail_in = length;
259
    s->zstream.next_in = s->bytestream;
260
    s->bytestream += length;
261

    
262
    if(s->bytestream > s->bytestream_end)
263
        return -1;
264

    
265
    /* decode one line if possible */
266
    while (s->zstream.avail_in > 0) {
267
        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
268
        if (ret != Z_OK && ret != Z_STREAM_END) {
269
            return -1;
270
        }
271
        if (s->zstream.avail_out == 0) {
272
            if (!(s->state & PNG_ALLIMAGE)) {
273
                png_handle_row(s);
274
            }
275
            s->zstream.avail_out = s->crow_size;
276
            s->zstream.next_out = s->crow_buf;
277
        }
278
    }
279
    return 0;
280
}
281

    
282
static int decode_frame(AVCodecContext *avctx,
283
                        void *data, int *data_size,
284
                        uint8_t *buf, int buf_size)
285
{
286
    PNGContext * const s = avctx->priv_data;
287
    AVFrame *picture = data;
288
    AVFrame * const p= (AVFrame*)&s->picture;
289
    uint32_t tag, length;
290
    int ret, crc;
291

    
292
    s->bytestream_start=
293
    s->bytestream= buf;
294
    s->bytestream_end= buf + buf_size;
295

    
296
    /* check signature */
297
    if (memcmp(s->bytestream, ff_pngsig, 8) != 0)
298
        return -1;
299
    s->bytestream+= 8;
300
    s->y=
301
    s->state=0;
302
//    memset(s, 0, sizeof(PNGContext));
303
    /* init the zlib */
304
    s->zstream.zalloc = ff_png_zalloc;
305
    s->zstream.zfree = ff_png_zfree;
306
    s->zstream.opaque = NULL;
307
    ret = inflateInit(&s->zstream);
308
    if (ret != Z_OK)
309
        return -1;
310
    for(;;) {
311
        int tag32;
312
        if (s->bytestream >= s->bytestream_end)
313
            goto fail;
314
        length = bytestream_get_be32(&s->bytestream);
315
        if (length > 0x7fffffff)
316
            goto fail;
317
        tag32 = bytestream_get_be32(&s->bytestream);
318
        tag = bswap_32(tag32);
319
#ifdef DEBUG
320
        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
321
               (tag & 0xff),
322
               ((tag >> 8) & 0xff),
323
               ((tag >> 16) & 0xff),
324
               ((tag >> 24) & 0xff), length);
325
#endif
326
        switch(tag) {
327
        case MKTAG('I', 'H', 'D', 'R'):
328
            if (length != 13)
329
                goto fail;
330
            s->width = bytestream_get_be32(&s->bytestream);
331
            s->height = bytestream_get_be32(&s->bytestream);
332
            if(avcodec_check_dimensions(avctx, s->width, s->height)){
333
                s->width= s->height= 0;
334
                goto fail;
335
            }
336
            s->bit_depth = *s->bytestream++;
337
            s->color_type = *s->bytestream++;
338
            s->compression_type = *s->bytestream++;
339
            s->filter_type = *s->bytestream++;
340
            s->interlace_type = *s->bytestream++;
341
            crc = bytestream_get_be32(&s->bytestream);
342
            s->state |= PNG_IHDR;
343
#ifdef DEBUG
344
            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",
345
                   s->width, s->height, s->bit_depth, s->color_type,
346
                   s->compression_type, s->filter_type, s->interlace_type);
347
#endif
348
            break;
349
        case MKTAG('I', 'D', 'A', 'T'):
350
            if (!(s->state & PNG_IHDR))
351
                goto fail;
352
            if (!(s->state & PNG_IDAT)) {
353
                /* init image info */
354
                avctx->width = s->width;
355
                avctx->height = s->height;
356

    
357
                s->channels = ff_png_get_nb_channels(s->color_type);
358
                s->bits_per_pixel = s->bit_depth * s->channels;
359
                s->bpp = (s->bits_per_pixel + 7) >> 3;
360
                s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
361

    
362
                if (s->bit_depth == 8 &&
363
                    s->color_type == PNG_COLOR_TYPE_RGB) {
364
                    avctx->pix_fmt = PIX_FMT_RGB24;
365
                } else if (s->bit_depth == 8 &&
366
                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
367
                    avctx->pix_fmt = PIX_FMT_RGB32;
368
                } else if (s->bit_depth == 8 &&
369
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
370
                    avctx->pix_fmt = PIX_FMT_GRAY8;
371
                } else if (s->bit_depth == 16 &&
372
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
373
                    avctx->pix_fmt = PIX_FMT_GRAY16BE;
374
                } else if (s->bit_depth == 1 &&
375
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
376
                    avctx->pix_fmt = PIX_FMT_MONOBLACK;
377
                } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
378
                    avctx->pix_fmt = PIX_FMT_PAL8;
379
                } else {
380
                    goto fail;
381
                }
382
                if(p->data[0])
383
                    avctx->release_buffer(avctx, p);
384

    
385
                p->reference= 0;
386
                if(avctx->get_buffer(avctx, p) < 0){
387
                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
388
                    goto fail;
389
                }
390
                p->pict_type= FF_I_TYPE;
391
                p->key_frame= 1;
392
                p->interlaced_frame = !!s->interlace_type;
393

    
394
                /* compute the compressed row size */
395
                if (!s->interlace_type) {
396
                    s->crow_size = s->row_size + 1;
397
                } else {
398
                    s->pass = 0;
399
                    s->pass_row_size = ff_png_pass_row_size(s->pass,
400
                                                         s->bits_per_pixel,
401
                                                         s->width);
402
                    s->crow_size = s->pass_row_size + 1;
403
                }
404
#ifdef DEBUG
405
                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
406
                       s->row_size, s->crow_size);
407
#endif
408
                s->image_buf = p->data[0];
409
                s->image_linesize = p->linesize[0];
410
                /* copy the palette if needed */
411
                if (s->color_type == PNG_COLOR_TYPE_PALETTE)
412
                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
413
                /* empty row is used if differencing to the first row */
414
                s->last_row = av_mallocz(s->row_size);
415
                if (!s->last_row)
416
                    goto fail;
417
                if (s->interlace_type ||
418
                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
419
                    s->tmp_row = av_malloc(s->row_size);
420
                    if (!s->tmp_row)
421
                        goto fail;
422
                }
423
                /* compressed row */
424
                s->crow_buf = av_malloc(s->row_size + 1);
425
                if (!s->crow_buf)
426
                    goto fail;
427
                s->zstream.avail_out = s->crow_size;
428
                s->zstream.next_out = s->crow_buf;
429
            }
430
            s->state |= PNG_IDAT;
431
            if (png_decode_idat(s, length) < 0)
432
                goto fail;
433
            /* skip crc */
434
            crc = bytestream_get_be32(&s->bytestream);
435
            break;
436
        case MKTAG('P', 'L', 'T', 'E'):
437
            {
438
                int n, i, r, g, b;
439

    
440
                if ((length % 3) != 0 || length > 256 * 3)
441
                    goto skip_tag;
442
                /* read the palette */
443
                n = length / 3;
444
                for(i=0;i<n;i++) {
445
                    r = *s->bytestream++;
446
                    g = *s->bytestream++;
447
                    b = *s->bytestream++;
448
                    s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
449
                }
450
                for(;i<256;i++) {
451
                    s->palette[i] = (0xff << 24);
452
                }
453
                s->state |= PNG_PLTE;
454
                crc = bytestream_get_be32(&s->bytestream);
455
            }
456
            break;
457
        case MKTAG('t', 'R', 'N', 'S'):
458
            {
459
                int v, i;
460

    
461
                /* read the transparency. XXX: Only palette mode supported */
462
                if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
463
                    length > 256 ||
464
                    !(s->state & PNG_PLTE))
465
                    goto skip_tag;
466
                for(i=0;i<length;i++) {
467
                    v = *s->bytestream++;
468
                    s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
469
                }
470
                crc = bytestream_get_be32(&s->bytestream);
471
            }
472
            break;
473
        case MKTAG('I', 'E', 'N', 'D'):
474
            if (!(s->state & PNG_ALLIMAGE))
475
                goto fail;
476
            crc = bytestream_get_be32(&s->bytestream);
477
            goto exit_loop;
478
        default:
479
            /* skip tag */
480
        skip_tag:
481
            s->bytestream += length + 4;
482
            break;
483
        }
484
    }
485
 exit_loop:
486
    *picture= *(AVFrame*)&s->picture;
487
    *data_size = sizeof(AVPicture);
488

    
489
    ret = s->bytestream - s->bytestream_start;
490
 the_end:
491
    inflateEnd(&s->zstream);
492
    av_freep(&s->crow_buf);
493
    av_freep(&s->last_row);
494
    av_freep(&s->tmp_row);
495
    return ret;
496
 fail:
497
    ret = -1;
498
    goto the_end;
499
}
500

    
501
AVCodec png_decoder = {
502
    "png",
503
    CODEC_TYPE_VIDEO,
504
    CODEC_ID_PNG,
505
    sizeof(PNGContext),
506
    ff_png_common_init,
507
    NULL,
508
    NULL, //decode_end,
509
    decode_frame,
510
    0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
511
    NULL
512
};