Hello, in attach a patch to add support for Y and YA exr file (ticket #5621)
sample can be found in this ticket, https://trac.ffmpeg.org/ticket/5621 or in the official samples http://download.savannah.nongnu.org/releases/openexr/openexr-images-1.7.0.tar.gz pass exr fate test. The second patch is only indent. Comments welcome Martin Jokyo Images
From 949e4fa6571229d7253a90fdd8ca3946f8cc54ac Mon Sep 17 00:00:00 2001 From: Martin Vignali <martin.vign...@gmail.com> Date: Mon, 27 Jun 2016 23:52:39 +0200 Subject: [PATCH 1/2] libavodec/exr : add support for Y and YA file (ticket #5621) a gray channel in exr, is named Y we admit that the file need to be interpreted as gray only if no other channel match (except alpha) to manage RGB and Y in the color conversion part of decode_block, the color processing is now made with a for loop. --- libavcodec/exr.c | 103 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index c87187c..46e8312 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -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; @@ -1016,6 +1018,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; @@ -1125,9 +1128,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]; @@ -1136,11 +1145,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]; @@ -1155,37 +1166,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)); } @@ -1193,9 +1193,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)); } @@ -1279,6 +1280,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"); @@ -1346,17 +1348,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, @@ -1383,6 +1390,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", @@ -1417,6 +1425,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) { @@ -1428,6 +1437,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; @@ -1577,10 +1587,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"); -- 1.9.3 (Apple Git-50)
From 86543b18ac8a2fb355350d39f1f28bd62b4bd639 Mon Sep 17 00:00:00 2001 From: Martin Vignali <martin.vign...@gmail.com> Date: Mon, 27 Jun 2016 23:57:06 +0200 Subject: [PATCH 2/2] libavcodec/exr : indent gray support patch --- libavcodec/exr.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 46e8312..1ee613f 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1129,10 +1129,10 @@ static int decode_block(AVCodecContext *avctx, void *tdata, } 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; + 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; @@ -1363,11 +1363,12 @@ static int decode_header(EXRContext *s) !strcmp(ch_gb.buffer, "W")){ channel_index = 2; s->is_luma = 0; - } else if (!strcmp(ch_gb.buffer, "A")) + } else if (!strcmp(ch_gb.buffer, "A")) { channel_index = 3; - else + } else { av_log(s->avctx, AV_LOG_WARNING, "Unsupported channel %.256s.\n", ch_gb.buffer); + } } /* skip until you get a 0 */ @@ -1426,17 +1427,17 @@ 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) { - if (s->channel_offsets[0] < 0) - av_log(s->avctx, AV_LOG_ERROR, "Missing red channel.\n"); - if (s->channel_offsets[1] < 0) - av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n"); - if (s->channel_offsets[2] < 0) - av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n"); - return AVERROR_INVALIDDATA; - } + if (FFMIN3(s->channel_offsets[0], + s->channel_offsets[1], + s->channel_offsets[2]) < 0) { + if (s->channel_offsets[0] < 0) + av_log(s->avctx, AV_LOG_ERROR, "Missing red channel.\n"); + if (s->channel_offsets[1] < 0) + av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n"); + if (s->channel_offsets[2] < 0) + av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n"); + return AVERROR_INVALIDDATA; + } } // skip one last byte and update main gb @@ -1589,13 +1590,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, case EXR_HALF: if (s->channel_offsets[3] >= 0) { if (!s->is_luma) { - avctx->pix_fmt = AV_PIX_FMT_RGBA64; + avctx->pix_fmt = AV_PIX_FMT_RGBA64; } else { avctx->pix_fmt = AV_PIX_FMT_YA16; } } else { if (!s->is_luma) { - avctx->pix_fmt = AV_PIX_FMT_RGB48; + avctx->pix_fmt = AV_PIX_FMT_RGB48; } else { avctx->pix_fmt = AV_PIX_FMT_GRAY16; } -- 1.9.3 (Apple Git-50)
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel