png.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:28k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * PNG image format
  3.  * Copyright (c) 2003 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include "avcodec.h"
  20. /* TODO:
  21.  * - add 2, 4 and 16 bit depth support
  22.  * - use filters when generating a png (better compression)
  23.  */
  24. #ifdef CONFIG_ZLIB
  25. #include <zlib.h>
  26. //#define DEBUG
  27. #define PNG_COLOR_MASK_PALETTE    1
  28. #define PNG_COLOR_MASK_COLOR      2
  29. #define PNG_COLOR_MASK_ALPHA      4
  30. #define PNG_COLOR_TYPE_GRAY 0
  31. #define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
  32. #define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
  33. #define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
  34. #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
  35. #define PNG_FILTER_VALUE_NONE  0
  36. #define PNG_FILTER_VALUE_SUB   1
  37. #define PNG_FILTER_VALUE_UP    2
  38. #define PNG_FILTER_VALUE_AVG   3
  39. #define PNG_FILTER_VALUE_PAETH 4
  40. #define PNG_IHDR      0x0001
  41. #define PNG_IDAT      0x0002
  42. #define PNG_ALLIMAGE  0x0004
  43. #define PNG_PLTE      0x0008
  44. #define NB_PASSES 7
  45. #define IOBUF_SIZE 4096
  46. typedef struct PNGContext {
  47.     uint8_t *bytestream;
  48.     uint8_t *bytestream_start;
  49.     uint8_t *bytestream_end;
  50.     AVFrame picture;
  51.     int state;
  52.     int width, height;
  53.     int bit_depth;
  54.     int color_type;
  55.     int compression_type;
  56.     int interlace_type;
  57.     int filter_type;
  58.     int channels;
  59.     int bits_per_pixel;
  60.     int bpp;
  61.     
  62.     uint8_t *image_buf;
  63.     int image_linesize;
  64.     uint32_t palette[256];
  65.     uint8_t *crow_buf;
  66.     uint8_t *last_row;
  67.     uint8_t *tmp_row;
  68.     int pass;
  69.     int crow_size; /* compressed row size (include filter type) */
  70.     int row_size; /* decompressed row size */
  71.     int pass_row_size; /* decompress row size of the current pass */
  72.     int y;
  73.     z_stream zstream;
  74.     uint8_t buf[IOBUF_SIZE];
  75. } PNGContext;
  76. static unsigned int get32(uint8_t **b){
  77.     (*b) += 4;
  78.     return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
  79. }
  80. static void put32(uint8_t **b, unsigned int v){
  81.     *(*b)++= v>>24;
  82.     *(*b)++= v>>16;
  83.     *(*b)++= v>>8;
  84.     *(*b)++= v;
  85. }
  86. static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
  87. /* Mask to determine which y pixels are valid in a pass */
  88. static const uint8_t png_pass_ymask[NB_PASSES] = {
  89.     0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
  90. };
  91. /* Mask to determine which y pixels can be written in a pass */
  92. static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
  93.     0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
  94. };
  95. /* minimum x value */
  96. static const uint8_t png_pass_xmin[NB_PASSES] = {
  97.     0, 4, 0, 2, 0, 1, 0
  98. };
  99. /* x shift to get row width */
  100. static const uint8_t png_pass_xshift[NB_PASSES] = {
  101.     3, 3, 2, 2, 1, 1, 0
  102. };
  103. /* Mask to determine which pixels are valid in a pass */
  104. static const uint8_t png_pass_mask[NB_PASSES] = {
  105.     0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
  106. };
  107. /* Mask to determine which pixels to overwrite while displaying */
  108. static const uint8_t png_pass_dsp_mask[NB_PASSES] = { 
  109.     0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
  110. };
  111. #if 0
  112. static int png_probe(AVProbeData *pd)
  113. {
  114.     if (pd->buf_size >= 8 &&
  115.         memcmp(pd->buf, pngsig, 8) == 0)
  116.         return AVPROBE_SCORE_MAX;
  117.     else
  118.         return 0;
  119. }
  120. #endif
  121. static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
  122. {
  123.     if(items >= UINT_MAX / size)
  124.         return NULL;
  125.     return av_malloc(items * size);
  126. }
  127. static void png_zfree(void *opaque, void *ptr)
  128. {
  129.     av_free(ptr);
  130. }
  131. static int png_get_nb_channels(int color_type)
  132. {
  133.     int channels;
  134.     channels = 1;
  135.     if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) ==
  136.         PNG_COLOR_MASK_COLOR)
  137.         channels = 3;
  138.     if (color_type & PNG_COLOR_MASK_ALPHA)
  139.         channels++;
  140.     return channels;
  141. }
  142. /* compute the row size of an interleaved pass */
  143. static int png_pass_row_size(int pass, int bits_per_pixel, int width)
  144. {
  145.     int shift, xmin, pass_width;
  146.     xmin = png_pass_xmin[pass];
  147.     if (width <= xmin)
  148.         return 0;
  149.     shift = png_pass_xshift[pass];
  150.     pass_width = (width - xmin + (1 << shift) - 1) >> shift;
  151.     return (pass_width * bits_per_pixel + 7) >> 3;
  152. }
  153. /* NOTE: we try to construct a good looking image at each pass. width
  154.    is the original image width. We also do pixel format convertion at
  155.    this stage */
  156. static void png_put_interlaced_row(uint8_t *dst, int width, 
  157.                                    int bits_per_pixel, int pass, 
  158.                                    int color_type, const uint8_t *src)
  159. {
  160.     int x, mask, dsp_mask, j, src_x, b, bpp;
  161.     uint8_t *d;
  162.     const uint8_t *s;
  163.     
  164.     mask = png_pass_mask[pass];
  165.     dsp_mask = png_pass_dsp_mask[pass];
  166.     switch(bits_per_pixel) {
  167.     case 1:
  168.         /* we must intialize the line to zero before writing to it */
  169.         if (pass == 0)
  170.             memset(dst, 0, (width + 7) >> 3);
  171.         src_x = 0;
  172.         for(x = 0; x < width; x++) {
  173.             j = (x & 7);
  174.             if ((dsp_mask << j) & 0x80) {
  175.                 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
  176.                 dst[x >> 3] |= b << (7 - j);
  177.             }
  178.             if ((mask << j) & 0x80)
  179.                 src_x++;
  180.         }
  181.         break;
  182.     default:
  183.         bpp = bits_per_pixel >> 3;
  184.         d = dst;
  185.         s = src;
  186.         if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  187.             for(x = 0; x < width; x++) {
  188.                 j = x & 7;
  189.                 if ((dsp_mask << j) & 0x80) {
  190.                     *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
  191.                 }
  192.                 d += bpp;
  193.                 if ((mask << j) & 0x80)
  194.                     s += bpp;
  195.             }
  196.         } else {
  197.             for(x = 0; x < width; x++) {
  198.                 j = x & 7;
  199.                 if ((dsp_mask << j) & 0x80) {
  200.                     memcpy(d, s, bpp);
  201.                 }
  202.                 d += bpp;
  203.                 if ((mask << j) & 0x80)
  204.                     s += bpp;
  205.             }
  206.         }
  207.         break;
  208.     }
  209. }
  210. static void png_get_interlaced_row(uint8_t *dst, int row_size, 
  211.                                    int bits_per_pixel, int pass, 
  212.                                    const uint8_t *src, int width)
  213. {
  214.     int x, mask, dst_x, j, b, bpp;
  215.     uint8_t *d;
  216.     const uint8_t *s;
  217.     mask = png_pass_mask[pass];
  218.     switch(bits_per_pixel) {
  219.     case 1:
  220.         memset(dst, 0, row_size);
  221.         dst_x = 0;
  222.         for(x = 0; x < width; x++) {
  223.             j = (x & 7);
  224.             if ((mask << j) & 0x80) {
  225.                 b = (src[x >> 3] >> (7 - j)) & 1;
  226.                 dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
  227.                 dst_x++;
  228.             }
  229.         }
  230.         break;
  231.     default:
  232.         bpp = bits_per_pixel >> 3;
  233.         d = dst;
  234.         s = src;
  235.         for(x = 0; x < width; x++) {
  236.             j = x & 7;
  237.             if ((mask << j) & 0x80) {
  238.                 memcpy(d, s, bpp);
  239.                 d += bpp;
  240.             }
  241.             s += bpp;
  242.         }
  243.         break;
  244.     }
  245. }
  246. /* XXX: optimize */
  247. /* NOTE: 'dst' can be equal to 'last' */
  248. static void png_filter_row(uint8_t *dst, int filter_type, 
  249.                            uint8_t *src, uint8_t *last, int size, int bpp)
  250. {
  251.     int i, p;
  252.     switch(filter_type) {
  253.     case PNG_FILTER_VALUE_NONE:
  254.         memcpy(dst, src, size);
  255.         break;
  256.     case PNG_FILTER_VALUE_SUB:
  257.         for(i = 0; i < bpp; i++) {
  258.             dst[i] = src[i];
  259.         }
  260.         for(i = bpp; i < size; i++) {
  261.             p = dst[i - bpp];
  262.             dst[i] = p + src[i];
  263.         }
  264.         break;
  265.     case PNG_FILTER_VALUE_UP:
  266.         for(i = 0; i < size; i++) {
  267.             p = last[i];
  268.             dst[i] = p + src[i];
  269.         }
  270.         break;
  271.     case PNG_FILTER_VALUE_AVG:
  272.         for(i = 0; i < bpp; i++) {
  273.             p = (last[i] >> 1);
  274.             dst[i] = p + src[i];
  275.         }
  276.         for(i = bpp; i < size; i++) {
  277.             p = ((dst[i - bpp] + last[i]) >> 1);
  278.             dst[i] = p + src[i];
  279.         }
  280.         break;
  281.     case PNG_FILTER_VALUE_PAETH:
  282.         for(i = 0; i < bpp; i++) {
  283.             p = last[i];
  284.             dst[i] = p + src[i];
  285.         }
  286.         for(i = bpp; i < size; i++) {
  287.             int a, b, c, pa, pb, pc;
  288.             a = dst[i - bpp];
  289.             b = last[i];
  290.             c = last[i - bpp];
  291.             p = b - c;
  292.             pc = a - c;
  293.             pa = abs(p);
  294.             pb = abs(pc);
  295.             pc = abs(p + pc);
  296.             if (pa <= pb && pa <= pc)
  297.                 p = a;
  298.             else if (pb <= pc)
  299.                 p = b;
  300.             else
  301.                 p = c;
  302.             dst[i] = p + src[i];
  303.         }
  304.         break;
  305.     }
  306. }
  307. static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
  308. {
  309.     uint8_t *d;
  310.     int j;
  311.     unsigned int v;
  312.     
  313.     d = dst;
  314.     for(j = 0; j < width; j++) {
  315.         v = ((uint32_t *)src)[j];
  316.         d[0] = v >> 16;
  317.         d[1] = v >> 8;
  318.         d[2] = v;
  319.         d[3] = v >> 24;
  320.         d += 4;
  321.     }
  322. }
  323. static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
  324. {
  325.     int j;
  326.     unsigned int r, g, b, a;
  327.     for(j = 0;j < width; j++) {
  328.         r = src[0];
  329.         g = src[1];
  330.         b = src[2];
  331.         a = src[3];
  332.         *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
  333.         dst += 4;
  334.         src += 4;
  335.     }
  336. }
  337. /* process exactly one decompressed row */
  338. static void png_handle_row(PNGContext *s)
  339. {
  340.     uint8_t *ptr, *last_row;
  341.     int got_line;
  342.     
  343.     if (!s->interlace_type) {
  344.         ptr = s->image_buf + s->image_linesize * s->y;
  345.         /* need to swap bytes correctly for RGB_ALPHA */
  346.         if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  347.             png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1, 
  348.                            s->last_row, s->row_size, s->bpp);
  349.             memcpy(s->last_row, s->tmp_row, s->row_size);
  350.             convert_to_rgba32(ptr, s->tmp_row, s->width);
  351.         } else {
  352.             /* in normal case, we avoid one copy */
  353.             if (s->y == 0)
  354.                 last_row = s->last_row;
  355.             else
  356.                 last_row = ptr - s->image_linesize;
  357.             
  358.             png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1, 
  359.                            last_row, s->row_size, s->bpp);
  360.         }
  361.         s->y++;
  362.         if (s->y == s->height) {
  363.             s->state |= PNG_ALLIMAGE;
  364.         }
  365.     } else {
  366.         got_line = 0;
  367.         for(;;) {
  368.             ptr = s->image_buf + s->image_linesize * s->y;
  369.             if ((png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
  370.                 /* if we already read one row, it is time to stop to
  371.                    wait for the next one */
  372.                 if (got_line)
  373.                     break;
  374.                 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1, 
  375.                                s->last_row, s->pass_row_size, s->bpp);
  376.                 memcpy(s->last_row, s->tmp_row, s->pass_row_size);
  377.                 got_line = 1;
  378.             }
  379.             if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
  380.                 /* NOTE: rgba32 is handled directly in png_put_interlaced_row */
  381.                 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass, 
  382.                                        s->color_type, s->last_row);
  383.             }
  384.             s->y++;
  385.             if (s->y == s->height) {
  386.                 for(;;) {
  387.                     if (s->pass == NB_PASSES - 1) {
  388.                         s->state |= PNG_ALLIMAGE;
  389.                         goto the_end;
  390.                     } else {
  391.                         s->pass++;
  392.                         s->y = 0;
  393.                         s->pass_row_size = png_pass_row_size(s->pass, 
  394.                                                              s->bits_per_pixel, 
  395.                                                              s->width);
  396.                         s->crow_size = s->pass_row_size + 1;
  397.                         if (s->pass_row_size != 0)
  398.                             break;
  399.                         /* skip pass if empty row */
  400.                     }
  401.                 }
  402.             }
  403.         }
  404.     the_end: ;
  405.     }
  406. }
  407. static int png_decode_idat(PNGContext *s, int length)
  408. {
  409.     int ret;
  410.     s->zstream.avail_in = length;
  411.     s->zstream.next_in = s->bytestream;
  412.     s->bytestream += length;
  413.     
  414.     if(s->bytestream > s->bytestream_end)
  415.         return -1;
  416.     /* decode one line if possible */
  417.     while (s->zstream.avail_in > 0) {
  418.         ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
  419.         if (ret != Z_OK && ret != Z_STREAM_END) {
  420.             return -1;
  421.         }
  422.         if (s->zstream.avail_out == 0) {
  423.             if (!(s->state & PNG_ALLIMAGE)) {
  424.                 png_handle_row(s);
  425.             }
  426.             s->zstream.avail_out = s->crow_size;
  427.             s->zstream.next_out = s->crow_buf;
  428.         }
  429.     }
  430.     return 0;
  431. }
  432. static int decode_frame(AVCodecContext *avctx, 
  433.                         void *data, int *data_size,
  434.                         uint8_t *buf, int buf_size)
  435. {
  436.     PNGContext * const s = avctx->priv_data;
  437.     AVFrame *picture = data;
  438.     AVFrame * const p= (AVFrame*)&s->picture;
  439.     uint32_t tag, length;
  440.     int ret, crc;
  441.     s->bytestream_start=
  442.     s->bytestream= buf;
  443.     s->bytestream_end= buf + buf_size;
  444.     /* check signature */
  445.     if (memcmp(s->bytestream, pngsig, 8) != 0)
  446.         return -1;
  447.     s->bytestream+= 8;
  448.     s->y=
  449.     s->state=0;
  450. //    memset(s, 0, sizeof(PNGContext));
  451.     /* init the zlib */
  452.     s->zstream.zalloc = png_zalloc;
  453.     s->zstream.zfree = png_zfree;
  454.     s->zstream.opaque = NULL;
  455.     ret = inflateInit(&s->zstream);
  456.     if (ret != Z_OK)
  457.         return -1;
  458.     for(;;) {
  459.         int tag32;
  460.         if (s->bytestream >= s->bytestream_end)
  461.             goto fail;
  462.         length = get32(&s->bytestream);
  463.         if (length > 0x7fffffff)
  464.             goto fail;
  465.         tag32 = get32(&s->bytestream);
  466.         tag = bswap_32(tag32);
  467. #ifdef DEBUG
  468.         printf("png: tag=%c%c%c%c length=%un", 
  469.                (tag & 0xff),
  470.                ((tag >> 8) & 0xff),
  471.                ((tag >> 16) & 0xff),
  472.                ((tag >> 24) & 0xff), length);
  473. #endif
  474.         switch(tag) {
  475.         case MKTAG('I', 'H', 'D', 'R'):
  476.             if (length != 13)
  477.                 goto fail;
  478.             s->width = get32(&s->bytestream);
  479.             s->height = get32(&s->bytestream);
  480.             if(avcodec_check_dimensions(avctx, s->width, s->height)){
  481.                 s->width= s->height= 0;
  482.                 goto fail;
  483.             }
  484.             s->bit_depth = *s->bytestream++;
  485.             s->color_type = *s->bytestream++;
  486.             s->compression_type = *s->bytestream++;
  487.             s->filter_type = *s->bytestream++;
  488.             s->interlace_type = *s->bytestream++;
  489.             crc = get32(&s->bytestream);
  490.             s->state |= PNG_IHDR;
  491. #ifdef DEBUG
  492.             printf("width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%dn", 
  493.                    s->width, s->height, s->bit_depth, s->color_type, 
  494.                    s->compression_type, s->filter_type, s->interlace_type);
  495. #endif
  496.             break;
  497.         case MKTAG('I', 'D', 'A', 'T'):
  498.             if (!(s->state & PNG_IHDR))
  499.                 goto fail;
  500.             if (!(s->state & PNG_IDAT)) {
  501.                 /* init image info */
  502.                 avctx->width = s->width;
  503.                 avctx->height = s->height;
  504.                 s->channels = png_get_nb_channels(s->color_type);
  505.                 s->bits_per_pixel = s->bit_depth * s->channels;
  506.                 s->bpp = (s->bits_per_pixel + 7) >> 3;
  507.                 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
  508.                 if (s->bit_depth == 8 && 
  509.                     s->color_type == PNG_COLOR_TYPE_RGB) {
  510.                     avctx->pix_fmt = PIX_FMT_RGB24;
  511.                 } else if (s->bit_depth == 8 && 
  512.                            s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  513.                     avctx->pix_fmt = PIX_FMT_RGBA32;
  514.                 } else if (s->bit_depth == 8 && 
  515.                            s->color_type == PNG_COLOR_TYPE_GRAY) {
  516.                     avctx->pix_fmt = PIX_FMT_GRAY8;
  517.                 } else if (s->bit_depth == 1 && 
  518.                            s->color_type == PNG_COLOR_TYPE_GRAY) {
  519.                     avctx->pix_fmt = PIX_FMT_MONOBLACK;
  520.                 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
  521.                     avctx->pix_fmt = PIX_FMT_PAL8;
  522.                 } else {
  523.                     goto fail;
  524.                 }
  525.                 if(p->data[0])
  526.                     avctx->release_buffer(avctx, p);
  527.             
  528.                 p->reference= 0;
  529.                 if(avctx->get_buffer(avctx, p) < 0){
  530.                     av_log(avctx, AV_LOG_ERROR, "get_buffer() failedn");
  531.                     goto fail;
  532.                 }
  533.                 p->pict_type= FF_I_TYPE;
  534.                 p->key_frame= 1;
  535.                 p->interlaced_frame = !!s->interlace_type;
  536.                 /* compute the compressed row size */
  537.                 if (!s->interlace_type) {
  538.                     s->crow_size = s->row_size + 1;
  539.                 } else {
  540.                     s->pass = 0;
  541.                     s->pass_row_size = png_pass_row_size(s->pass, 
  542.                                                          s->bits_per_pixel, 
  543.                                                          s->width);
  544.                     s->crow_size = s->pass_row_size + 1;
  545.                 }
  546. #ifdef DEBUG
  547.                 printf("row_size=%d crow_size =%dn", 
  548.                        s->row_size, s->crow_size);
  549. #endif
  550.                 s->image_buf = p->data[0];
  551.                 s->image_linesize = p->linesize[0];
  552.                 /* copy the palette if needed */
  553.                 if (s->color_type == PNG_COLOR_TYPE_PALETTE)
  554.                     memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
  555.                 /* empty row is used if differencing to the first row */
  556.                 s->last_row = av_mallocz(s->row_size);
  557.                 if (!s->last_row)
  558.                     goto fail;
  559.                 if (s->interlace_type ||
  560.                     s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  561.                     s->tmp_row = av_malloc(s->row_size);
  562.                     if (!s->tmp_row)
  563.                         goto fail;
  564.                 }
  565.                 /* compressed row */
  566.                 s->crow_buf = av_malloc(s->row_size + 1);
  567.                 if (!s->crow_buf)
  568.                     goto fail;
  569.                 s->zstream.avail_out = s->crow_size;
  570.                 s->zstream.next_out = s->crow_buf;
  571.             }
  572.             s->state |= PNG_IDAT;
  573.             if (png_decode_idat(s, length) < 0)
  574.                 goto fail;
  575.             /* skip crc */
  576.             crc = get32(&s->bytestream);
  577.             break;
  578.         case MKTAG('P', 'L', 'T', 'E'):
  579.             {
  580.                 int n, i, r, g, b;
  581.                 
  582.                 if ((length % 3) != 0 || length > 256 * 3)
  583.                     goto skip_tag;
  584.                 /* read the palette */
  585.                 n = length / 3;
  586.                 for(i=0;i<n;i++) {
  587.                     r = *s->bytestream++;
  588.                     g = *s->bytestream++;
  589.                     b = *s->bytestream++;
  590.                     s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
  591.                 }
  592.                 for(;i<256;i++) {
  593.                     s->palette[i] = (0xff << 24);
  594.                 }
  595.                 s->state |= PNG_PLTE;
  596.                 crc = get32(&s->bytestream);
  597.             }
  598.             break;
  599.         case MKTAG('t', 'R', 'N', 'S'):
  600.             {
  601.                 int v, i;
  602.                 /* read the transparency. XXX: Only palette mode supported */
  603.                 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
  604.                     length > 256 ||
  605.                     !(s->state & PNG_PLTE))
  606.                     goto skip_tag;
  607.                 for(i=0;i<length;i++) {
  608.                     v = *s->bytestream++;
  609.                     s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
  610.                 }
  611.                 crc = get32(&s->bytestream);
  612.             }
  613.             break;
  614.         case MKTAG('I', 'E', 'N', 'D'):
  615.             if (!(s->state & PNG_ALLIMAGE))
  616.                 goto fail;
  617.             crc = get32(&s->bytestream);
  618.             goto exit_loop;
  619.         default:
  620.             /* skip tag */
  621.         skip_tag:
  622.             s->bytestream += length + 4;
  623.             break;
  624.         }
  625.     }
  626.  exit_loop:
  627.     *picture= *(AVFrame*)&s->picture;
  628.     *data_size = sizeof(AVPicture);
  629.     ret = s->bytestream - s->bytestream_start;
  630.  the_end:
  631.     inflateEnd(&s->zstream);
  632.     av_freep(&s->crow_buf);
  633.     av_freep(&s->last_row);
  634.     av_freep(&s->tmp_row);
  635.     return ret;
  636.  fail:
  637.     ret = -1;
  638.     goto the_end;
  639. }
  640. static void png_write_chunk(uint8_t **f, uint32_t tag,
  641.                             const uint8_t *buf, int length)
  642. {
  643.     uint32_t crc;
  644.     uint8_t tagbuf[4];
  645.     put32(f, length);
  646.     crc = crc32(0, Z_NULL, 0);
  647.     tagbuf[0] = tag;
  648.     tagbuf[1] = tag >> 8;
  649.     tagbuf[2] = tag >> 16;
  650.     tagbuf[3] = tag >> 24;
  651.     crc = crc32(crc, tagbuf, 4);
  652.     put32(f, bswap_32(tag));
  653.     if (length > 0) {
  654.         crc = crc32(crc, buf, length);
  655.         memcpy(*f, buf, length);
  656.         *f += length;
  657.     }
  658.     put32(f, crc);
  659. }
  660. /* XXX: use avcodec generic function ? */
  661. static void to_be32(uint8_t *p, uint32_t v)
  662. {
  663.     p[0] = v >> 24;
  664.     p[1] = v >> 16;
  665.     p[2] = v >> 8;
  666.     p[3] = v;
  667. }
  668. /* XXX: do filtering */
  669. static int png_write_row(PNGContext *s, const uint8_t *data, int size)
  670. {
  671.     int ret;
  672.     s->zstream.avail_in = size;
  673.     s->zstream.next_in = (uint8_t *)data;
  674.     while (s->zstream.avail_in > 0) {
  675.         ret = deflate(&s->zstream, Z_NO_FLUSH);
  676.         if (ret != Z_OK)
  677.             return -1;
  678.         if (s->zstream.avail_out == 0) {
  679.             if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
  680.                 png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE);
  681.             s->zstream.avail_out = IOBUF_SIZE;
  682.             s->zstream.next_out = s->buf;
  683.         }
  684.     }
  685.     return 0;
  686. }
  687. static int common_init(AVCodecContext *avctx){
  688.     PNGContext *s = avctx->priv_data;
  689.     avcodec_get_frame_defaults((AVFrame*)&s->picture);
  690.     avctx->coded_frame= (AVFrame*)&s->picture;
  691. //    s->avctx= avctx;
  692.     return 0;
  693. }
  694. static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
  695.     PNGContext *s = avctx->priv_data;
  696.     AVFrame *pict = data;
  697.     AVFrame * const p= (AVFrame*)&s->picture;
  698.     int bit_depth, color_type, y, len, row_size, ret, is_progressive;
  699.     int bits_per_pixel, pass_row_size;
  700.     uint8_t *ptr;
  701.     uint8_t *crow_buf = NULL;
  702.     uint8_t *tmp_buf = NULL;
  703.     *p = *pict;
  704.     p->pict_type= FF_I_TYPE;
  705.     p->key_frame= 1;
  706.     
  707.     s->bytestream_start=
  708.     s->bytestream= buf;
  709.     s->bytestream_end= buf+buf_size;
  710.     is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
  711.     switch(avctx->pix_fmt) {
  712.     case PIX_FMT_RGBA32:
  713.         bit_depth = 8;
  714.         color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  715.         break;
  716.     case PIX_FMT_RGB24:
  717.         bit_depth = 8;
  718.         color_type = PNG_COLOR_TYPE_RGB;
  719.         break;
  720.     case PIX_FMT_GRAY8:
  721.         bit_depth = 8;
  722.         color_type = PNG_COLOR_TYPE_GRAY;
  723.         break;
  724.     case PIX_FMT_MONOBLACK:
  725.         bit_depth = 1;
  726.         color_type = PNG_COLOR_TYPE_GRAY;
  727.         break;
  728.     case PIX_FMT_PAL8:
  729.         bit_depth = 8;
  730.         color_type = PNG_COLOR_TYPE_PALETTE;
  731.         break;
  732.     default:
  733.         return -1;
  734.     }
  735.     bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
  736.     row_size = (avctx->width * bits_per_pixel + 7) >> 3;
  737.     s->zstream.zalloc = png_zalloc;
  738.     s->zstream.zfree = png_zfree;
  739.     s->zstream.opaque = NULL;
  740.     ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
  741.                        Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
  742.     if (ret != Z_OK)
  743.         return -1;
  744.     crow_buf = av_malloc(row_size + 1);
  745.     if (!crow_buf)
  746.         goto fail;
  747.     if (is_progressive) {
  748.         tmp_buf = av_malloc(row_size + 1);
  749.         if (!tmp_buf)
  750.             goto fail;
  751.     }
  752.     /* write png header */
  753.     memcpy(s->bytestream, pngsig, 8);
  754.     s->bytestream += 8;
  755.     
  756.     to_be32(s->buf, avctx->width);
  757.     to_be32(s->buf + 4, avctx->height);
  758.     s->buf[8] = bit_depth;
  759.     s->buf[9] = color_type;
  760.     s->buf[10] = 0; /* compression type */
  761.     s->buf[11] = 0; /* filter type */
  762.     s->buf[12] = is_progressive; /* interlace type */
  763.     
  764.     png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
  765.     /* put the palette if needed */
  766.     if (color_type == PNG_COLOR_TYPE_PALETTE) {
  767.         int has_alpha, alpha, i;
  768.         unsigned int v;
  769.         uint32_t *palette;
  770.         uint8_t *alpha_ptr;
  771.         
  772.         palette = (uint32_t *)p->data[1];
  773.         ptr = s->buf;
  774.         alpha_ptr = s->buf + 256 * 3;
  775.         has_alpha = 0;
  776.         for(i = 0; i < 256; i++) {
  777.             v = palette[i];
  778.             alpha = v >> 24;
  779.             if (alpha != 0xff)
  780.                 has_alpha = 1;
  781.             *alpha_ptr++ = alpha;
  782.             ptr[0] = v >> 16;
  783.             ptr[1] = v >> 8;
  784.             ptr[2] = v;
  785.             ptr += 3;
  786.         }
  787.         png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
  788.         if (has_alpha) {
  789.             png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
  790.         }
  791.     }
  792.     /* now put each row */
  793.     s->zstream.avail_out = IOBUF_SIZE;
  794.     s->zstream.next_out = s->buf;
  795.     if (is_progressive) {
  796.         uint8_t *ptr1;
  797.         int pass;
  798.         for(pass = 0; pass < NB_PASSES; pass++) {
  799.             /* NOTE: a pass is completely omited if no pixels would be
  800.                output */
  801.             pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
  802.             if (pass_row_size > 0) {
  803.                 for(y = 0; y < avctx->height; y++) {
  804.                     if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
  805.                         ptr = p->data[0] + y * p->linesize[0];
  806.                         if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  807.                             convert_from_rgba32(tmp_buf, ptr, avctx->width);
  808.                             ptr1 = tmp_buf;
  809.                         } else {
  810.                             ptr1 = ptr;
  811.                         }
  812.                         png_get_interlaced_row(crow_buf + 1, pass_row_size, 
  813.                                                bits_per_pixel, pass, 
  814.                                                ptr1, avctx->width);
  815.                         crow_buf[0] = PNG_FILTER_VALUE_NONE;
  816.                         png_write_row(s, crow_buf, pass_row_size + 1);
  817.                     }
  818.                 }
  819.             }
  820.         }
  821.     } else {
  822.         for(y = 0; y < avctx->height; y++) {
  823.             ptr = p->data[0] + y * p->linesize[0];
  824.             if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  825.                 convert_from_rgba32(crow_buf + 1, ptr, avctx->width);
  826.             else
  827.                 memcpy(crow_buf + 1, ptr, row_size);
  828.             crow_buf[0] = PNG_FILTER_VALUE_NONE;
  829.             png_write_row(s, crow_buf, row_size + 1);
  830.         }
  831.     }
  832.     /* compress last bytes */
  833.     for(;;) {
  834.         ret = deflate(&s->zstream, Z_FINISH);
  835.         if (ret == Z_OK || ret == Z_STREAM_END) {
  836.             len = IOBUF_SIZE - s->zstream.avail_out;
  837.             if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
  838.                 png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len);
  839.             }
  840.             s->zstream.avail_out = IOBUF_SIZE;
  841.             s->zstream.next_out = s->buf;
  842.             if (ret == Z_STREAM_END)
  843.                 break;
  844.         } else {
  845.             goto fail;
  846.         }
  847.     }
  848.     png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
  849.     ret = s->bytestream - s->bytestream_start;
  850.  the_end:
  851.     av_free(crow_buf);
  852.     av_free(tmp_buf);
  853.     deflateEnd(&s->zstream);
  854.     return ret;
  855.  fail:
  856.     ret = -1;
  857.     goto the_end;
  858. }
  859. AVCodec png_decoder = {
  860.     "png",
  861.     CODEC_TYPE_VIDEO,
  862.     CODEC_ID_PNG,
  863.     sizeof(PNGContext),
  864.     common_init,
  865.     NULL,
  866.     NULL, //decode_end,
  867.     decode_frame,
  868.     0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
  869.     NULL
  870. };
  871. #ifdef CONFIG_PNG_ENCODER
  872. AVCodec png_encoder = {
  873.     "png",
  874.     CODEC_TYPE_VIDEO,
  875.     CODEC_ID_PNG,
  876.     sizeof(PNGContext),
  877.     common_init,
  878.     encode_frame,
  879.     NULL, //encode_end,
  880.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
  881. };
  882. #endif // CONFIG_PNG_ENCODER
  883. #endif