blind-make-kernel.c (3372B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("[-d denominator] ... [-nxyza] [-- value ...] ...") 5 6 static void 7 new_row(double **kernel, size_t *col, size_t *rows, size_t *cols) 8 { 9 if (!*col) 10 return; 11 if (*rows && *col != *cols) 12 eprintf("the rows in the matrix do not have the same number of columns\n"); 13 *kernel = erealloc3(*kernel, 1 + ++*rows, *cols = *col, sizeof(**kernel)); 14 *col = 0; 15 } 16 17 static void 18 new_col(char *arg, double **kernel, size_t *col, size_t *rows, size_t *cols) 19 { 20 if (*rows && *col >= *cols) 21 eprintf("the rows in the matrix do not have the same number of columns\n"); 22 if (!*rows) 23 *kernel = erealloc2(*kernel, *col + 1, sizeof(**kernel)); 24 if (tolf(arg, &(*kernel)[*rows * *cols + (*col)++])) 25 eprintf("matrix cell values must be floating-point values\n"); 26 } 27 28 static void 29 finalise(double **kernel, size_t col, size_t *rows, size_t *cols) 30 { 31 if (col) 32 new_row(kernel, &col, rows, cols); 33 if (!*rows) 34 eprintf("the matrix cannot be null-sized\n"); 35 } 36 37 static double * 38 read_matrix_cmdline(char *args[], size_t *rows, size_t *cols) 39 { 40 size_t col = 0; 41 double *kernel = NULL; 42 *rows = *cols = 0; 43 for (; *args; args++) { 44 if (!strcmp(*args, "--")) 45 new_row(&kernel, &col, rows, cols); 46 else 47 new_col(*args, &kernel, &col, rows, cols); 48 } 49 finalise(&kernel, col, rows, cols); 50 return kernel; 51 } 52 53 static double * 54 read_matrix_stdin(size_t *rows, size_t *cols) 55 { 56 char *line = NULL, *p, *q; 57 size_t size = 0, col = 0; 58 double *kernel = NULL; 59 ssize_t len; 60 *rows = *cols = 0; 61 while ((len = getline(&line, &size, stdin)) >= 0) { 62 col = 0; 63 for (p = line;; p = q) { 64 while (*p && isspace(*p)) p++; 65 if (!*(q = p)) 66 break; 67 while (*q && !isspace(*q)) q++; 68 *q++ = '\0'; 69 new_col(p, &kernel, &col, rows, cols); 70 } 71 new_row(&kernel, &col, rows, cols); 72 } 73 free(line); 74 if (ferror(stdout)) 75 eprintf("getline:"); 76 finalise(&kernel, col, rows, cols); 77 return kernel; 78 } 79 80 int 81 main(int argc, char *argv[]) 82 { 83 int normalise = 0; 84 double denominator = 1; 85 int id_x = 1, id_y = 1, id_z = 1, id_a = 1; 86 size_t rows, cols, y, x, n; 87 double *kernel, *kern, sum = 0, value; 88 double *buffer, *buf, id_val; 89 90 ARGBEGIN { 91 case 'd': 92 denominator *= etolf_flag('d', UARGF()); 93 break; 94 case 'n': 95 normalise = 1; 96 break; 97 case 'x': 98 id_x = 0; 99 break; 100 case 'y': 101 id_y = 0; 102 break; 103 case 'z': 104 id_z = 0; 105 break; 106 case 'a': 107 id_a = 0; 108 break; 109 default: 110 usage(); 111 } ARGEND; 112 113 if (id_x && id_y && id_z && id_a) 114 id_x = id_y = id_z = id_a = 0; 115 116 if (argc) 117 kernel = read_matrix_cmdline(argv, &rows, &cols); 118 else 119 kernel = read_matrix_stdin(&rows, &cols); 120 121 FPRINTF_HEAD(stdout, (size_t)1, cols, rows, "xyza"); 122 efflush(stdout, "<stdout>"); 123 124 buffer = emalloc2(cols, 4 * sizeof(double)); 125 n = cols * 4 * sizeof(double); 126 127 if (normalise) { 128 kern = kernel; 129 for (y = 0; y < rows; y++) 130 for (x = 0; x < cols; x++) 131 sum += *kern++; 132 denominator *= sum; 133 } 134 135 kern = kernel; 136 for (y = 0; y < rows; y++) { 137 buf = buffer; 138 for (x = 0; x < cols; x++) { 139 id_val = (x == cols / 2 && y == rows / 2) ? 1. : 0.; 140 value = *kern++ / denominator; 141 buf[0] = id_x ? id_val : value; 142 buf[1] = id_y ? id_val : value; 143 buf[2] = id_z ? id_val : value; 144 buf[3] = id_a ? id_val : value; 145 buf += 4; 146 } 147 ewriteall(STDOUT_FILENO, buffer, n, "<stdout>"); 148 } 149 150 free(kernel); 151 free(buffer); 152 return 0; 153 }