blind-arithm.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-arithm.c (3393B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-axyz] operation right-hand-stream ...")
            5 
            6 static int skip_ch[4] = {0, 0, 0, 0};
            7 
            8 /* Because the syntax for a function returning a function pointer is disgusting. */
            9 typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n);
           10 
           11 #define LIST_OPERATORS(PIXFMT, TYPE)\
           12         X(add, 0, *lh += rh,                  PIXFMT, TYPE)\
           13         X(sub, 0, *lh -= rh,                  PIXFMT, TYPE)\
           14         X(mul, 0, *lh *= rh,                  PIXFMT, TYPE)\
           15         X(div, 0, *lh /= rh,                  PIXFMT, TYPE)\
           16         X(mod, 0, *lh = posmod(*lh, rh),      PIXFMT, TYPE)\
           17         X(exp, 1, *lh = pow(*lh, rh),         PIXFMT, TYPE)\
           18         X(log, 0, *lh = log2(*lh) / log2(rh), PIXFMT, TYPE)\
           19         X(min, 0, *lh = MIN(*lh, rh),         PIXFMT, TYPE)\
           20         X(max, 0, *lh = MAX(*lh, rh),         PIXFMT, TYPE)\
           21         X(abs, 0, *lh = abs(*lh - rh) + rh,   PIXFMT, TYPE)
           22 
           23 #define P(L, R, ALGO, TYPE)\
           24         (lh = (TYPE *)(streams[L].buf + k),\
           25          rh = *((TYPE *)(streams[R].buf + k)),\
           26          (ALGO))
           27 
           28 #define X(NAME, RTL, ALGO, PIXFMT, TYPE)\
           29         static void\
           30         process_##PIXFMT##_##NAME(struct stream *streams, size_t n_streams, size_t n)\
           31         {\
           32                 size_t i, j, k;\
           33                 TYPE *lh, rh;\
           34                 if (RTL) {\
           35                         for (i = 0; i < streams->n_chan; i++)\
           36                                 if (!skip_ch[i])\
           37                                         for (j = n_streams; --j;)\
           38                                                 for (k = i * sizeof(TYPE); k < n; k += 4 * sizeof(TYPE))\
           39                                                         P(j - 1, j, ALGO, TYPE);\
           40                 } else {\
           41                         for (i = 0; i < streams->n_chan; i++)\
           42                                 if (!skip_ch[i])\
           43                                         for (j = 1; j < n_streams; j++)\
           44                                                 for (k = i * sizeof(TYPE); k < n; k += 4 * sizeof(TYPE))\
           45                                                         P(0, j, ALGO, TYPE);\
           46                 }\
           47         }
           48 LIST_OPERATORS(lf, double)
           49 LIST_OPERATORS(f, float)
           50 #undef X
           51 
           52 static process_func
           53 get_process_lf(const char *operation)
           54 {
           55 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\
           56         if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
           57         LIST_OPERATORS(lf, double)
           58 #undef X
           59         eprintf("algorithm not recognised: %s\n", operation);
           60         return NULL;
           61 }
           62 
           63 static process_func
           64 get_process_f(const char *operation)
           65 {
           66 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\
           67         if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
           68         LIST_OPERATORS(f, float)
           69 #undef X
           70         eprintf("algorithm not recognised: %s\n", operation);
           71         return NULL;
           72 }
           73 
           74 int
           75 main(int argc, char *argv[])
           76 {
           77         struct stream *streams;
           78         process_func process;
           79         const char *operation;
           80         size_t frames = SIZE_MAX, tmp;
           81         int i;
           82 
           83         ARGBEGIN {
           84         case 'a':
           85                 skip_ch[3] = 1;
           86                 break;
           87         case 'x':
           88         case 'y':
           89         case 'z':
           90                 skip_ch[ARGC() - 'x'] = 1;
           91                 break;
           92         default:
           93                 usage();
           94         } ARGEND;
           95 
           96         if (argc < 2)
           97                 usage();
           98 
           99         operation = *argv;
          100         streams = alloca((size_t)argc * sizeof(*streams));
          101         *argv = NULL;
          102         for (i = 0; i < argc; i++) {
          103                 eopen_stream(streams + i, argv[i]);
          104                 if (streams[i].frames && streams[i].frames < frames)
          105                         frames = streams[i].frames;
          106         }
          107 
          108         if (streams->alpha)
          109                 CHECK_ALPHA(streams);
          110         CHECK_N_CHAN(streams, 1, 3 + !!streams->alpha);
          111         if (streams->encoding == DOUBLE)
          112                 process = get_process_lf(operation);
          113         else if (streams->encoding == FLOAT)
          114                 process = get_process_f(operation);
          115         else
          116                 eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt);
          117 
          118         tmp = streams->frames, streams->frames = frames;
          119         fprint_stream_head(stdout, streams);
          120         efflush(stdout, "<stdout>");
          121         streams->frames = tmp;
          122         process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "<stdout>", 1, process);
          123         return 0;
          124 }