blind-set-luma.c - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       blind-set-luma.c (3592B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #ifndef TYPE
            3 #include "common.h"
            4 
            5 USAGE("luma-stream")
            6 
            7 #define FILE "blind-set-luma.c"
            8 #include "define-functions.h"
            9 
           10 int
           11 main(int argc, char *argv[])
           12 {
           13         struct stream colour, luma;
           14         void (*process)(struct stream *colour, struct stream *luma, size_t n);
           15 
           16         UNOFLAGS(argc != 1);
           17 
           18         eopen_stream(&colour, NULL);
           19         eopen_stream(&luma, argv[0]);
           20 
           21         SELECT_PROCESS_FUNCTION(&colour);
           22         CHECK_CHANS(&colour, == 3, == 1);
           23         CHECK_COLOUR_SPACE(&colour, CIEXYZ);
           24 
           25         fprint_stream_head(stdout, &colour);
           26         efflush(stdout, "<stdout>");
           27         process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process);
           28         return 0;
           29 }
           30 
           31 #else
           32 
           33 static void
           34 PROCESS(struct stream *colour, struct stream *luma, size_t n)
           35 {\
           36         size_t i;
           37         TYPE a, y;
           38         for (i = 0; i < n; i += colour->pixel_size) {
           39                 a = ((TYPE *)(luma->buf + i))[1];
           40                 a *= ((TYPE *)(luma->buf + i))[3];
           41                 y = ((TYPE *)(colour->buf + i))[1];
           42                 ((TYPE *)(colour->buf + i))[0] += y * a - y;
           43                 ((TYPE *)(colour->buf + i))[1]  = y * a;
           44                 ((TYPE *)(colour->buf + i))[2] += y * a - y;
           45                 /*
           46                  * Note, this changes the luma only, not the saturation,
           47                  * so the result may look a bit weird. To change both
           48                  * you can use `blind-arithm mul`.
           49                  * 
           50                  * Explaination of algorithm:
           51                  * 
           52                  *   Y is the luma, but (X, Z) is not the chroma,
           53                  *   but in CIELAB, L* is the luma and (a*, *b) is
           54                  *   the chroma. Multiplying
           55                  *   
           56                  *      ⎛0 1   0⎞
           57                  *      ⎜1 −1  0⎟
           58                  *      ⎝0  1 −1⎠
           59                  *   
           60                  *   (X Y Z)' gives a colour model similar to
           61                  *   CIE L*a*b*: a model where each parameter is
           62                  *   a linear transformation of the corresponding
           63                  *   parameter in CIE L*a*b*. The inverse of that
           64                  *   matrix is
           65                  *   
           66                  *      ⎛1 1  0⎞
           67                  *      ⎜1 0  0⎟
           68                  *      ⎝0 0 −1⎠
           69                  *   
           70                  *   and
           71                  *   
           72                  *      ⎛1 1  0⎞⎛a 0 0⎞⎛0 1   0⎞   ⎛1 a−1 0⎞
           73                  *      ⎜1 0  0⎟⎜0 1 0⎟⎜1 −1  0⎟ = ⎜0  a  0⎟.
           74                  *      ⎝0 0 −1⎠⎝0 0 1⎠⎝0  1 −1⎠   ⎝0 a−1 1⎠
           75                  * 
           76                  * Explanation of why changing only the luma looks weird:
           77                  * 
           78                  *   Consider when you are workings with colours,
           79                  *   when you want to change the brightness of a
           80                  *   colour, you multiply all parameters: red, green,
           81                  *   and blue, with the same value (this is however
           82                  *   only an approximation in most cases, since you
           83                  *   are usually usally working with colours that
           84                  *   have the sRGB transfer function applied to their
           85                  *   parameters). This action is the same in all
           86                  *   colour models and colour spaces that are a
           87                  *   linear transformation of the sRGB colour spaces
           88                  *   (sans transfer function); this is simply because
           89                  *   of the properties of linear transformations.
           90                  * 
           91                  *   The reason you change brightness this way can
           92                  *   be explained by how objects reflect colour.
           93                  *   Objects can only reject colours that are present
           94                  *   in the light source. A ideal white object will look
           95                  *   pure red if the light sources is ideal red, and a
           96                  *   a ideal blue object will pure black in the same
           97                  *   light source. An object can also not reflect
           98                  *   colours brighter than the source. When the brightness
           99                  *   of a light source is changed, the intensity of all
          100                  *   colours (by wavelength) it emits is multiplied by
          101                  *   one value. Therefore, when changing the brightness
          102                  *   it looks most natural when all primaries (red, green,
          103                  *   and blue) are multiplied by one value, or all
          104                  *   parameters of the used colour spaces is a linear
          105                  *   transformation of sRGB, such as CIE XYZ.
          106                  */
          107         }
          108 }
          109 
          110 #endif