This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository legacy-imlib2.

View the commit online.

commit e4644560f9c9d8d12e32d5ca647acfa540e5089b
Author: Chema Gonzalez <che...@meta.com>
AuthorDate: Thu Apr 11 17:52:14 2024 -0700

    Y4M loader: add support for 10-bit 4:2:0
    
    Current implementation just discards the last 2 bits.
    
    Images generated using ffmpeg:
    ```
    $ ffmpeg -i test/images/img-17x14.full_range.y4m -strict -1 -pix_fmt yuv420p10 -color_range full test/images/img-17x14.yuv420p10.full_range.y4m
    $ ffmpeg -i test/images/img-8x8.full_range.y4m -strict -1 -pix_fmt yuv420p10 -color_range full test/images/img-8x8.yuv420p10.full_range.y4m
    ```
    
    Tested:
    ```
    $ src/bin/.libs/imlib2_view test/images/img-8x8.yuv420p10.full_range.y4m
    $ feh test/images/img-8x8.yuv420p10.full_range.y4m
    ```
---
 src/modules/loaders/loader_y4m.c               |  85 +++++++++++++++++++++++--
 test/images/img-17x14.yuv420p10.full_range.y4m | Bin 0 -> 811 bytes
 test/images/img-8x8.full_range.y4m             | Bin 0 -> 251 bytes
 test/images/img-8x8.yuv420p10.full_range.y4m   | Bin 0 -> 273 bytes
 4 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/src/modules/loaders/loader_y4m.c b/src/modules/loaders/loader_y4m.c
index 89040cd..9b7873a 100644
--- a/src/modules/loaders/loader_y4m.c
+++ b/src/modules/loaders/loader_y4m.c
@@ -46,6 +46,7 @@ typedef struct {
         Y4M_PARSE_CS_422,
         Y4M_PARSE_CS_444,
         Y4M_PARSE_CS_MONO,
+        Y4M_PARSE_CS_420P10,
     } colour_space;
     enum {
         Y4M_PARSE_IL_PROGRESSIVE,
@@ -67,6 +68,7 @@ typedef struct {
         Y4M_PARSE_RANGE_LIMITED,
         Y4M_PARSE_RANGE_FULL,
     } range;
+    uint8_t         depth;      // Bit depth  (8, 10, 12, 14, 16)
 
     const void     *frame_data;
     ptrdiff_t       frame_data_len;
@@ -121,6 +123,10 @@ y4m__parse_params(Y4mParse *res, const uint8_t **start, const uint8_t *end)
     const uint8_t  *p = *start;
     const uint8_t  *peek;
 
+    // default values
+    res->range = Y4M_PARSE_RANGE_UNSPECIFIED;
+    res->depth = 8;
+
     for (;;)
     {
 #if IMLIB2_DEBUG
@@ -183,19 +189,45 @@ y4m__parse_params(Y4mParse *res, const uint8_t **start, const uint8_t *end)
         case 'C':
             res->colour_space = Y4M_PARSE_CS_UNSUPPORTED;
             if (y4m__match("mono", 4, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_MONO;
+                res->depth = 8;
+            }
             else if (y4m__match("420jpeg", 7, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_420JPEG;
+                res->depth = 8;
+            }
             else if (y4m__match("420mpeg2", 8, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_420MPEG2;
+                res->depth = 8;
+            }
             else if (y4m__match("420paldv", 8, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_420PALDV;
+                res->depth = 8;
+            }
+            else if (y4m__match("420p10", 6, &p, end))
+            {
+                res->colour_space = Y4M_PARSE_CS_420P10;
+                res->depth = 10;
+            }
             else if (y4m__match("420", 3, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_420;
+                res->depth = 8;
+            }
             else if (y4m__match("422", 3, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_422;
+                res->depth = 8;
+            }
             else if (y4m__match("444", 3, &p, end))
+            {
                 res->colour_space = Y4M_PARSE_CS_444;
+                res->depth = 8;
+            }
 
             peek = p;           /* peek to avoid falsly matching things like "420p16" */
             if (res->colour_space == Y4M_PARSE_CS_UNSUPPORTED ||
@@ -306,6 +338,7 @@ y4m_parse_frame(Y4mParse *res)
     case Y4M_PARSE_CS_420MPEG2:
     case Y4M_PARSE_CS_420PALDV:
     case Y4M_PARSE_CS_420:
+    case Y4M_PARSE_CS_420P10:
         res->frame_data_len = npixels * 3 / 2;
         sdiv = 2;
         voff = (npixels * 5) / 4;
@@ -342,8 +375,16 @@ y4m_parse_frame(Y4mParse *res)
     }
     else
     {
-        res->u = p + npixels;
-        res->v = p + voff;
+        if (res->depth == 10)
+        {
+            res->u = p + npixels * 2;
+            res->v = p + voff * 2;
+        }
+        else
+        {
+            res->u = p + npixels;
+            res->v = p + voff;
+        }
         res->u_stride = res->v_stride = res->w / sdiv;
     }
 
@@ -439,6 +480,7 @@ _load(ImlibImage *im, int load_data)
     case Y4M_PARSE_CS_420MPEG2:
     case Y4M_PARSE_CS_420PALDV:
     case Y4M_PARSE_CS_420:
+    case Y4M_PARSE_CS_420P10:
         if (y4m.range == Y4M_PARSE_RANGE_FULL)
             conv = J420ToARGB;
         else
@@ -463,8 +505,43 @@ _load(ImlibImage *im, int load_data)
     if (!__imlib_AllocateData(im))
         return LOAD_OOM;
 
-    res = conv(y4m.y, y4m.y_stride, y4m.u, y4m.u_stride, y4m.v, y4m.v_stride,
-               (uint8_t *) im->data, im->w * 4, im->w, im->h);
+    if (y4m.depth == 10 && y4m.colour_space == Y4M_PARSE_CS_420P10)
+    {
+        /* allocate a small buffer to convert image data */
+        uint8_t        *buf =
+            calloc(((y4m.w * y4m.h * 3) >> 1), sizeof(uint8_t));
+        if (!buf)
+            return LOAD_OOM;
+
+        /* convert 10-bit YUV to 8-bit YUV */
+        uint8_t        *buf_y = buf;
+        int             npixels = y4m.w * y4m.h;
+        uint8_t        *buf_u = buf + npixels;
+        int             voff = (npixels * 5) / 4;
+        uint8_t        *buf_v = buf + voff;
+        int             buf_stride_y = y4m.w;
+        ptrdiff_t       buf_stride_u;
+        ptrdiff_t       buf_stride_v;
+        int             sdiv = 2;
+        buf_stride_u = buf_stride_v = y4m.w / sdiv;
+        I010ToI420(y4m.y, y4m.y_stride, y4m.u, y4m.u_stride,
+                   y4m.v, y4m.v_stride, buf_y, buf_stride_y,
+                   buf_u, buf_stride_u, buf_v, buf_stride_v, y4m.w, y4m.h);
+
+        /* convert 8-bit YUV to 8-bit ARGB */
+        res =
+            conv(buf_y, buf_stride_y, buf_u, buf_stride_u, buf_v, buf_stride_v,
+                 (uint8_t *) im->data, im->w * 4, im->w, im->h);
+
+        free(buf);
+    }
+    else
+    {
+        res =
+            conv(y4m.y, y4m.y_stride, y4m.u, y4m.u_stride, y4m.v, y4m.v_stride,
+                 (uint8_t *) im->data, im->w * 4, im->w, im->h);
+    }
+
     if (res != 0)
         return LOAD_BADIMAGE;
 
diff --git a/test/images/img-17x14.yuv420p10.full_range.y4m b/test/images/img-17x14.yuv420p10.full_range.y4m
new file mode 100644
index 0000000..84a222b
Binary files /dev/null and b/test/images/img-17x14.yuv420p10.full_range.y4m differ
diff --git a/test/images/img-8x8.full_range.y4m b/test/images/img-8x8.full_range.y4m
new file mode 100644
index 0000000..163171a
Binary files /dev/null and b/test/images/img-8x8.full_range.y4m differ
diff --git a/test/images/img-8x8.yuv420p10.full_range.y4m b/test/images/img-8x8.yuv420p10.full_range.y4m
new file mode 100644
index 0000000..d6c5b71
Binary files /dev/null and b/test/images/img-8x8.yuv420p10.full_range.y4m differ

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to