Statistics
| Branch: | Revision:

ffmpeg / libavcodec / png.c @ 71e445fc

History | View | Annotate | Download (28.8 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

    
23
/* TODO:
24
 * - add 2, 4 and 16 bit depth support
25
 * - use filters when generating a png (better compression)
26
 */
27

    
28
#include <zlib.h>
29

    
30
//#define DEBUG
31

    
32
#define PNG_COLOR_MASK_PALETTE    1
33
#define PNG_COLOR_MASK_COLOR      2
34
#define PNG_COLOR_MASK_ALPHA      4
35

    
36
#define PNG_COLOR_TYPE_GRAY 0
37
#define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
38
#define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
39
#define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
40
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
41

    
42
#define PNG_FILTER_VALUE_NONE  0
43
#define PNG_FILTER_VALUE_SUB   1
44
#define PNG_FILTER_VALUE_UP    2
45
#define PNG_FILTER_VALUE_AVG   3
46
#define PNG_FILTER_VALUE_PAETH 4
47

    
48
#define PNG_IHDR      0x0001
49
#define PNG_IDAT      0x0002
50
#define PNG_ALLIMAGE  0x0004
51
#define PNG_PLTE      0x0008
52

    
53
#define NB_PASSES 7
54

    
55
#define IOBUF_SIZE 4096
56

    
57
typedef struct PNGContext {
58
    uint8_t *bytestream;
59
    uint8_t *bytestream_start;
60
    uint8_t *bytestream_end;
61
    AVFrame picture;
62

    
63
    int state;
64
    int width, height;
65
    int bit_depth;
66
    int color_type;
67
    int compression_type;
68
    int interlace_type;
69
    int filter_type;
70
    int channels;
71
    int bits_per_pixel;
72
    int bpp;
73

    
74
    uint8_t *image_buf;
75
    int image_linesize;
76
    uint32_t palette[256];
77
    uint8_t *crow_buf;
78
    uint8_t *last_row;
79
    uint8_t *tmp_row;
80
    int pass;
81
    int crow_size; /* compressed row size (include filter type) */
82
    int row_size; /* decompressed row size */
83
    int pass_row_size; /* decompress row size of the current pass */
84
    int y;
85
    z_stream zstream;
86
    uint8_t buf[IOBUF_SIZE];
87
} PNGContext;
88

    
89
static unsigned int get32(uint8_t **b){
90
    (*b) += 4;
91
    return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
92
}
93

    
94
#ifdef CONFIG_ENCODERS
95
static void put32(uint8_t **b, unsigned int v){
96
    *(*b)++= v>>24;
97
    *(*b)++= v>>16;
98
    *(*b)++= v>>8;
99
    *(*b)++= v;
100
}
101
#endif
102

    
103
static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
104

    
105
/* Mask to determine which y pixels are valid in a pass */
106
static const uint8_t png_pass_ymask[NB_PASSES] = {
107
    0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
108
};
109

    
110
/* Mask to determine which y pixels can be written in a pass */
111
static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
112
    0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
113
};
114

    
115
/* minimum x value */
116
static const uint8_t png_pass_xmin[NB_PASSES] = {
117
    0, 4, 0, 2, 0, 1, 0
118
};
119

    
120
/* x shift to get row width */
121
static const uint8_t png_pass_xshift[NB_PASSES] = {
122
    3, 3, 2, 2, 1, 1, 0
123
};
124

    
125
/* Mask to determine which pixels are valid in a pass */
126
static const uint8_t png_pass_mask[NB_PASSES] = {
127
    0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
128
};
129

    
130
/* Mask to determine which pixels to overwrite while displaying */
131
static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
132
    0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
133
};
134
#if 0
135
static int png_probe(AVProbeData *pd)
136
{
137
    if (pd->buf_size >= 8 &&
138
        memcmp(pd->buf, pngsig, 8) == 0)
139
        return AVPROBE_SCORE_MAX;
140
    else
141
        return 0;
142
}
143
#endif
144
static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
145
{
146
    if(items >= UINT_MAX / size)
147
        return NULL;
148
    return av_malloc(items * size);
149
}
150

    
151
static void png_zfree(void *opaque, void *ptr)
152
{
153
    av_free(ptr);
154
}
155

    
156
static int png_get_nb_channels(int color_type)
157
{
158
    int channels;
159
    channels = 1;
160
    if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) ==
161
        PNG_COLOR_MASK_COLOR)
162
        channels = 3;
163
    if (color_type & PNG_COLOR_MASK_ALPHA)
164
        channels++;
165
    return channels;
166
}
167

    
168
/* compute the row size of an interleaved pass */
169
static int png_pass_row_size(int pass, int bits_per_pixel, int width)
170
{
171
    int shift, xmin, pass_width;
172

    
173
    xmin = png_pass_xmin[pass];
174
    if (width <= xmin)
175
        return 0;
176
    shift = png_pass_xshift[pass];
177
    pass_width = (width - xmin + (1 << shift) - 1) >> shift;
178
    return (pass_width * bits_per_pixel + 7) >> 3;
179
}
180

    
181
/* NOTE: we try to construct a good looking image at each pass. width
182
   is the original image width. We also do pixel format convertion at
183
   this stage */
184
static void png_put_interlaced_row(uint8_t *dst, int width,
185
                                   int bits_per_pixel, int pass,
186
                                   int color_type, const uint8_t *src)
187
{
188
    int x, mask, dsp_mask, j, src_x, b, bpp;
189
    uint8_t *d;
190
    const uint8_t *s;
191

    
192
    mask = png_pass_mask[pass];
193
    dsp_mask = png_pass_dsp_mask[pass];
194
    switch(bits_per_pixel) {
195
    case 1:
196
        /* we must intialize the line to zero before writing to it */
197
        if (pass == 0)
198
            memset(dst, 0, (width + 7) >> 3);
199
        src_x = 0;
200
        for(x = 0; x < width; x++) {
201
            j = (x & 7);
202
            if ((dsp_mask << j) & 0x80) {
203
                b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
204
                dst[x >> 3] |= b << (7 - j);
205
            }
206
            if ((mask << j) & 0x80)
207
                src_x++;
208
        }
209
        break;
210
    default:
211
        bpp = bits_per_pixel >> 3;
212
        d = dst;
213
        s = src;
214
        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
215
            for(x = 0; x < width; x++) {
216
                j = x & 7;
217
                if ((dsp_mask << j) & 0x80) {
218
                    *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
219
                }
220
                d += bpp;
221
                if ((mask << j) & 0x80)
222
                    s += bpp;
223
            }
224
        } else {
225
            for(x = 0; x < width; x++) {
226
                j = x & 7;
227
                if ((dsp_mask << j) & 0x80) {
228
                    memcpy(d, s, bpp);
229
                }
230
                d += bpp;
231
                if ((mask << j) & 0x80)
232
                    s += bpp;
233
            }
234
        }
235
        break;
236
    }
237
}
238

    
239
#ifdef CONFIG_ENCODERS
240
static void png_get_interlaced_row(uint8_t *dst, int row_size,
241
                                   int bits_per_pixel, int pass,
242
                                   const uint8_t *src, int width)
243
{
244
    int x, mask, dst_x, j, b, bpp;
245
    uint8_t *d;
246
    const uint8_t *s;
247

    
248
    mask = png_pass_mask[pass];
249
    switch(bits_per_pixel) {
250
    case 1:
251
        memset(dst, 0, row_size);
252
        dst_x = 0;
253
        for(x = 0; x < width; x++) {
254
            j = (x & 7);
255
            if ((mask << j) & 0x80) {
256
                b = (src[x >> 3] >> (7 - j)) & 1;
257
                dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
258
                dst_x++;
259
            }
260
        }
261
        break;
262
    default:
263
        bpp = bits_per_pixel >> 3;
264
        d = dst;
265
        s = src;
266
        for(x = 0; x < width; x++) {
267
            j = x & 7;
268
            if ((mask << j) & 0x80) {
269
                memcpy(d, s, bpp);
270
                d += bpp;
271
            }
272
            s += bpp;
273
        }
274
        break;
275
    }
276
}
277
#endif
278

    
279
/* XXX: optimize */
280
/* NOTE: 'dst' can be equal to 'last' */
281
static void png_filter_row(uint8_t *dst, int filter_type,
282
                           uint8_t *src, uint8_t *last, int size, int bpp)
283
{
284
    int i, p;
285

    
286
    switch(filter_type) {
287
    case PNG_FILTER_VALUE_NONE:
288
        memcpy(dst, src, size);
289
        break;
290
    case PNG_FILTER_VALUE_SUB:
291
        for(i = 0; i < bpp; i++) {
292
            dst[i] = src[i];
293
        }
294
        for(i = bpp; i < size; i++) {
295
            p = dst[i - bpp];
296
            dst[i] = p + src[i];
297
        }
298
        break;
299
    case PNG_FILTER_VALUE_UP:
300
        for(i = 0; i < size; i++) {
301
            p = last[i];
302
            dst[i] = p + src[i];
303
        }
304
        break;
305
    case PNG_FILTER_VALUE_AVG:
306
        for(i = 0; i < bpp; i++) {
307
            p = (last[i] >> 1);
308
            dst[i] = p + src[i];
309
        }
310
        for(i = bpp; i < size; i++) {
311
            p = ((dst[i - bpp] + last[i]) >> 1);
312
            dst[i] = p + src[i];
313
        }
314
        break;
315
    case PNG_FILTER_VALUE_PAETH:
316
        for(i = 0; i < bpp; i++) {
317
            p = last[i];
318
            dst[i] = p + src[i];
319
        }
320
        for(i = bpp; i < size; i++) {
321
            int a, b, c, pa, pb, pc;
322

    
323
            a = dst[i - bpp];
324
            b = last[i];
325
            c = last[i - bpp];
326

    
327
            p = b - c;
328
            pc = a - c;
329

    
330
            pa = abs(p);
331
            pb = abs(pc);
332
            pc = abs(p + pc);
333

    
334
            if (pa <= pb && pa <= pc)
335
                p = a;
336
            else if (pb <= pc)
337
                p = b;
338
            else
339
                p = c;
340
            dst[i] = p + src[i];
341
        }
342
        break;
343
    }
344
}
345

    
346
#ifdef CONFIG_ENCODERS
347
static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
348
{
349
    uint8_t *d;
350
    int j;
351
    unsigned int v;
352

    
353
    d = dst;
354
    for(j = 0; j < width; j++) {
355
        v = ((const uint32_t *)src)[j];
356
        d[0] = v >> 16;
357
        d[1] = v >> 8;
358
        d[2] = v;
359
        d[3] = v >> 24;
360
        d += 4;
361
    }
362
}
363
#endif
364

    
365
#ifdef CONFIG_DECODERS
366
static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
367
{
368
    int j;
369
    unsigned int r, g, b, a;
370

    
371
    for(j = 0;j < width; j++) {
372
        r = src[0];
373
        g = src[1];
374
        b = src[2];
375
        a = src[3];
376
        *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
377
        dst += 4;
378
        src += 4;
379
    }
380
}
381

    
382
/* process exactly one decompressed row */
383
static void png_handle_row(PNGContext *s)
384
{
385
    uint8_t *ptr, *last_row;
386
    int got_line;
387

    
388
    if (!s->interlace_type) {
389
        ptr = s->image_buf + s->image_linesize * s->y;
390
        /* need to swap bytes correctly for RGB_ALPHA */
391
        if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
392
            png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
393
                           s->last_row, s->row_size, s->bpp);
394
            memcpy(s->last_row, s->tmp_row, s->row_size);
395
            convert_to_rgba32(ptr, s->tmp_row, s->width);
396
        } else {
397
            /* in normal case, we avoid one copy */
398
            if (s->y == 0)
399
                last_row = s->last_row;
400
            else
401
                last_row = ptr - s->image_linesize;
402

    
403
            png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
404
                           last_row, s->row_size, s->bpp);
405
        }
406
        s->y++;
407
        if (s->y == s->height) {
408
            s->state |= PNG_ALLIMAGE;
409
        }
410
    } else {
411
        got_line = 0;
412
        for(;;) {
413
            ptr = s->image_buf + s->image_linesize * s->y;
414
            if ((png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
415
                /* if we already read one row, it is time to stop to
416
                   wait for the next one */
417
                if (got_line)
418
                    break;
419
                png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
420
                               s->last_row, s->pass_row_size, s->bpp);
421
                memcpy(s->last_row, s->tmp_row, s->pass_row_size);
422
                got_line = 1;
423
            }
424
            if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
425
                /* NOTE: rgba32 is handled directly in png_put_interlaced_row */
426
                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
427
                                       s->color_type, s->last_row);
428
            }
429
            s->y++;
430
            if (s->y == s->height) {
431
                for(;;) {
432
                    if (s->pass == NB_PASSES - 1) {
433
                        s->state |= PNG_ALLIMAGE;
434
                        goto the_end;
435
                    } else {
436
                        s->pass++;
437
                        s->y = 0;
438
                        s->pass_row_size = png_pass_row_size(s->pass,
439
                                                             s->bits_per_pixel,
440
                                                             s->width);
441
                        s->crow_size = s->pass_row_size + 1;
442
                        if (s->pass_row_size != 0)
443
                            break;
444
                        /* skip pass if empty row */
445
                    }
446
                }
447
            }
448
        }
449
    the_end: ;
450
    }
451
}
452

    
453
static int png_decode_idat(PNGContext *s, int length)
454
{
455
    int ret;
456
    s->zstream.avail_in = length;
457
    s->zstream.next_in = s->bytestream;
458
    s->bytestream += length;
459

    
460
    if(s->bytestream > s->bytestream_end)
461
        return -1;
462

    
463
    /* decode one line if possible */
464
    while (s->zstream.avail_in > 0) {
465
        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
466
        if (ret != Z_OK && ret != Z_STREAM_END) {
467
            return -1;
468
        }
469
        if (s->zstream.avail_out == 0) {
470
            if (!(s->state & PNG_ALLIMAGE)) {
471
                png_handle_row(s);
472
            }
473
            s->zstream.avail_out = s->crow_size;
474
            s->zstream.next_out = s->crow_buf;
475
        }
476
    }
477
    return 0;
478
}
479

    
480
static int decode_frame(AVCodecContext *avctx,
481
                        void *data, int *data_size,
482
                        uint8_t *buf, int buf_size)
483
{
484
    PNGContext * const s = avctx->priv_data;
485
    AVFrame *picture = data;
486
    AVFrame * const p= (AVFrame*)&s->picture;
487
    uint32_t tag, length;
488
    int ret, crc;
489

    
490
    s->bytestream_start=
491
    s->bytestream= buf;
492
    s->bytestream_end= buf + buf_size;
493

    
494
    /* check signature */
495
    if (memcmp(s->bytestream, pngsig, 8) != 0)
496
        return -1;
497
    s->bytestream+= 8;
498
    s->y=
499
    s->state=0;
500
//    memset(s, 0, sizeof(PNGContext));
501
    /* init the zlib */
502
    s->zstream.zalloc = png_zalloc;
503
    s->zstream.zfree = png_zfree;
504
    s->zstream.opaque = NULL;
505
    ret = inflateInit(&s->zstream);
506
    if (ret != Z_OK)
507
        return -1;
508
    for(;;) {
509
        int tag32;
510
        if (s->bytestream >= s->bytestream_end)
511
            goto fail;
512
        length = get32(&s->bytestream);
513
        if (length > 0x7fffffff)
514
            goto fail;
515
        tag32 = get32(&s->bytestream);
516
        tag = bswap_32(tag32);
517
#ifdef DEBUG
518
        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
519
               (tag & 0xff),
520
               ((tag >> 8) & 0xff),
521
               ((tag >> 16) & 0xff),
522
               ((tag >> 24) & 0xff), length);
523
#endif
524
        switch(tag) {
525
        case MKTAG('I', 'H', 'D', 'R'):
526
            if (length != 13)
527
                goto fail;
528
            s->width = get32(&s->bytestream);
529
            s->height = get32(&s->bytestream);
530
            if(avcodec_check_dimensions(avctx, s->width, s->height)){
531
                s->width= s->height= 0;
532
                goto fail;
533
            }
534
            s->bit_depth = *s->bytestream++;
535
            s->color_type = *s->bytestream++;
536
            s->compression_type = *s->bytestream++;
537
            s->filter_type = *s->bytestream++;
538
            s->interlace_type = *s->bytestream++;
539
            crc = get32(&s->bytestream);
540
            s->state |= PNG_IHDR;
541
#ifdef DEBUG
542
            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",
543
                   s->width, s->height, s->bit_depth, s->color_type,
544
                   s->compression_type, s->filter_type, s->interlace_type);
545
#endif
546
            break;
547
        case MKTAG('I', 'D', 'A', 'T'):
548
            if (!(s->state & PNG_IHDR))
549
                goto fail;
550
            if (!(s->state & PNG_IDAT)) {
551
                /* init image info */
552
                avctx->width = s->width;
553
                avctx->height = s->height;
554

    
555
                s->channels = png_get_nb_channels(s->color_type);
556
                s->bits_per_pixel = s->bit_depth * s->channels;
557
                s->bpp = (s->bits_per_pixel + 7) >> 3;
558
                s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
559

    
560
                if (s->bit_depth == 8 &&
561
                    s->color_type == PNG_COLOR_TYPE_RGB) {
562
                    avctx->pix_fmt = PIX_FMT_RGB24;
563
                } else if (s->bit_depth == 8 &&
564
                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
565
                    avctx->pix_fmt = PIX_FMT_RGB32;
566
                } else if (s->bit_depth == 8 &&
567
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
568
                    avctx->pix_fmt = PIX_FMT_GRAY8;
569
                } else if (s->bit_depth == 16 &&
570
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
571
                    avctx->pix_fmt = PIX_FMT_GRAY16BE;
572
                } else if (s->bit_depth == 1 &&
573
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
574
                    avctx->pix_fmt = PIX_FMT_MONOBLACK;
575
                } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
576
                    avctx->pix_fmt = PIX_FMT_PAL8;
577
                } else {
578
                    goto fail;
579
                }
580
                if(p->data[0])
581
                    avctx->release_buffer(avctx, p);
582

    
583
                p->reference= 0;
584
                if(avctx->get_buffer(avctx, p) < 0){
585
                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
586
                    goto fail;
587
                }
588
                p->pict_type= FF_I_TYPE;
589
                p->key_frame= 1;
590
                p->interlaced_frame = !!s->interlace_type;
591

    
592
                /* compute the compressed row size */
593
                if (!s->interlace_type) {
594
                    s->crow_size = s->row_size + 1;
595
                } else {
596
                    s->pass = 0;
597
                    s->pass_row_size = png_pass_row_size(s->pass,
598
                                                         s->bits_per_pixel,
599
                                                         s->width);
600
                    s->crow_size = s->pass_row_size + 1;
601
                }
602
#ifdef DEBUG
603
                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
604
                       s->row_size, s->crow_size);
605
#endif
606
                s->image_buf = p->data[0];
607
                s->image_linesize = p->linesize[0];
608
                /* copy the palette if needed */
609
                if (s->color_type == PNG_COLOR_TYPE_PALETTE)
610
                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
611
                /* empty row is used if differencing to the first row */
612
                s->last_row = av_mallocz(s->row_size);
613
                if (!s->last_row)
614
                    goto fail;
615
                if (s->interlace_type ||
616
                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
617
                    s->tmp_row = av_malloc(s->row_size);
618
                    if (!s->tmp_row)
619
                        goto fail;
620
                }
621
                /* compressed row */
622
                s->crow_buf = av_malloc(s->row_size + 1);
623
                if (!s->crow_buf)
624
                    goto fail;
625
                s->zstream.avail_out = s->crow_size;
626
                s->zstream.next_out = s->crow_buf;
627
            }
628
            s->state |= PNG_IDAT;
629
            if (png_decode_idat(s, length) < 0)
630
                goto fail;
631
            /* skip crc */
632
            crc = get32(&s->bytestream);
633
            break;
634
        case MKTAG('P', 'L', 'T', 'E'):
635
            {
636
                int n, i, r, g, b;
637

    
638
                if ((length % 3) != 0 || length > 256 * 3)
639
                    goto skip_tag;
640
                /* read the palette */
641
                n = length / 3;
642
                for(i=0;i<n;i++) {
643
                    r = *s->bytestream++;
644
                    g = *s->bytestream++;
645
                    b = *s->bytestream++;
646
                    s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
647
                }
648
                for(;i<256;i++) {
649
                    s->palette[i] = (0xff << 24);
650
                }
651
                s->state |= PNG_PLTE;
652
                crc = get32(&s->bytestream);
653
            }
654
            break;
655
        case MKTAG('t', 'R', 'N', 'S'):
656
            {
657
                int v, i;
658

    
659
                /* read the transparency. XXX: Only palette mode supported */
660
                if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
661
                    length > 256 ||
662
                    !(s->state & PNG_PLTE))
663
                    goto skip_tag;
664
                for(i=0;i<length;i++) {
665
                    v = *s->bytestream++;
666
                    s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
667
                }
668
                crc = get32(&s->bytestream);
669
            }
670
            break;
671
        case MKTAG('I', 'E', 'N', 'D'):
672
            if (!(s->state & PNG_ALLIMAGE))
673
                goto fail;
674
            crc = get32(&s->bytestream);
675
            goto exit_loop;
676
        default:
677
            /* skip tag */
678
        skip_tag:
679
            s->bytestream += length + 4;
680
            break;
681
        }
682
    }
683
 exit_loop:
684
    *picture= *(AVFrame*)&s->picture;
685
    *data_size = sizeof(AVPicture);
686

    
687
    ret = s->bytestream - s->bytestream_start;
688
 the_end:
689
    inflateEnd(&s->zstream);
690
    av_freep(&s->crow_buf);
691
    av_freep(&s->last_row);
692
    av_freep(&s->tmp_row);
693
    return ret;
694
 fail:
695
    ret = -1;
696
    goto the_end;
697
}
698
#endif
699

    
700
#ifdef CONFIG_ENCODERS
701
static void png_write_chunk(uint8_t **f, uint32_t tag,
702
                            const uint8_t *buf, int length)
703
{
704
    uint32_t crc;
705
    uint8_t tagbuf[4];
706

    
707
    put32(f, length);
708
    crc = crc32(0, Z_NULL, 0);
709
    tagbuf[0] = tag;
710
    tagbuf[1] = tag >> 8;
711
    tagbuf[2] = tag >> 16;
712
    tagbuf[3] = tag >> 24;
713
    crc = crc32(crc, tagbuf, 4);
714
    put32(f, bswap_32(tag));
715
    if (length > 0) {
716
        crc = crc32(crc, buf, length);
717
        memcpy(*f, buf, length);
718
        *f += length;
719
    }
720
    put32(f, crc);
721
}
722

    
723
/* XXX: use avcodec generic function ? */
724
static void to_be32(uint8_t *p, uint32_t v)
725
{
726
    p[0] = v >> 24;
727
    p[1] = v >> 16;
728
    p[2] = v >> 8;
729
    p[3] = v;
730
}
731

    
732
/* XXX: do filtering */
733
static int png_write_row(PNGContext *s, const uint8_t *data, int size)
734
{
735
    int ret;
736

    
737
    s->zstream.avail_in = size;
738
    s->zstream.next_in = (uint8_t *)data;
739
    while (s->zstream.avail_in > 0) {
740
        ret = deflate(&s->zstream, Z_NO_FLUSH);
741
        if (ret != Z_OK)
742
            return -1;
743
        if (s->zstream.avail_out == 0) {
744
            if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
745
                png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE);
746
            s->zstream.avail_out = IOBUF_SIZE;
747
            s->zstream.next_out = s->buf;
748
        }
749
    }
750
    return 0;
751
}
752
#endif /* CONFIG_ENCODERS */
753

    
754
static int common_init(AVCodecContext *avctx){
755
    PNGContext *s = avctx->priv_data;
756

    
757
    avcodec_get_frame_defaults((AVFrame*)&s->picture);
758
    avctx->coded_frame= (AVFrame*)&s->picture;
759
//    s->avctx= avctx;
760

    
761
    return 0;
762
}
763

    
764
#ifdef CONFIG_ENCODERS
765
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
766
    PNGContext *s = avctx->priv_data;
767
    AVFrame *pict = data;
768
    AVFrame * const p= (AVFrame*)&s->picture;
769
    int bit_depth, color_type, y, len, row_size, ret, is_progressive;
770
    int bits_per_pixel, pass_row_size;
771
    uint8_t *ptr;
772
    uint8_t *crow_buf = NULL;
773
    uint8_t *tmp_buf = NULL;
774

    
775
    *p = *pict;
776
    p->pict_type= FF_I_TYPE;
777
    p->key_frame= 1;
778

    
779
    s->bytestream_start=
780
    s->bytestream= buf;
781
    s->bytestream_end= buf+buf_size;
782

    
783
    is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
784
    switch(avctx->pix_fmt) {
785
    case PIX_FMT_RGB32:
786
        bit_depth = 8;
787
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
788
        break;
789
    case PIX_FMT_RGB24:
790
        bit_depth = 8;
791
        color_type = PNG_COLOR_TYPE_RGB;
792
        break;
793
    case PIX_FMT_GRAY8:
794
        bit_depth = 8;
795
        color_type = PNG_COLOR_TYPE_GRAY;
796
        break;
797
    case PIX_FMT_MONOBLACK:
798
        bit_depth = 1;
799
        color_type = PNG_COLOR_TYPE_GRAY;
800
        break;
801
    case PIX_FMT_PAL8:
802
        bit_depth = 8;
803
        color_type = PNG_COLOR_TYPE_PALETTE;
804
        break;
805
    default:
806
        return -1;
807
    }
808
    bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
809
    row_size = (avctx->width * bits_per_pixel + 7) >> 3;
810

    
811
    s->zstream.zalloc = png_zalloc;
812
    s->zstream.zfree = png_zfree;
813
    s->zstream.opaque = NULL;
814
    ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
815
                       Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
816
    if (ret != Z_OK)
817
        return -1;
818
    crow_buf = av_malloc(row_size + 1);
819
    if (!crow_buf)
820
        goto fail;
821
    if (is_progressive) {
822
        tmp_buf = av_malloc(row_size + 1);
823
        if (!tmp_buf)
824
            goto fail;
825
    }
826

    
827
    /* write png header */
828
    memcpy(s->bytestream, pngsig, 8);
829
    s->bytestream += 8;
830

    
831
    to_be32(s->buf, avctx->width);
832
    to_be32(s->buf + 4, avctx->height);
833
    s->buf[8] = bit_depth;
834
    s->buf[9] = color_type;
835
    s->buf[10] = 0; /* compression type */
836
    s->buf[11] = 0; /* filter type */
837
    s->buf[12] = is_progressive; /* interlace type */
838

    
839
    png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
840

    
841
    /* put the palette if needed */
842
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
843
        int has_alpha, alpha, i;
844
        unsigned int v;
845
        uint32_t *palette;
846
        uint8_t *alpha_ptr;
847

    
848
        palette = (uint32_t *)p->data[1];
849
        ptr = s->buf;
850
        alpha_ptr = s->buf + 256 * 3;
851
        has_alpha = 0;
852
        for(i = 0; i < 256; i++) {
853
            v = palette[i];
854
            alpha = v >> 24;
855
            if (alpha && alpha != 0xff)
856
                has_alpha = 1;
857
            *alpha_ptr++ = alpha;
858
            ptr[0] = v >> 16;
859
            ptr[1] = v >> 8;
860
            ptr[2] = v;
861
            ptr += 3;
862
        }
863
        png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
864
        if (has_alpha) {
865
            png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
866
        }
867
    }
868

    
869
    /* now put each row */
870
    s->zstream.avail_out = IOBUF_SIZE;
871
    s->zstream.next_out = s->buf;
872
    if (is_progressive) {
873
        uint8_t *ptr1;
874
        int pass;
875

    
876
        for(pass = 0; pass < NB_PASSES; pass++) {
877
            /* NOTE: a pass is completely omited if no pixels would be
878
               output */
879
            pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
880
            if (pass_row_size > 0) {
881
                for(y = 0; y < avctx->height; y++) {
882
                    if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
883
                        ptr = p->data[0] + y * p->linesize[0];
884
                        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
885
                            convert_from_rgba32(tmp_buf, ptr, avctx->width);
886
                            ptr1 = tmp_buf;
887
                        } else {
888
                            ptr1 = ptr;
889
                        }
890
                        png_get_interlaced_row(crow_buf + 1, pass_row_size,
891
                                               bits_per_pixel, pass,
892
                                               ptr1, avctx->width);
893
                        crow_buf[0] = PNG_FILTER_VALUE_NONE;
894
                        png_write_row(s, crow_buf, pass_row_size + 1);
895
                    }
896
                }
897
            }
898
        }
899
    } else {
900
        for(y = 0; y < avctx->height; y++) {
901
            ptr = p->data[0] + y * p->linesize[0];
902
            if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
903
                convert_from_rgba32(crow_buf + 1, ptr, avctx->width);
904
            else
905
                memcpy(crow_buf + 1, ptr, row_size);
906
            crow_buf[0] = PNG_FILTER_VALUE_NONE;
907
            png_write_row(s, crow_buf, row_size + 1);
908
        }
909
    }
910
    /* compress last bytes */
911
    for(;;) {
912
        ret = deflate(&s->zstream, Z_FINISH);
913
        if (ret == Z_OK || ret == Z_STREAM_END) {
914
            len = IOBUF_SIZE - s->zstream.avail_out;
915
            if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
916
                png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len);
917
            }
918
            s->zstream.avail_out = IOBUF_SIZE;
919
            s->zstream.next_out = s->buf;
920
            if (ret == Z_STREAM_END)
921
                break;
922
        } else {
923
            goto fail;
924
        }
925
    }
926
    png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
927

    
928
    ret = s->bytestream - s->bytestream_start;
929
 the_end:
930
    av_free(crow_buf);
931
    av_free(tmp_buf);
932
    deflateEnd(&s->zstream);
933
    return ret;
934
 fail:
935
    ret = -1;
936
    goto the_end;
937
}
938
#endif
939

    
940
#ifdef CONFIG_PNG_DECODER
941
AVCodec png_decoder = {
942
    "png",
943
    CODEC_TYPE_VIDEO,
944
    CODEC_ID_PNG,
945
    sizeof(PNGContext),
946
    common_init,
947
    NULL,
948
    NULL, //decode_end,
949
    decode_frame,
950
    0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
951
    NULL
952
};
953
#endif
954

    
955
#ifdef CONFIG_PNG_ENCODER
956
AVCodec png_encoder = {
957
    "png",
958
    CODEC_TYPE_VIDEO,
959
    CODEC_ID_PNG,
960
    sizeof(PNGContext),
961
    common_init,
962
    encode_frame,
963
    NULL, //encode_end,
964
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
965
};
966
#endif // CONFIG_PNG_ENCODER