diff options
| author | Mattias Andrée <maandree@kth.se> | 2017-01-13 09:05:08 +0100 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2017-01-13 09:05:08 +0100 |
| commit | 4674ec0e4b833ab0d0365225ba99228df14abe87 (patch) | |
| tree | 1b89fe1559fc9a2422e20048700e694a72d17751 /src/blind-gauss-blur.c | |
| parent | vu-from-video: fix Y'UV encoding + add vu-to-video (diff) | |
| download | blind-4674ec0e4b833ab0d0365225ba99228df14abe87.tar.gz blind-4674ec0e4b833ab0d0365225ba99228df14abe87.tar.bz2 blind-4674ec0e4b833ab0d0365225ba99228df14abe87.tar.xz | |
Rename to blind
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/blind-gauss-blur.c')
| -rw-r--r-- | src/blind-gauss-blur.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/blind-gauss-blur.c b/src/blind-gauss-blur.c new file mode 100644 index 0000000..b64391c --- /dev/null +++ b/src/blind-gauss-blur.c @@ -0,0 +1,189 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include <fcntl.h> +#include <limits.h> +#include <math.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +USAGE("[-j jobs] [-ac] sd-stream") + +static int chroma = 0; +static int noalpha = 0; +static size_t jobs = 1; + +static void +process_xyza(char *restrict output, char *restrict cbuf, char *restrict sbuf, + struct stream *colour, struct stream *sigma, size_t n, size_t unused) +{ + typedef double pixel_t[4]; + + pixel_t *restrict clr = (pixel_t *)cbuf; + pixel_t *restrict sig = (pixel_t *)sbuf; + pixel_t *img = (pixel_t *)output; + pixel_t c, k; + double *p; + size_t x1, y1, i1, x2, y2, i2; + double dy, d, m, dblurred; + int i, blurred, blur[3] = {0, 0, 0}; + size_t start = 0, end = colour->height; + int is_master; + + /* premultiply alpha channel */ + if (!noalpha) { + for (y1 = i1 = 0; y1 < colour->height; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + clr[i1][0] *= clr[i1][3]; + clr[i1][1] *= clr[i1][3]; + clr[i1][2] *= clr[i1][3]; + } + } + } + + is_master = efork_jobs(&start, &end, jobs); + + /* blur */ + i1 = start * colour->width; + for (y1 = i1 = start; y1 < end; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + if (sig[i1][3] == 0) + goto no_blur; + if (!chroma) { + for (i = 0; i < 3; i++) { + k[i] = sig[i1][i] * sig[i1][3], c[i] = k[i] *= k[i] * 2, c[i] *= M_PI; + k[i] = 1 / k[i], c[i] = -1 / c[i]; + blur[i] = !sig[i1][1]; + } + } else { + k[1] = sig[i1][1] * sig[i1][3], c[1] = k[1] *= k[1] * 2, c[1] *= M_PI; + k[1] = 1 / -k[1], c[1] = 1 / c[1]; + blur[1] = !sig[i1][1]; + } + if (blur[0] + blur[1] + blur[2] == 0) + goto no_blur; + + p = img[i1]; + p[0] = p[1] = p[2] = 0; + p[3] = noalpha; + if (k[0] == k[1] && k[1] == k[2]) { + for (y2 = i2 = 0; y2 < colour->height; y2++) { + dy = (ssize_t)y1 - (ssize_t)y2; + dy *= dy; + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + for (i = noalpha ? 3 : 4; i--;) + p[i] += clr[i2][i] * m; + } + } + } else { + blurred = 0; + for (i = 0; i < n; i++) { + if (!blur[i]) { + p[i] = clr[i1][i]; + continue; + } + for (y2 = i2 = 0; y2 < colour->height; y2++) { + dy = (ssize_t)y1 - (ssize_t)y2; + dy *= dy; + if (!noalpha) { + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + p[i] += clr[i2][i] * m; + p[3] += clr[i2][3] * m; + } + } else { + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + p[i] += clr[i2][i] * m; + } + } + } + blurred += 1; + } + if (!noalpha) { + dblurred = blurred; + for (y2 = i2 = 0; y2 < colour->height; y2++) + for (x2 = 0; x2 < colour->width; x2++, i2++) + p[3] /= dblurred; + } + } + + continue; + no_blur: + img[i1][0] = clr[i1][0]; + img[i1][1] = clr[i1][1]; + img[i1][2] = clr[i1][2]; + img[i1][3] = clr[i1][3]; + } + } + + ejoin_jobs(is_master); + + /* unpremultiply alpha channel */ + if (!noalpha) { + for (y1 = i1 = 0; y1 < colour->height; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + if (!img[i1][3]) + continue; + img[i1][0] /= img[i1][3]; + img[i1][1] /= img[i1][3]; + img[i1][2] /= img[i1][3]; + } + } + } + + (void) unused; +} + +int +main(int argc, char *argv[]) +{ + struct stream colour, sigma; + void (*process)(char *restrict output, char *restrict cbuf, char *restrict sbuf, + struct stream *colour, struct stream *sigma, size_t cn, size_t sn); + + ARGBEGIN { + case 'a': + noalpha = 1; + break; + case 'c': + chroma = 1; + break; + case 'j': + jobs = etozu_flag('j', EARG(), 1, SHRT_MAX); + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + colour.file = "<stdin>"; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + sigma.file = argv[0]; + sigma.fd = eopen(sigma.file, O_RDONLY); + einit_stream(&sigma); + + if (!strcmp(colour.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + echeck_compat(&colour, &sigma); + + process_each_frame_two_streams(&colour, &sigma, STDOUT_FILENO, "<stdout>", process); + + return 0; +} |
