URI: 
       blind-apply-palette.c - 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
       ---
       blind-apply-palette.c (3026B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #ifndef TYPE
            3 #include "common.h"
            4 
            5 USAGE("palette-stream")
            6 
            7 static double (*compare)(double x1, double y1, double z1, double a1, double x2, double y2, double z2, double a2);
            8 /* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */
            9 
           10 static double
           11 distance_xyz(double x1, double y1, double z1, double a1, double x2, double y2, double z2, double a2)
           12 {
           13         x2 -= x1, x2 *= x2;
           14         y2 -= y1, y2 *= y2;
           15         z2 -= z1, z2 *= z2;
           16         a2 -= a1, a2 *= a2;
           17         return sqrt(x2 + y2 + z2 + a2);
           18 }
           19 
           20 #define FILE "blind-apply-palette.c"
           21 #include "define-functions.h"
           22 
           23 int
           24 main(int argc, char *argv[])
           25 {
           26         struct stream stream, palette;
           27         void (*process)(struct stream *stream, struct stream *palette, char *pal);
           28         char *pal;
           29 
           30         compare = distance_xyz;
           31 
           32         UNOFLAGS(argc != 1);
           33 
           34         eopen_stream(&stream, NULL);
           35         eopen_stream(&palette, argv[0]);
           36 
           37         SELECT_PROCESS_FUNCTION(&stream);
           38         CHECK_N_CHAN(&stream, 4, 4);
           39 
           40         if (strcmp(stream.pixfmt, palette.pixfmt))
           41                 eprintf("videos use incompatible pixel formats\n");
           42 
           43         echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
           44         echeck_dimensions(&palette, WIDTH | HEIGHT, NULL);
           45         pal = emalloc(palette.frame_size);
           46         fprint_stream_head(stdout, &stream);
           47         efflush(stdout, "<stdout>");
           48 
           49         process(&stream, &palette, pal);
           50 
           51         free(pal);
           52         return 0;
           53 }
           54 
           55 #else
           56 
           57 static void
           58 PROCESS(struct stream *stream, struct stream *palette, char *pal)
           59 {
           60         size_t i, j, n, m;
           61         size_t palsiz = palette->width * palette->height;
           62         size_t best = 0;
           63         TYPE x, y, z, a, lx = 0, ly = 0, lz = 0, la = 0;
           64         TYPE cx, cy, cz, ca;
           65         double distance, best_distance = 0;
           66         while (eread_frame(palette, pal)) {
           67                 m = stream->frame_size;
           68                 do {
           69                         n = MIN(stream->ptr, m) / stream->pixel_size;
           70                         for (i = 0; i < n; i++) {
           71                                 x = ((TYPE *)(stream->buf + i * stream->pixel_size))[0];
           72                                 y = ((TYPE *)(stream->buf + i * stream->pixel_size))[1];
           73                                 z = ((TYPE *)(stream->buf + i * stream->pixel_size))[2];
           74                                 a = ((TYPE *)(stream->buf + i * stream->pixel_size))[3];
           75                                 if ((!i && m == stream->frame_size) || x != lx || y != ly || z != lz || a != la) {
           76                                         for (j = 0; j < palsiz; j++) {
           77                                                 cx = ((TYPE *)(pal + j * stream->pixel_size))[0];
           78                                                 cy = ((TYPE *)(pal + j * stream->pixel_size))[1];
           79                                                 cz = ((TYPE *)(pal + j * stream->pixel_size))[2];
           80                                                 ca = ((TYPE *)(pal + j * stream->pixel_size))[3];
           81                                                 distance = compare((double)x, (double)y, (double)z, (double)a,
           82                                                                    (double)cx, (double)cy, (double)cz, (double)ca);
           83                                                 if (!j || distance < best_distance) {
           84                                                         best_distance = distance;
           85                                                         best = j;
           86                                                 }
           87                                         }
           88                                         lx = x, ly = y, lz = z, la = a;
           89                                 }
           90                                 memcpy(stream->buf + i * stream->pixel_size,
           91                                        pal + best * stream->pixel_size,
           92                                        stream->pixel_size);
           93                         }
           94                         m -= n *= stream->pixel_size;
           95                         ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
           96                         memmove(stream->buf, stream->buf + n, stream->ptr -= n);
           97                 } while (m && eread_stream(stream, SIZE_MAX));
           98                 if (m)
           99                         eprintf("%s: incomplete frame\n", stream->file);
          100         }
          101 }
          102 
          103 #endif