blind-apply-kernel.c (3898B)
1 /* See LICENSE file for copyright and license details. */ 2 #ifndef TYPE 3 #include "common.h" 4 5 USAGE("[-apPxy] kernel-stream") 6 7 static int no_alpha = 0; 8 static int dont_premultiply = 0; 9 static int per_pixel = 0; 10 static int wrap_x = 0; 11 static int wrap_y = 0; 12 static size_t kern_w; 13 static size_t kern_h; 14 15 #define FILE "blind-apply-kernel.c" 16 #include "define-functions.h" 17 18 int 19 main(int argc, char *argv[]) 20 { 21 struct stream colour, kernel; 22 void (*process)(struct stream *colour, struct stream *kernel); 23 size_t tmp; 24 25 ARGBEGIN { 26 case 'a': 27 no_alpha = 1; 28 break; 29 case 'p': 30 per_pixel = 1; 31 break; 32 case 'P': 33 dont_premultiply = 1; 34 break; 35 case 'x': 36 wrap_x = 1; 37 break; 38 case 'y': 39 wrap_y = 1; 40 break; 41 default: 42 usage(); 43 } ARGEND; 44 45 if (argc != 1) 46 usage(); 47 48 eopen_stream(&colour, NULL); 49 eopen_stream(&kernel, argv[0]); 50 51 SELECT_PROCESS_FUNCTION(&colour); 52 CHECK_ALPHA_CHAN(&colour); 53 CHECK_N_CHAN(&colour, 4, 4); 54 if (colour.encoding != kernel.encoding || colour.n_chan != kernel.n_chan) 55 eprintf("videos use incompatible pixel formats"); 56 if (per_pixel && !(kernel.width % colour.width || kernel.height % colour.height)) 57 eprintf("-p is specified but the dimensions of kernel-stream " 58 "are not multiples of the dimensions of stdin."); 59 60 kern_w = per_pixel ? kernel.width / colour.width : kernel.width; 61 kern_h = per_pixel ? kernel.height / colour.height : kernel.height; 62 63 tmp = kernel.height, kernel.height = kern_h; 64 echeck_dimensions(&colour, WIDTH | HEIGHT, NULL); 65 echeck_dimensions(&kernel, WIDTH | HEIGHT, NULL); 66 kernel.height = tmp; 67 68 fprint_stream_head(stdout, &colour); 69 efflush(stdout, "<stdout>"); 70 process(&colour, &kernel); 71 return 0; 72 } 73 74 #else 75 76 static void 77 PROCESS(struct stream *colour, struct stream *kernel) 78 { 79 TYPE *out, *clr, *krn, *kern, *pix; 80 size_t i, x, y, n, x2, y2; 81 ssize_t cx, cy, xoff, yoff; 82 83 out = emalloc(colour->frame_size); 84 clr = emalloc(colour->frame_size); 85 krn = emalloc2(kern_h, kernel->row_size); 86 87 xoff = (ssize_t)(kern_w / 2); 88 yoff = (ssize_t)(kern_h / 2); 89 90 n = colour->width * colour->height * colour->n_chan; 91 while (eread_frame(colour, clr)) { 92 /* premultiply */ 93 if (!no_alpha && !dont_premultiply) { 94 for (i = 0; i < n; i += 4) { 95 clr[i + 0] *= clr[i + 3]; 96 clr[i + 1] *= clr[i + 3]; 97 clr[i + 2] *= clr[i + 3]; 98 } 99 } 100 101 /* apply kernel */ 102 memset(out, 0, colour->frame_size); 103 pix = out; 104 for (y = 0; y < colour->height; y++) { 105 if ((!y || per_pixel) && !eread_segment(kernel, krn, kern_h * kernel->row_size)) 106 goto done; 107 for (x = 0; x < colour->width; x++, pix += colour->n_chan) { 108 kern = per_pixel ? (krn + x * kern_w * kernel->n_chan) : krn; 109 for (y2 = 0; y2 < kern_h; y2++, kern += kernel->width * kernel->n_chan) { 110 cy = (ssize_t)(y + y2) - yoff; 111 if (cy < 0 || (size_t)cy >= colour->height) { 112 if (!wrap_y) 113 continue; 114 cy %= (ssize_t)(colour->height); 115 if (cy < 0) 116 cy += (ssize_t)(colour->height); 117 } 118 for (x2 = 0; x2 < kern_w; x2++) { 119 cx = (ssize_t)(x + x2) - xoff; 120 if (cx < 0 || (size_t)cx >= colour->width) { 121 if (!wrap_x) 122 continue; 123 cx %= (ssize_t)(colour->width); 124 if (cx < 0) 125 cx += (ssize_t)(colour->width); 126 } 127 for (i = 0; i < colour->n_chan; i++) 128 pix[i] += kern[x2 * kernel->n_chan + i] * 129 clr[((size_t)cy * colour->width + (size_t)cx) * colour->n_chan + i]; 130 } 131 } 132 } 133 } 134 135 /* unpremultiply */ 136 if (!dont_premultiply) { 137 for (i = 0; i < n; i += 4) { 138 if (out[i + 3]) { 139 out[i + 0] /= out[i + 3]; 140 out[i + 1] /= out[i + 3]; 141 out[i + 2] /= out[i + 3]; 142 } 143 } 144 } 145 146 /* ensure video is opaque if -a was used */ 147 if (no_alpha) 148 for (i = 0; i < n; i += 4) 149 out[i + 3] = 1; 150 151 /* output video */ 152 ewriteall(STDOUT_FILENO, out, colour->frame_size, "<stdout>"); 153 } 154 done: 155 156 free(out); 157 free(clr); 158 free(krn); 159 } 160 161 #endif