blind-matrix-{rotate,shear}: add -d - 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
       ---
 (DIR) commit ff0286325a3dd1f4fe7e29e78341b9bd63e1725c
 (DIR) parent e650c912ba86c84cdad466674a0ca0c4ebadef9c
 (HTM) Author: Mattias Andrée <maandree@kth.se>
       Date:   Fri, 14 Jul 2017 21:15:32 +0200
       
       blind-matrix-{rotate,shear}: add -d
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M man/blind-matrix-rotate.1           |      14 +++++++++++++-
         M man/blind-matrix-shear.1            |       5 ++++-
         M src/blind-matrix-rotate.c           |      22 ++++++++++++++++++----
         M src/blind-matrix-shear.c            |      13 +++++++++----
         M src/video-math.h                    |      46 +++++++++++++++++++++++++++++++
       
       5 files changed, 90 insertions(+), 10 deletions(-)
       ---
 (DIR) diff --git a/man/blind-matrix-rotate.1 b/man/blind-matrix-rotate.1
       @@ -3,7 +3,7 @@
        blind-matrix-rotate - Create an affine 2D-transformation matrix for rotation
        .SH SYNOPSIS
        .B blind-matrix-rotate
       -[-c]
       +[-cd]
        .SH DESCRIPTION
        .B blind-matrix-rotate
        creates an affine 2D-transformation matrix for
       @@ -28,9 +28,21 @@ Create different matrices for each channel. Use
        values from each channel in stdin to create
        matrices whose values are stored in the same
        channels in stdout.
       +.TP
       +.B -d
       +Input angles in degrees rather than radians.
        .SH NOTES
        The image is rotated anti-clockwise if the Y-axis
        grows upwards rather than downwards.
       +.P
       +Due to truncation error, when rotating a multiple
       +of 90 degrees, it is preferable to use
       +.B -d
       +with lets
       +.B blind-matrix-rotate
       +eliminate the error. If this is not done,
       +.BR blind-invert-matrix (1)
       +may return odd results.
        .SH SEE ALSO
        .BR blind (7),
        .BR blind-from-text (1),
 (DIR) diff --git a/man/blind-matrix-shear.1 b/man/blind-matrix-shear.1
       @@ -3,7 +3,7 @@
        blind-matrix-shear - Create an affine 2D-transformation matrix for shearing
        .SH SYNOPSIS
        .B blind-matrix-shear
       -[-ac]
       +[-a [-d]] [-c]
        .SH DESCRIPTION
        .B blind-matrix-shear
        creates an affine 2D-transformation matrix for
       @@ -37,6 +37,9 @@ Create different matrices for each channel. Use
        values from each channel in stdin to create
        matrices whose values are stored in the same
        channels in stdout.
       +.TP
       +.B -d
       +Input angles in degrees rather than radians.
        .SH NOTES
        The description assumes the Y-axis grows downwards.
        .P
 (DIR) diff --git a/src/blind-matrix-rotate.c b/src/blind-matrix-rotate.c
       @@ -1,9 +1,10 @@
        /* See LICENSE file for copyright and license details. */
        #include "common.h"
        
       -USAGE("[-c]")
       +USAGE("[-cd]")
        
        static int per_channel = 0;
       +static int in_degrees = 0;
        
        #define PROCESS(TYPE)\
                do {\
       @@ -19,15 +20,25 @@ static int per_channel = 0;
                        }\
                        \
                        while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       +                        if (per_channel && in_degrees) {\
       +                                for (i = 0; i < 4; i++) {\
       +                                        matrix[4][i] = matrix[0][i] = degcos(buf[i]);\
       +                                        matrix[3][i] = -(matrix[1][i] = degsin(buf[i]));\
       +                                }\
       +                        } else if (per_channel) {\
                                        for (i = 0; i < 4; i++) {\
                                                matrix[4][i] = matrix[0][i] = cos(buf[i]);\
                                                matrix[3][i] = -(matrix[1][i] = sin(buf[i]));\
                                        }\
                                } else {\
                                        buf[1] *= buf[3];\
       -                                matrix[4][0] = matrix[0][0] = cos(buf[1]);\
       -                                matrix[3][0] = -(matrix[1][0] = sin(buf[1]));\
       +                                if (in_degrees) {\
       +                                        matrix[4][0] = matrix[0][0] = degcos(buf[1]);\
       +                                        matrix[3][0] = -(matrix[1][0] = degsin(buf[1]));\
       +                                } else {\
       +                                        matrix[4][0] = matrix[0][0] = cos(buf[1]);\
       +                                        matrix[3][0] = -(matrix[1][0] = sin(buf[1]));\
       +                                }\
                                        matrix[0][3] = matrix[0][2] = matrix[0][1] = matrix[0][0];\
                                        matrix[1][3] = matrix[1][2] = matrix[1][1] = matrix[1][0];\
                                        matrix[3][3] = matrix[3][2] = matrix[3][1] = matrix[3][0];\
       @@ -50,6 +61,9 @@ main(int argc, char *argv[])
                case 'c':
                        per_channel = 1;
                        break;
       +        case 'd':
       +                in_degrees = 1;
       +                break;
                default:
                        usage();
                } ARGEND;
 (DIR) diff --git a/src/blind-matrix-shear.c b/src/blind-matrix-shear.c
       @@ -1,16 +1,18 @@
        /* See LICENSE file for copyright and license details. */
        #include "common.h"
        
       -USAGE("[-ac]")
       +USAGE("[-a [-d]][c]")
        
        static int by_angle = 0;
        static int per_channel = 0;
       +static int in_degrees = 0;
        
        #define PROCESS(TYPE)\
                do {\
                        typedef TYPE pixel_t[4];\
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
       +                TYPE conv = in_degrees ? (TYPE)(M_PI / 180.) : 1;\
                        int i;\
                        \
                        for (i = 0; i < 4; i++) {\
       @@ -22,8 +24,8 @@ static int per_channel = 0;
                        while (eread_frame(stream, buf)) {\
                                if (by_angle) {\
                                        for (i = !per_channel; i < (per_channel ? 4 : 2); i++) {\
       -                                        buf[0][i] = tan(buf[0][i]);\
       -                                        buf[1][i] = tan(buf[1][i]);\
       +                                        buf[0][i] = tan(buf[0][i] * conv);\
       +                                        buf[1][i] = tan(buf[1][i] * conv);\
                                        }\
                                }\
                                if (per_channel) {\
       @@ -55,11 +57,14 @@ main(int argc, char *argv[])
                case 'c':
                        per_channel = 1;
                        break;
       +        case 'd':
       +                in_degrees = 1;
       +                break;
                default:
                        usage();
                } ARGEND;
        
       -        if (argc)
       +        if (argc || (in_degrees && !by_angle))
                        usage();
        
                eopen_stream(&stream, NULL);
 (DIR) diff --git a/src/video-math.h b/src/video-math.h
       @@ -31,6 +31,50 @@ posmodf(float a, float b)
                return x < 0 ? x + b : x;
        }
        
       +static inline double
       +degsin(double u)
       +{
       +        if (!fmod(u, 90)) {
       +                int64_t v = u;
       +                v = ((v / 90) % 4 + 4) % 4;
       +                return ((double[]){0, 1, 0, -1})[v];
       +        }
       +        return sin(u * (M_PI / 180.0));
       +}
       +
       +static inline float
       +degsinf(float u)
       +{
       +        if (!fmodf(u, 90)) {
       +                int64_t v = u;
       +                v = ((v / 90) % 4 + 4) % 4;
       +                return ((float[]){0, 1, 0, -1})[v];
       +        }
       +        return sin(u * (float)(M_PI / 180.0));
       +}
       +
       +static inline double
       +degcos(double u)
       +{
       +        if (!fmod(u, 90)) {
       +                int64_t v = u;
       +                v = ((v / 90) % 4 + 4) % 4;
       +                return ((double[]){1, 0, -1, 0})[v];
       +        }
       +        return cos(u * (M_PI / 180.0));
       +}
       +
       +static inline float
       +degcosf(float u)
       +{
       +        if (!fmodf(u, 90)) {
       +                int64_t v = u;
       +                v = ((v / 90) % 4 + 4) % 4;
       +                return ((float[]){1, 0, -1, 0})[v];
       +        }
       +        return cos(u * (float)(M_PI / 180.0));
       +}
       +
        #define GENERIC(TYPE, FUNC, ...)\
                TYPE:           FUNC(__VA_ARGS__),\
                TYPE *:         FUNC(__VA_ARGS__),\
       @@ -73,6 +117,8 @@ posmodf(float a, float b)
        #define sin(...)         MATH_GENERIC_1(sin,      __VA_ARGS__)
        #define tan(...)         MATH_GENERIC_1(tan,      __VA_ARGS__)
        #define atan2(...)       MATH_GENERIC_N(atan2,    __VA_ARGS__)
       +#define degcos(...)      MATH_GENERIC_1(degcos,   __VA_ARGS__)
       +#define degsin(...)      MATH_GENERIC_1(degsin,   __VA_ARGS__)
        
        #define srgb_encode(...) BLIND_GENERIC_1(srgb_encode, __VA_ARGS__)
        #define srgb_decode(...) BLIND_GENERIC_1(srgb_decode, __VA_ARGS__)