|
@@ -129,6 +129,8 @@ typedef struct EXRContext {
|
|
|
EXRTileAttribute tile_attr; /* header data attribute of tile */
|
|
|
int is_tile; /* 0 if scanline, 1 if tile */
|
|
|
|
|
|
+ int is_luma;/* 1 if there is an Y plane */
|
|
|
+
|
|
|
GetByteContext gb;
|
|
|
const uint8_t *buf;
|
|
|
int buf_size;
|
|
@@ -1033,6 +1035,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
|
|
|
int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; /* nb pixel to add at the right of the datawindow */
|
|
|
int bxmin = s->xmin * 2 * s->desc->nb_components; /* nb pixel to add at the left of the datawindow */
|
|
|
int i, x, buf_size = s->buf_size;
|
|
|
+ int c, rgb_channel_count;
|
|
|
float one_gamma = 1.0f / s->gamma;
|
|
|
avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type);
|
|
|
int ret;
|
|
@@ -1142,9 +1145,15 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
|
|
|
src = td->uncompressed_data;
|
|
|
}
|
|
|
|
|
|
+ if (!s->is_luma) {
|
|
|
channel_buffer[0] = src + td->xsize * s->channel_offsets[0];
|
|
|
channel_buffer[1] = src + td->xsize * s->channel_offsets[1];
|
|
|
channel_buffer[2] = src + td->xsize * s->channel_offsets[2];
|
|
|
+ rgb_channel_count = 3;
|
|
|
+ } else { /* put y data in the first channel_buffer */
|
|
|
+ channel_buffer[0] = src + td->xsize * s->channel_offsets[1];
|
|
|
+ rgb_channel_count = 1;
|
|
|
+ }
|
|
|
if (s->channel_offsets[3] >= 0)
|
|
|
channel_buffer[3] = src + td->xsize * s->channel_offsets[3];
|
|
|
|
|
@@ -1153,11 +1162,13 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
|
|
|
for (i = 0;
|
|
|
i < td->ysize; i++, ptr += p->linesize[0]) {
|
|
|
|
|
|
- const uint8_t *r, *g, *b, *a;
|
|
|
+ const uint8_t * a;
|
|
|
+ const uint8_t *rgb[3];
|
|
|
+
|
|
|
+ for (c = 0; c < rgb_channel_count; c++){
|
|
|
+ rgb[c] = channel_buffer[c];
|
|
|
+ }
|
|
|
|
|
|
- r = channel_buffer[0];
|
|
|
- g = channel_buffer[1];
|
|
|
- b = channel_buffer[2];
|
|
|
if (channel_buffer[3])
|
|
|
a = channel_buffer[3];
|
|
|
|
|
@@ -1172,37 +1183,26 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
|
|
|
if (trc_func) {
|
|
|
for (x = 0; x < td->xsize; x++) {
|
|
|
union av_intfloat32 t;
|
|
|
- t.i = bytestream_get_le32(&r);
|
|
|
- t.f = trc_func(t.f);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
-
|
|
|
- t.i = bytestream_get_le32(&g);
|
|
|
- t.f = trc_func(t.f);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
|
|
|
- t.i = bytestream_get_le32(&b);
|
|
|
- t.f = trc_func(t.f);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
+ for (c = 0; c < rgb_channel_count; c++) {
|
|
|
+ t.i = bytestream_get_le32(&rgb[c]);
|
|
|
+ t.f = trc_func(t.f);
|
|
|
+ *ptr_x++ = exr_flt2uint(t.i);
|
|
|
+ }
|
|
|
if (channel_buffer[3])
|
|
|
*ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
|
|
|
}
|
|
|
} else {
|
|
|
for (x = 0; x < td->xsize; x++) {
|
|
|
union av_intfloat32 t;
|
|
|
- t.i = bytestream_get_le32(&r);
|
|
|
- if (t.f > 0.0f) /* avoid negative values */
|
|
|
- t.f = powf(t.f, one_gamma);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
-
|
|
|
- t.i = bytestream_get_le32(&g);
|
|
|
- if (t.f > 0.0f)
|
|
|
- t.f = powf(t.f, one_gamma);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
-
|
|
|
- t.i = bytestream_get_le32(&b);
|
|
|
- if (t.f > 0.0f)
|
|
|
- t.f = powf(t.f, one_gamma);
|
|
|
- *ptr_x++ = exr_flt2uint(t.i);
|
|
|
+
|
|
|
+ for (int c = 0; c < rgb_channel_count; c++) {
|
|
|
+ t.i = bytestream_get_le32(&rgb[c]);
|
|
|
+ if (t.f > 0.0f) /* avoid negative values */
|
|
|
+ t.f = powf(t.f, one_gamma);
|
|
|
+ *ptr_x++ = exr_flt2uint(t.i);
|
|
|
+ }
|
|
|
+
|
|
|
if (channel_buffer[3])
|
|
|
*ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
|
|
|
}
|
|
@@ -1210,9 +1210,10 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
|
|
|
} else {
|
|
|
// 16-bit
|
|
|
for (x = 0; x < td->xsize; x++) {
|
|
|
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&r)];
|
|
|
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&g)];
|
|
|
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&b)];
|
|
|
+ for (int c = 0; c < rgb_channel_count; c++) {
|
|
|
+ *ptr_x++ = s->gamma_table[bytestream_get_le16(&rgb[c])];
|
|
|
+ }
|
|
|
+
|
|
|
if (channel_buffer[3])
|
|
|
*ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a));
|
|
|
}
|
|
@@ -1296,6 +1297,7 @@ static int decode_header(EXRContext *s)
|
|
|
s->tile_attr.xSize = -1;
|
|
|
s->tile_attr.ySize = -1;
|
|
|
s->is_tile = 0;
|
|
|
+ s->is_luma = 0;
|
|
|
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 10) {
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n");
|
|
@@ -1363,17 +1365,22 @@ static int decode_header(EXRContext *s)
|
|
|
if (layer_match) { /* only search channel if the layer match is valid */
|
|
|
if (!strcmp(ch_gb.buffer, "R") ||
|
|
|
!strcmp(ch_gb.buffer, "X") ||
|
|
|
- !strcmp(ch_gb.buffer, "U"))
|
|
|
+ !strcmp(ch_gb.buffer, "U")) {
|
|
|
channel_index = 0;
|
|
|
- else if (!strcmp(ch_gb.buffer, "G") ||
|
|
|
- !strcmp(ch_gb.buffer, "Y") ||
|
|
|
- !strcmp(ch_gb.buffer, "V"))
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!strcmp(ch_gb.buffer, "G") ||
|
|
|
+ !strcmp(ch_gb.buffer, "V")) {
|
|
|
channel_index = 1;
|
|
|
- else if (!strcmp(ch_gb.buffer, "B") ||
|
|
|
- !strcmp(ch_gb.buffer, "Z") ||
|
|
|
- !strcmp(ch_gb.buffer, "W"))
|
|
|
- channel_index = 2;
|
|
|
- else if (!strcmp(ch_gb.buffer, "A"))
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!strcmp(ch_gb.buffer, "Y")) {
|
|
|
+ channel_index = 1;
|
|
|
+ s->is_luma = 1;
|
|
|
+ } else if (!strcmp(ch_gb.buffer, "B") ||
|
|
|
+ !strcmp(ch_gb.buffer, "Z") ||
|
|
|
+ !strcmp(ch_gb.buffer, "W")){
|
|
|
+ channel_index = 2;
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!strcmp(ch_gb.buffer, "A"))
|
|
|
channel_index = 3;
|
|
|
else
|
|
|
av_log(s->avctx, AV_LOG_WARNING,
|
|
@@ -1400,6 +1407,7 @@ static int decode_header(EXRContext *s)
|
|
|
bytestream2_skip(&ch_gb, 4);
|
|
|
xsub = bytestream2_get_le32(&ch_gb);
|
|
|
ysub = bytestream2_get_le32(&ch_gb);
|
|
|
+
|
|
|
if (xsub != 1 || ysub != 1) {
|
|
|
avpriv_report_missing_feature(s->avctx,
|
|
|
"Subsampling %dx%d",
|
|
@@ -1434,6 +1442,7 @@ static int decode_header(EXRContext *s)
|
|
|
|
|
|
/* Check if all channels are set with an offset or if the channels
|
|
|
* are causing an overflow */
|
|
|
+ if (!s->is_luma){/* if we expected to have at least 3 channels */
|
|
|
if (FFMIN3(s->channel_offsets[0],
|
|
|
s->channel_offsets[1],
|
|
|
s->channel_offsets[2]) < 0) {
|
|
@@ -1445,6 +1454,7 @@ static int decode_header(EXRContext *s)
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n");
|
|
|
return AVERROR_INVALIDDATA;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
// skip one last byte and update main gb
|
|
|
s->gb.buffer = ch_gb.buffer + 1;
|
|
@@ -1594,10 +1604,19 @@ static int decode_frame(AVCodecContext *avctx, void *data,
|
|
|
switch (s->pixel_type) {
|
|
|
case EXR_FLOAT:
|
|
|
case EXR_HALF:
|
|
|
- if (s->channel_offsets[3] >= 0)
|
|
|
+ if (s->channel_offsets[3] >= 0) {
|
|
|
+ if (!s->is_luma) {
|
|
|
avctx->pix_fmt = AV_PIX_FMT_RGBA64;
|
|
|
- else
|
|
|
+ } else {
|
|
|
+ avctx->pix_fmt = AV_PIX_FMT_YA16;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!s->is_luma) {
|
|
|
avctx->pix_fmt = AV_PIX_FMT_RGB48;
|
|
|
+ } else {
|
|
|
+ avctx->pix_fmt = AV_PIX_FMT_GRAY16;
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
case EXR_UINT:
|
|
|
avpriv_request_sample(avctx, "32-bit unsigned int");
|