libswscale: Adding RGB => XYZ support
authorclook <build@localhost.localdomain>
Sun, 14 Jul 2013 03:30:38 +0000 (03:30 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 22 Jul 2013 23:02:41 +0000 (01:02 +0200)
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/utils.c
tests/ref/fate/filter-pixdesc
tests/ref/fate/filter-pixfmts-copy
tests/ref/fate/filter-pixfmts-crop
tests/ref/fate/filter-pixfmts-field
tests/ref/fate/filter-pixfmts-hflip
tests/ref/fate/filter-pixfmts-il
tests/ref/fate/filter-pixfmts-null
tests/ref/fate/filter-pixfmts-scale

index cec4288..6721dc3 100644 (file)
@@ -849,6 +849,62 @@ static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst,
     }
 }
 
+static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst,
+                         const uint16_t *src, int stride, int h)
+{
+    int xp,yp;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+
+    for (yp=0; yp<h; yp++) {
+        for (xp=0; xp+2<stride; xp+=3) {
+            int x, y, z, r, g, b;
+
+            if (desc->flags & AV_PIX_FMT_FLAG_BE) {
+                r = AV_RB16(src + xp + 0);
+                g = AV_RB16(src + xp + 1);
+                b = AV_RB16(src + xp + 2);
+            } else {
+                r = AV_RL16(src + xp + 0);
+                g = AV_RL16(src + xp + 1);
+                b = AV_RL16(src + xp + 2);
+            }
+
+            r = c->rgbgammainv[r>>4];
+            g = c->rgbgammainv[g>>4];
+            b = c->rgbgammainv[b>>4];
+
+            // convert from sRGBlinear to XYZlinear
+            x = c->rgb2xyz_matrix[0][0] * r +
+                c->rgb2xyz_matrix[0][1] * g +
+                c->rgb2xyz_matrix[0][2] * b >> 12;
+            y = c->rgb2xyz_matrix[1][0] * r +
+                c->rgb2xyz_matrix[1][1] * g +
+                c->rgb2xyz_matrix[1][2] * b >> 12;
+            z = c->rgb2xyz_matrix[2][0] * r +
+                c->rgb2xyz_matrix[2][1] * g +
+                c->rgb2xyz_matrix[2][2] * b >> 12;
+
+            // limit values to 12-bit depth
+            x = av_clip_c(x,0,4095);
+            y = av_clip_c(y,0,4095);
+            z = av_clip_c(z,0,4095);
+
+            // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
+            if (desc->flags & AV_PIX_FMT_FLAG_BE) {
+                AV_WB16(dst + xp + 0, c->xyzgammainv[x] << 4);
+                AV_WB16(dst + xp + 1, c->xyzgammainv[y] << 4);
+                AV_WB16(dst + xp + 2, c->xyzgammainv[z] << 4);
+            } else {
+                AV_WL16(dst + xp + 0, c->xyzgammainv[x] << 4);
+                AV_WL16(dst + xp + 1, c->xyzgammainv[y] << 4);
+                AV_WL16(dst + xp + 2, c->xyzgammainv[z] << 4);
+            }
+        }
+        src += stride;
+        dst += stride;
+    }
+}
+
 /**
  * swscale wrapper, so we don't need to export the SwsContext.
  * Assumes planar YUV to be in YUV order instead of YVU.
@@ -1045,6 +1101,12 @@ int attribute_align_arg sws_scale(struct SwsContext *c,
                           srcSliceH, dst2, dstStride2);
     }
 
+
+    if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
+        /* replace on the same data */
+        rgb48Toxyz12(c, (uint16_t*)dst2[0], (const uint16_t*)dst2[0], dstStride[0]/2, ret);
+    }
+
     av_free(rgb0_tmp);
     return ret;
 }
index 02214f3..e7cc26e 100644 (file)
@@ -484,7 +484,10 @@ typedef struct SwsContext {
 #define RGB_GAMMA (2.2f)
     int16_t *xyzgamma;
     int16_t *rgbgamma;
+    int16_t *xyzgammainv;
+    int16_t *rgbgammainv;
     int16_t xyz2rgb_matrix[3][4];
+    int16_t rgb2xyz_matrix[3][4];
 
     /* function pointers for swScale() */
     yuv2planar1_fn yuv2plane1;
index 59bf49a..00308e1 100644 (file)
@@ -201,8 +201,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
     [AV_PIX_FMT_GBRP14BE]    = { 1, 1 },
     [AV_PIX_FMT_GBRP16LE]    = { 1, 0 },
     [AV_PIX_FMT_GBRP16BE]    = { 1, 0 },
-    [AV_PIX_FMT_XYZ12BE]     = { 1, 0, 1 },
-    [AV_PIX_FMT_XYZ12LE]     = { 1, 0, 1 },
+    [AV_PIX_FMT_XYZ12BE]     = { 1, 1, 1 },
+    [AV_PIX_FMT_XYZ12LE]     = { 1, 1, 1 },
     [AV_PIX_FMT_GBRAP]       = { 1, 1 },
     [AV_PIX_FMT_GBRAP16LE]   = { 1, 0 },
     [AV_PIX_FMT_GBRAP16BE]   = { 1, 0 },
@@ -924,15 +924,24 @@ static void fill_xyztables(struct SwsContext *c)
     int i;
     double xyzgamma = XYZ_GAMMA;
     double rgbgamma = 1.0 / RGB_GAMMA;
+    double xyzgammainv = 1.0 / XYZ_GAMMA;
+    double rgbgammainv = RGB_GAMMA;
     static const int16_t xyz2rgb_matrix[3][4] = {
         {13270, -6295, -2041},
         {-3969,  7682,   170},
         {  228,  -835,  4329} };
-    static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096];
+    static const int16_t rgb2xyz_matrix[3][4] = {
+        {1689, 1464,  739},
+        { 871, 2929,  296},
+        {  79,  488, 3891} };
+    static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096], xyzgammainv_tab[4096], rgbgammainv_tab[4096];
 
     memcpy(c->xyz2rgb_matrix, xyz2rgb_matrix, sizeof(c->xyz2rgb_matrix));
+    memcpy(c->rgb2xyz_matrix, rgb2xyz_matrix, sizeof(c->rgb2xyz_matrix));
     c->xyzgamma = xyzgamma_tab;
     c->rgbgamma = rgbgamma_tab;
+    c->xyzgammainv = xyzgammainv_tab;
+    c->rgbgammainv = rgbgammainv_tab;
 
     if (rgbgamma_tab[4095])
         return;
@@ -941,6 +950,8 @@ static void fill_xyztables(struct SwsContext *c)
     for (i = 0; i < 4096; i++) {
         xyzgamma_tab[i] = lrint(pow(i / 4095.0, xyzgamma) * 4095.0);
         rgbgamma_tab[i] = lrint(pow(i / 4095.0, rgbgamma) * 4095.0);
+        xyzgammainv_tab[i] = lrint(pow(i / 4095.0, xyzgammainv) * 4095.0);
+        rgbgammainv_tab[i] = lrint(pow(i / 4095.0, rgbgammainv) * 4095.0);
     }
 }
 
index ccbbbc3..94e4bfb 100644 (file)
@@ -48,6 +48,8 @@ rgba                53796fa4c392a1b2659595b6a284f8c4
 rgba64be            c05fbb1ada1b48fb1eb192fc200af2b6
 rgba64le            1b826cc613666f545274e8a7799d69f1
 uyvy422             3f411f947e3ac8f842c88e717d68bd9a
+xyz12be             71f608adceed8e8997aa463203b1a648
+xyz12le             dc524e3726ba1df0d2f406db3a2c08aa
 yuv410p             7dcf3f4770c8b494290ceacd2c2ce6db
 yuv411p             9461b188dab6f8b90d9a27e353a89f58
 yuv420p             61fffd2d8425759a33ae07e718d0242d
index 6a82855..0c3ce68 100644 (file)
@@ -49,8 +49,8 @@ rgba                53796fa4c392a1b2659595b6a284f8c4
 rgba64be            c05fbb1ada1b48fb1eb192fc200af2b6
 rgba64le            1b826cc613666f545274e8a7799d69f1
 uyvy422             3f411f947e3ac8f842c88e717d68bd9a
-xyz12be             e1e6718ae1c83e904fbdf903d62e5808
-xyz12le             24e8a22c1bd7d637edb731d10b7c54d0
+xyz12be             b91ff224254afceb4a8f803d56eb52a1
+xyz12le             dc524e3726ba1df0d2f406db3a2c08aa
 yuv410p             7dcf3f4770c8b494290ceacd2c2ce6db
 yuv411p             9461b188dab6f8b90d9a27e353a89f58
 yuv420p             61fffd2d8425759a33ae07e718d0242d
index 6298374..4c2e4e8 100644 (file)
@@ -46,8 +46,8 @@ rgb8                87cf541b110e35a6f9a983e9cde85e15
 rgba                7abe1af7b97f5b9a7aa5ad3e4bf32f76
 rgba64be            2eed28b61af25790c02cc658e5f86b9b
 rgba64le            de8bc34c6d573488d87e87ce8c7ad07f
-xyz12be             1de64f52c6e2e7ff0b5da20c78910304
-xyz12le             f7b79cf87ad69dfc24056468e6dffaea
+xyz12be             7ea4ce13143195dfe1ed340bc9e86b2f
+xyz12le             e4e86ef100e07cda561a22811f242e5d
 yuv410p             126e0da1da4fd89be28087b8367bbb36
 yuv411p             b94f0af107fc4796aca70c0a36d374c5
 yuv420p             74c6b331bd30f005e6c75a192423ad90
index e66d4df..db37201 100644 (file)
@@ -49,8 +49,8 @@ rgba                d0ebdf1495bc6b7e9d3bfbe2813a9d16
 rgba64be            53363baf266592e0ac02b3f8242ec4fb
 rgba64le            a630eaa38545b2be741f000ab58451e5
 uyvy422             a6a52504a16f09b8f2ec2405bc8190b5
-xyz12be             9d904fb640dd024e668acb9dc7b3f11f
-xyz12le             7f93c7d2981f1976108e941afa1363f8
+xyz12be             33d0b7ef124a9e94d2d13a2cad1dfc00
+xyz12le             bab6403abf58e69575900802ffef8f38
 yuv410p             3feb55b1e2a385b488c82e808a12587b
 yuv411p             ab3dd8e6cf1452afe2d2e976e4726370
 yuv420p             52e26ad198368e2326bef97cdfa6a2bb
index 4d08d7e..12d7548 100644 (file)
@@ -46,8 +46,8 @@ rgb8                22fdbd14ce296c1afa9bb4a6ea09b3fe
 rgba                a37789c4df73c3bd8648ad1fe9d3f991
 rgba64be            286067334e4bca33fba7ebb1706890a2
 rgba64le            2a8b3dd5045df299259636d8e6b62589
-xyz12be             4738d2cb5321376d5eed70930f47a953
-xyz12le             51288f3440c8584406b332545d69c5a9
+xyz12be             079dac329f0d93df7a7e71b260f13dd9
+xyz12le             31c4f953548326b27920c5939bcf2cce
 yuv410p             a1280c2b9b562dba3c2d35a1e5fc4b23
 yuv411p             6bf10756ac5c7841db63a97106ff911b
 yuv420p             45f4a06481f2cd8e28fb29c7c151e110
index f48df9e..64d0475 100644 (file)
@@ -48,8 +48,8 @@ rgba                8ca9c8db589615ebbaa964be4ce62d08
 rgba64be            576dfc2fd1937f9e594c4004fafd83f2
 rgba64le            7938eccc1f05f13710ec351767b47a36
 uyvy422             8be40aded4b407ff66305911ba5ce2ce
-xyz12be             1cbb1f72c6875934e66f50f499a62cc3
-xyz12le             ba8c6eab49e58eace392ef0aeedbf677
+xyz12be             ba8a8152ca6e8b338e1dc5ace0a729b6
+xyz12le             1f20849dcf44539ce351346c73bdff1a
 yuv410p             92112d85ba4f74cbd3044945c0f33402
 yuv411p             b6b22000e5275c92baf5afc417c32a70
 yuv420p             fca7fbbff753612a718ee13e1dfe2af2
index 6a82855..0c3ce68 100644 (file)
@@ -49,8 +49,8 @@ rgba                53796fa4c392a1b2659595b6a284f8c4
 rgba64be            c05fbb1ada1b48fb1eb192fc200af2b6
 rgba64le            1b826cc613666f545274e8a7799d69f1
 uyvy422             3f411f947e3ac8f842c88e717d68bd9a
-xyz12be             e1e6718ae1c83e904fbdf903d62e5808
-xyz12le             24e8a22c1bd7d637edb731d10b7c54d0
+xyz12be             b91ff224254afceb4a8f803d56eb52a1
+xyz12le             dc524e3726ba1df0d2f406db3a2c08aa
 yuv410p             7dcf3f4770c8b494290ceacd2c2ce6db
 yuv411p             9461b188dab6f8b90d9a27e353a89f58
 yuv420p             61fffd2d8425759a33ae07e718d0242d
index 4ec78c9..116158a 100644 (file)
@@ -49,8 +49,8 @@ rgba                de6a65b8c01bdad84e575202ca8b66a0
 rgba64be            5ce6f591ac8be4edcf5c3350d2d2d3f5
 rgba64le            12baab5162019de2053db39a3bfca868
 uyvy422             479105bc4c7fbb4a33ca8745aa8c2de8
-xyz12be             e9be06091b6dd0b67598eaf8bd86a78e
-xyz12le             05a9bbd16d81183ef3db04447648e3b1
+xyz12be             6769a0b3b3b6d7a674542c8cd3e3644e
+xyz12le             b4f967df71db5c38c222f9236c341031
 yuv410p             d0daa93f5cee83360e219e39563ab6da
 yuv411p             e5c8f3ca024a88dd07e0a92db3e2133d
 yuv420p             485d9af8608f926ffffbf42230b4150d