|
|
|
@ -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; |
|
|
|
|