summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorLoren Merritt <lorenm@u.washington.edu>2008-02-26 10:21:33 +0000
committerLoren Merritt <lorenm@u.washington.edu>2008-02-26 10:21:33 +0000
commit042e0adda9fd3ae1322ef51f9edbceffe3ae0941 (patch)
tree5694d8a82c7688c74317a26aa6d2563cda70dc02 /libavcodec
parentd248905ba582b399bf1244fafcdfedc36569fe51 (diff)
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.c1
-rw-r--r--libavcodec/png.h2
-rw-r--r--libavcodec/pngdec.c36
3 files changed, 36 insertions, 3 deletions
diff --git a/libavcodec/png.c b/libavcodec/png.c
index 969c14774f..c95ba3e10d 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 3043471194..6e16f62e0f 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 abff1da77b..90dac4dfa5 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=