X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fpngdec.c;h=dd3fe67876ca840493e7807511a07cb10bee4889;hb=0a23067ab41326dfa1da41d18923ea8547a51ff5;hp=70635671c20cc94c6e25275ecd8ed4bc867b3b1c;hpb=ada49f936eaafe12365c7b962355d6dcfbfc4029;p=ffmpeg diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 70635671c20..dd3fe67876c 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -27,7 +27,7 @@ #include "png.h" /* TODO: - * - add 2, 4 and 16 bit depth support + * - add 16 bit depth support */ #include @@ -57,20 +57,46 @@ static void png_put_interlaced_row(uint8_t *dst, int width, dsp_mask = png_pass_dsp_mask[pass]; switch(bits_per_pixel) { case 1: - /* we must initialize the line to zero before writing to it */ - if (pass == 0) - memset(dst, 0, (width + 7) >> 3); src_x = 0; for(x = 0; x < width; x++) { j = (x & 7); if ((dsp_mask << j) & 0x80) { b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1; + dst[x >> 3] &= 0xFF7F>>j; dst[x >> 3] |= b << (7 - j); } if ((mask << j) & 0x80) src_x++; } break; + case 2: + src_x = 0; + for(x = 0; x < width; x++) { + int j2 = 2*(x&3); + j = (x & 7); + if ((dsp_mask << j) & 0x80) { + b = (src[src_x >> 2] >> (6 - 2*(src_x & 3))) & 3; + dst[x >> 2] &= 0xFF3F>>j2; + dst[x >> 2] |= b << (6 - j2); + } + if ((mask << j) & 0x80) + src_x++; + } + break; + case 4: + src_x = 0; + for(x = 0; x < width; x++) { + int j2 = 4*(x&1); + j = (x & 7); + if ((dsp_mask << j) & 0x80) { + b = (src[src_x >> 1] >> (4 - 4*(src_x & 1))) & 15; + dst[x >> 1] &= 0xFF0F>>j2; + dst[x >> 1] |= b << (4 - j2); + } + if ((mask << j) & 0x80) + src_x++; + } + break; default: bpp = bits_per_pixel >> 3; d = dst; @@ -319,6 +345,7 @@ static void png_handle_row(PNGDecContext *s) } s->y++; if (s->y == s->height) { + memset(s->last_row, 0, s->row_size); for(;;) { if (s->pass == NB_PASSES - 1) { s->state |= PNG_ALLIMAGE; @@ -479,7 +506,7 @@ static int decode_frame(AVCodecContext *avctx, if(p->data[0]) avctx->release_buffer(avctx, p); - p->reference= 0; + p->reference= 1; if(avctx->get_buffer(avctx, p) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); goto fail; @@ -580,6 +607,32 @@ static int decode_frame(AVCodecContext *avctx, } } exit_loop: + + if(s->bits_per_pixel == 2){ + int i, j; + uint8_t *pd = s->current_picture->data[0]; + for(j=0; j < s->height; j++) { + for(i=s->width/4-1; i>=0; i--) { + pd[4*i+3]= pd[i] &3; + pd[4*i+2]= (pd[i]>>2)&3; + pd[4*i+1]= (pd[i]>>4)&3; + pd[4*i+0]= pd[i]>>6; + } + pd += s->image_linesize; + } + } + if(s->bits_per_pixel == 4){ + int i, j; + uint8_t *pd = s->current_picture->data[0]; + for(j=0; j < s->height; j++) { + for(i=s->width/2-1; i>=0; i--) { + pd[2*i+1]= pd[i]&15; + pd[2*i+0]= pd[i]>>4; + } + pd += s->image_linesize; + } + } + /* handle p-frames only if a predecessor frame is available */ if(s->last_picture->data[0] != NULL) { if(!(avpkt->flags & AV_PKT_FLAG_KEY)) {