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

Reply via email to