From 33240dfa9acad976ed60dbddaf08e441d029b53b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Feb 2013 19:29:39 +0000 Subject: [PATCH] exr: pxr24 decompression Signed-off-by: Paul B Mahol --- libavcodec/exr.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 53c8f2b656..8c1cca4073 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -37,6 +37,7 @@ #include "mathops.h" #include "thread.h" #include "libavutil/imgutils.h" +#include "libavutil/avassert.h" enum ExrCompr { EXR_RAW = 0, @@ -44,6 +45,7 @@ enum ExrCompr { EXR_ZIP1 = 2, EXR_ZIP16 = 3, EXR_PIZ = 4, + EXR_PXR24 = 5, EXR_B44 = 6, EXR_B44A = 7, }; @@ -78,6 +80,8 @@ typedef struct EXRContext { uint32_t ymax, ymin; uint32_t xdelta, ydelta; + int ysize; + uint64_t scan_line_size; int scan_lines_per_block; @@ -273,6 +277,61 @@ static int rle_uncompress(const uint8_t *src, int compressed_size, return 0; } +static int pxr24_uncompress(EXRContext *s, const uint8_t *src, + int compressed_size, int uncompressed_size, + EXRThreadData *td) +{ + unsigned long dest_len = uncompressed_size; + const uint8_t *in = td->tmp; + uint8_t *out; + int c, i, j; + + if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK || + dest_len != uncompressed_size) + return AVERROR(EINVAL); + + out = td->uncompressed_data; + for (i = 0; i < s->ysize; i++) { + for (c = 0; c < s->nb_channels; c++) { + EXRChannel *channel = &s->channels[c]; + const uint8_t *ptr[4]; + uint32_t pixel = 0; + + switch (channel->pixel_type) { + case EXR_FLOAT: + ptr[0] = in; + ptr[1] = ptr[0] + s->xdelta; + ptr[2] = ptr[1] + s->xdelta; + in = ptr[2] + s->xdelta; + + for (j = 0; j < s->xdelta; ++j) { + uint32_t diff = (*(ptr[0]++) << 24) | + (*(ptr[1]++) << 16) | + (*(ptr[2]++) << 8); + pixel += diff; + AV_WL32(out, pixel); + } + break; + case EXR_HALF: + ptr[0] = in; + ptr[1] = ptr[0] + s->xdelta; + in = ptr[1] + s->xdelta; + for (j = 0; j < s->xdelta; j++, out += 2) { + uint32_t diff = (*(ptr[0]++) << 8) | *(ptr[1]++); + + pixel += diff; + AV_WL16(out, pixel); + } + break; + default: + av_assert1(0); + } + } + } + + return 0; +} + static int decode_block(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr) { @@ -305,7 +364,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, if (data_size <= 0 || data_size > buf_size) return AVERROR_INVALIDDATA; - uncompressed_size = s->scan_line_size * FFMIN(s->scan_lines_per_block, s->ymax - line + 1); + s->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); + uncompressed_size = s->scan_line_size * s->ysize; if ((s->compr == EXR_RAW && (data_size != uncompressed_size || line_offset > buf_size - uncompressed_size)) || (s->compr != EXR_RAW && (data_size > uncompressed_size || @@ -324,6 +384,9 @@ static int decode_block(AVCodecContext *avctx, void *tdata, case EXR_ZIP16: ret = zip_uncompress(src, data_size, uncompressed_size, td); break; + case EXR_PXR24: + ret = pxr24_uncompress(s, src, data_size, uncompressed_size, td); + break; case EXR_RLE: ret = rle_uncompress(src, data_size, uncompressed_size, td); } @@ -646,6 +709,7 @@ static int decode_frame(AVCodecContext *avctx, case EXR_ZIP1: s->scan_lines_per_block = 1; break; + case EXR_PXR24: case EXR_ZIP16: s->scan_lines_per_block = 16; break;