URI: 
       Fix colour distortion - blind - suckless command-line video editing utility
  HTML git clone git://git.suckless.org/blind
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 4154609e5de76bc8858d3f86e0af09ba2700c488
   DIR parent 2b646382a5745b65d32e6bc66b9cf41149673c8c
  HTML Author: Mattias Andrée <maandree@kth.se>
       Date:   Sat, 23 Sep 2017 21:57:45 +0200
       
       Fix colour distortion
       
       This matrices are not convert to or from the proper YUV colour space both
       rather the ones used in videos. srgb_to_yuv was created by converting the
       image [sRGB(100%, 0, 0); sRGB(0, 100%, 0); sRGB(0, 0, 100%)] to YUV with
       FFmpeg and transposing the matrix. yuv_to_srgb is the inversion of that
       matrix, the values in the first column should all be 1 but are not due to
       rounding/truncation error.
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M TODO                                |       2 --
         M src/blind-convert.c                 |      14 +++++++++-----
         M src/blind-from-video.c              |       3 ++-
         M src/blind-to-video.c                |       4 ++--
         M src/util/colour.h                   |      70 ++++++++++++++++---------------
       
       5 files changed, 49 insertions(+), 44 deletions(-)
       ---
   DIR diff --git a/TODO b/TODO
       @@ -1,5 +1,3 @@
       -Conversion either from or to video changes the brightness of the primitives (but not greys)
       -
        blind-transform                affine transformation by matrix multiplication, -[xy] for tiling, -s for
                                        improve quality on downscaling (pixels' neighbours must not change)
        blind-apply-map                remap pixels (distortion) using the X and Y values, -[xy] for tiling, -s for
   DIR diff --git a/src/blind-convert.c b/src/blind-convert.c
       @@ -47,7 +47,7 @@ static size_t
        remove_alpha_u16(uint16_t *buf, size_t n)
        {
                size_t i, j;
       -        long int a, max = (long int)UINT16_MAX, ymax = 0xDAF4L;
       +        long int a, max = (long int)0xFF00L, ymax = 0xDAF4L;
                for (i = j = 0; i < n; i += 4, j += 3) {
                        a = (long int)(buf[i + 3]);
                        buf[j + 0] = (uint16_t)(((long int)(buf[i + 0]) - 0x1001L) * a / ymax + 0x1001L);
       @@ -108,19 +108,23 @@ raw1_to_raw0(uint16_t *buf, size_t n)
        #define RAW2_TO_RAW3(TYPE, WITH_ALPHA)\
                do {\
                        size_t i;\
       -                TYPE max = (TYPE)UINT16_MAX, ymax = (TYPE)0xDAF4;\
       +                TYPE max = (TYPE)0xFF00L, ymax = (TYPE)0xDAF4L;\
                        if (sizeof(*in) > sizeof(*out)) {\
                                for (i = 0; i < n; i += 3 + WITH_ALPHA) {\
                                        out[i + 0] = (TYPE)((long int)(in[i + 0]) - 0x1001L) / ymax;\
                                        out[i + 1] = (TYPE)((long int)(in[i + 1]) - 0x8000L) /  max;\
                                        out[i + 2] = (TYPE)((long int)(in[i + 2]) - 0x8000L) /  max;\
       -                                if (WITH_ALPHA)\
       +                                if (WITH_ALPHA) {\
                                                out[i + 3] = (TYPE)(in[i + 3]) / max;\
       +                                        out[i + 3] = CLIP(0, out[i + 3], 1);\
       +                                }\
                                }\
                        } else {\
                                for (i = n; i; i -= 3 + WITH_ALPHA) {\
       -                                if (WITH_ALPHA)\
       +                                if (WITH_ALPHA) {\
                                                out[i - 1] = (TYPE)(in[i - 1]) / max;\
       +                                        out[i - 1] = CLIP(0, out[i - 1], 1);\
       +                                }\
                                        out[i - 1 - WITH_ALPHA] = (TYPE)((long int)(in[i - 1 - WITH_ALPHA]) - 0x8000L) /  max;\
                                        out[i - 2 - WITH_ALPHA] = (TYPE)((long int)(in[i - 2 - WITH_ALPHA]) - 0x8000L) /  max;\
                                        out[i - 3 - WITH_ALPHA] = (TYPE)((long int)(in[i - 3 - WITH_ALPHA]) - 0x1001L) / ymax;\
       @@ -136,7 +140,7 @@ static void raw2a_to_raw3a_f (uint16_t *in, float  *out, size_t n) { RAW2_TO_RAW
        #define RAW3_TO_RAW2(TYPE, WITH_ALPHA)\
                do {\
                        size_t i;\
       -                TYPE max = (TYPE)UINT16_MAX, ymax = (TYPE)0xDAF4;\
       +                TYPE max = (TYPE)0xFF00L, ymax = (TYPE)0xDAF4L;\
                        long int y, u, v;\
                        if (sizeof(*in) > sizeof(*out)) {\
                                for (i = 0; i < n; i += 3 + WITH_ALPHA) {\
   DIR diff --git a/src/blind-from-video.c b/src/blind-from-video.c
       @@ -75,7 +75,7 @@ get_metadata(char *file, size_t *width, size_t *height)
                do {\
                        typedef TYPE pixel_t[4];\
                        size_t i, ptr;\
       -                TYPE y, u, v, max = (TYPE)UINT16_MAX, ymax = (TYPE)0xDAF4;\
       +                TYPE y, u, v, max = (TYPE)0xFF00L, ymax = (TYPE)0xDAF4L;\
                        TYPE r, g, b;\
                        pixel_t pixels[1024];\
                        uint16_t *pix;\
       @@ -97,6 +97,7 @@ get_metadata(char *file, size_t *width, size_t *height)
                                for (ptr = i = 0; ptr < n; ptr += 8) {\
                                        pix = (uint16_t *)(buf + ptr);\
                                        pixels[i][3] = le16toh(pix[0]) / max;\
       +                                pixels[i][3] = CLIP(0, pixels[i][3], 1);\
                                        y = (TYPE)((long int)le16toh(pix[1]) - 0x1001L) / ymax;\
                                        u = (TYPE)((long int)le16toh(pix[2]) - 0x8000L) / max;\
                                        v = (TYPE)((long int)le16toh(pix[3]) - 0x8000L) / max;\
   DIR diff --git a/src/blind-to-video.c b/src/blind-to-video.c
       @@ -119,8 +119,8 @@ PROCESS(struct stream *stream, size_t n)
                                b = srgb_encode(b);
                                srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2);
                                y = (long int)(pixel[0] * 0xDAF4L) + 0x1001L;
       -                        u = (long int)(pixel[1] * 0xFFFFL) + 0x8000L;
       -                        v = (long int)(pixel[2] * 0xFFFFL) + 0x8000L;
       +                        u = (long int)(pixel[1] * 0xFF00L) + 0x8000L;
       +                        v = (long int)(pixel[2] * 0xFF00L) + 0x8000L;
                                *pixels++ = htole((uint16_t)CLIP(0, a, 0xFFFFL));
                                *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL));
                                *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL));
   DIR diff --git a/src/util/colour.h b/src/util/colour.h
       @@ -57,24 +57,26 @@ SRGB_DECODE(float, _f, f)
                MATRIX_MULTIPLY_FUNCTION(FUNCTION_BASE##_f, float,  __VA_ARGS__)
        
        MATRIX_MULTIPLY_FUNCTIONS(yuv_to_srgb,
       -                          1,
       -                          0.00028328010485821202317155420580263580632163211703,
       -                          1.14070449590558520291949662350816652178764343261719,
       -                          1,
       -                          -0.39630886669497211727275498560629785060882568359375,
       -                          -0.58107364288228224857846271333983168005943298339844,
       -                          1,
       -                          2.03990003507541306504435851820744574069976806640625,
       -                          0.00017179031692307700847528739718228507626918144524)
       +                           0.99983946058747896756813133833929896354675292968750,
       +                          -0.00111314629257774910797706979792565107345581054688,
       +                           1.59561960249794831945280293439282104372978210449219,
       +                           0.99983946058762285247212275862693786621093750000000,
       +                          -0.39124374513994553126394748687744140625000000000000,
       +                          -0.81304201036561862814266987697919830679893493652344,
       +                           0.99983946058757433572594663928612135350704193115234,
       +                           2.01741786772377817982260239659808576107025146484375,
       +                           0.00115819721926166407932612401054939255118370056152)
        
        MATRIX_MULTIPLY_FUNCTIONS(srgb_to_yuv,
       -                          0.299, 0.587, 0.114,
       -                          -0.14662756598240470062854967636667424812912940979004,
       -                          -0.28771586836102963635752871596196200698614120483398,
       -                           0.43434343434343436474165400795754976570606231689453,
       -                           0.61456892577224520035628074765554629266262054443359,
       -                          -0.51452282157676354490405401520547457039356231689453,
       -                          -0.10004610419548178035231700278018251992762088775635)
       +                           0.29906158567044888174635275390755850821733474731445,
       +                           0.58707985442089483107963587826816365122795104980469,
       +                           0.11401912509812317519930502385250292718410491943359,
       +                          -0.14846813725490196067546833091910229995846748352051,
       +                          -0.29074754901960786490633381617954000830650329589844,
       +                           0.43921568627450979782622653146972879767417907714844,
       +                           0.43921568627450979782622653146972879767417907714844,
       +                          -0.36807598039215688734415721228288020938634872436523,
       +                          -0.07113970588235293823764493481576209887862205505371)
        
        MATRIX_MULTIPLY_FUNCTIONS(ciexyz_to_srgb,
                                   3.240446254647737500675930277794,
       @@ -99,26 +101,26 @@ MATRIX_MULTIPLY_FUNCTIONS(srgb_to_ciexyz,
                                  0.950302838552371742508739771438)
        
        MATRIX_MULTIPLY_FUNCTIONS(scaled_yuv_to_ciexyz,
       -                           0.00001450325106667098632156481796684488472237717360 / 0.8552986953536278,
       -                           0.00000345586790639342739093228633329157872822179343,
       -                           0.00000400923398630552893485111398685916128670214675,
       -                           0.00001525902189669641837040624243737596543724066578 / 0.8552986953536278,
       -                          -0.00000207722814409390653614547427030512238843584782,
       -                          -0.00000263898607692305410302407824019166326934282552,
       -                           0.00001661446153041708825425643025752719950105529279 / 0.8552986953536278,
       -                           0.00002885925752619118069149627137104374696718878113,
       -                          -0.00000071781086875769179526501342566979779746816348)
       +                           0.00001450092272326647052454150210731853576362482272 / 0.8552986953536278,
       +                           0.00000341281577174185336742326911385614351956974133,
       +                           0.00000560936853511406815494611324823814868523186306,
       +                           0.00001525657222228693664302541510569000138275441714 / 0.8552986953536278,
       +                          -0.00000205124661398017884712786061685019234346327721,
       +                          -0.00000369297336083484072815404791745308443751127925,
       +                           0.00001661179425452522781048517175328527173405745998 / 0.8552986953536278,
       +                           0.00002854205077959434113873959937279778387164697051,
       +                          -0.00000099119265445913120730111588868593841539222922)
        
        MATRIX_MULTIPLY_FUNCTIONS(ciexyz_to_scaled_yuv,
       -                            26625.38231027395886485464870929718017578125   * 0.8552986953536278,
       -                            40524.0090949436053051613271236419677734375    * 0.8552986953536278,
       -                             -271.5313105642117079696618020534515380859375 * 0.8552986953536278,
       -                           -11278.3751445417292416095733642578125,
       -                           -26409.91773157499847002327442169189453125,
       -                            34100.5706543184860493056476116180419921875,
       -                           162829.60100012840121053159236907958984375,
       -                          -123829.313212639070115983486175537109375,
       -                           -28411.65702312920984695665538311004638671875)
       +                           26633.45812403910895227454602718353271484375   * 0.8552986953536278,
       +                           40527.367131481194519437849521636962890625     * 0.8552986953536278,
       +                            -272.0008243176007454167120158672332763671875 * 0.8552986953536278,
       +                          -11458.90154486896426533348858356475830078125,
       +                          -26662.3801805758339469321072101593017578125,
       +                           34490.0235254608633113093674182891845703125,
       +                          116394.099928013441967777907848358154296875,
       +                          -88546.58492295184987597167491912841796875,
       +                          -20281.0410136536011123098433017730712890625)
        
        #undef MATRIX_MULTIPLY_FUNCTIONS
        #undef MATRIX_MULTIPLY_FUNCTION