diff options
author | Loren Merritt <lorenm@u.washington.edu> | 2008-02-26 10:21:33 +0000 |
---|---|---|
committer | Loren Merritt <lorenm@u.washington.edu> | 2008-02-26 10:21:33 +0000 |
commit | 042e0adda9fd3ae1322ef51f9edbceffe3ae0941 (patch) | |
tree | 5694d8a82c7688c74317a26aa6d2563cda70dc02 /libavcodec | |
parent | d248905ba582b399bf1244fafcdfedc36569fe51 (diff) | |
download | ffmpeg-streaming-042e0adda9fd3ae1322ef51f9edbceffe3ae0941.zip ffmpeg-streaming-042e0adda9fd3ae1322ef51f9edbceffe3ae0941.tar.gz |
decode mng color decorrelation
Originally committed as revision 12228 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/png.c | 1 | ||||
-rw-r--r-- | libavcodec/png.h | 2 | ||||
-rw-r--r-- | libavcodec/pngdec.c | 36 |
3 files changed, 36 insertions, 3 deletions
diff --git a/libavcodec/png.c b/libavcodec/png.c index 969c147..c95ba3e 100644 --- a/libavcodec/png.c +++ b/libavcodec/png.c @@ -23,6 +23,7 @@ #include "png.h" const uint8_t ff_pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; +const uint8_t ff_mngsig[8] = {138, 77, 78, 71, 13, 10, 26, 10}; /* Mask to determine which y pixels are valid in a pass */ const uint8_t ff_png_pass_ymask[NB_PASSES] = { diff --git a/libavcodec/png.h b/libavcodec/png.h index 3043471..6e16f62 100644 --- a/libavcodec/png.h +++ b/libavcodec/png.h @@ -34,6 +34,7 @@ #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +#define PNG_FILTER_TYPE_LOCO 64 #define PNG_FILTER_VALUE_NONE 0 #define PNG_FILTER_VALUE_SUB 1 #define PNG_FILTER_VALUE_UP 2 @@ -49,6 +50,7 @@ #define NB_PASSES 7 extern const uint8_t ff_pngsig[8]; +extern const uint8_t ff_mngsig[8]; /* Mask to determine which y pixels are valid in a pass */ extern const uint8_t ff_png_pass_ymask[NB_PASSES]; diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index abff1da..90dac4d 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -234,7 +234,7 @@ static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type, } } -static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width) +static av_always_inline void convert_to_rgb32_loco(uint8_t *dst, const uint8_t *src, int width, int loco) { int j; unsigned int r, g, b, a; @@ -244,12 +244,34 @@ static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width) g = src[1]; b = src[2]; a = src[3]; + if(loco) { + r = (r+g)&0xff; + b = (b+g)&0xff; + } *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b; dst += 4; src += 4; } } +static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width, int loco) +{ + if(loco) + convert_to_rgb32_loco(dst, src, width, 1); + else + convert_to_rgb32_loco(dst, src, width, 0); +} + +static void deloco_rgb24(uint8_t *dst, int size) +{ + int i; + for(i=0; i<size; i+=3) { + int g = dst[i+1]; + dst[i+0] += g; + dst[i+2] += g; + } +} + /* process exactly one decompressed row */ static void png_handle_row(PNGDecContext *s) { @@ -262,7 +284,7 @@ static void png_handle_row(PNGDecContext *s) if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, s->last_row, s->row_size, s->bpp); - convert_to_rgb32(ptr, s->tmp_row, s->width); + convert_to_rgb32(ptr, s->tmp_row, s->width, s->filter_type == PNG_FILTER_TYPE_LOCO); FFSWAP(uint8_t*, s->last_row, s->tmp_row); } else { /* in normal case, we avoid one copy */ @@ -274,9 +296,16 @@ static void png_handle_row(PNGDecContext *s) png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, last_row, s->row_size, s->bpp); } + /* loco lags by 1 row so that it doesn't interfere with top prediction */ + if (s->filter_type == PNG_FILTER_TYPE_LOCO && + s->color_type == PNG_COLOR_TYPE_RGB && s->y > 0) + deloco_rgb24(ptr - s->image_linesize, s->row_size); s->y++; if (s->y == s->height) { s->state |= PNG_ALLIMAGE; + if (s->filter_type == PNG_FILTER_TYPE_LOCO && + s->color_type == PNG_COLOR_TYPE_RGB) + deloco_rgb24(ptr, s->row_size); } } else { got_line = 0; @@ -363,7 +392,8 @@ static int decode_frame(AVCodecContext *avctx, s->bytestream_end= buf + buf_size; /* check signature */ - if (memcmp(s->bytestream, ff_pngsig, 8) != 0) + if (memcmp(s->bytestream, ff_pngsig, 8) != 0 && + memcmp(s->bytestream, ff_mngsig, 8) != 0) return -1; s->bytestream+= 8; s->y= |