ff-zoom.c (4483B)
1 /* 2 * this is modified version of farbfeld-resize 3 * from https://github.com/ender672/farbfeld-resize 4 */ 5 6 #include <arpa/inet.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 struct image { 13 uint32_t width; 14 uint32_t height; 15 uint16_t *data; 16 }; 17 18 struct header { 19 char sig[8]; 20 uint32_t width; 21 uint32_t height; 22 }; 23 24 void 25 xscale(uint16_t *row_in, uint16_t *out, uint32_t width_in, uint32_t width_out, 26 uint32_t taps, uint32_t xpos) 27 { 28 double x, tx, coeff, sum[4]; 29 uint32_t i, j, smp_i, smp_safe; 30 int32_t val; 31 32 sum[0] = sum[1] = sum[2] = sum[3] = 0.0; 33 smp_i = (uint64_t)xpos * width_in / width_out; 34 tx = ((uint64_t)xpos * width_in % width_out) / (double)width_out; 35 36 for (i=1; i<=taps*2; i++) { 37 x = (i > taps ? i - taps - tx : taps - i + tx) / (taps / 2); 38 if (x < 1) { 39 coeff = (3*x*x*x - 5*x*x + 2) / taps; 40 } else { 41 coeff = (-1*x*x*x + 5*x*x - 8*x + 4) / taps; 42 } 43 smp_safe = smp_i + i < taps ? 0 : smp_i + i - taps; 44 smp_safe = smp_safe >= width_in ? width_in - 1 : smp_safe; 45 for (j=0; j<4; j++) { 46 sum[j] += row_in[smp_safe * 4 + j] / 65535.0 * coeff; 47 } 48 } 49 50 for (i=0; i<4; i++) { 51 val = 65535 * sum[i]; 52 out[i] = val < 0 ? 0 : (val > 65535 ? 65535 : val); 53 } 54 } 55 56 void 57 xscale_transpose(struct image in, struct image out) 58 { 59 uint16_t *in_row, *out_smp; 60 uint32_t i, j, taps; 61 62 taps = out.height < in.width ? 2 * in.width / out.height : 2; 63 taps += taps & 1; 64 65 for (i=0; i<out.width; i++) { 66 in_row = in.data + i * in.width * 4; 67 for (j=0; j<out.height; j++) { 68 out_smp = out.data + (j * out.width + i) * 4; 69 xscale(in_row, out_smp, in.width, out.height, taps, j); 70 } 71 } 72 } 73 74 void 75 crop(struct image in, struct image out) 76 { 77 uint32_t i, j, dx, dy; 78 uint16_t *ip, *op; 79 dx = labs((in.width - out.width)/2); 80 dy = labs((in.height - out.height)/2); 81 82 for (i=0; i<out.width; i++) 83 for (j=0; j<out.height; j++) { 84 ip = in.data + (i + dx + (j + dy) * in.width) * 4; 85 op = out.data + (i + j * out.width) * 4; 86 memcpy(op, ip, 8); 87 } 88 } 89 90 void* 91 alloc_img(uint32_t width, uint32_t height) 92 { 93 uint64_t tmp; 94 size_t size; 95 96 tmp = (uint64_t)width * height; 97 size = 4 * sizeof(uint16_t); 98 99 if (tmp > SIZE_MAX / size) { 100 return 0; 101 } 102 return malloc(tmp * size); 103 } 104 105 int 106 main(int argc, char *argv[]) 107 { 108 struct header hdr; 109 struct image in, tmp, mid, out; 110 size_t i, in_len, out_len; 111 char *end; 112 113 if (argc != 3) { 114 fprintf(stderr, "usage: %s [width] [height]\n", argv[0]); 115 return 1; 116 } 117 118 out.width = strtoul(argv[1], &end, 10); 119 if (!end || !out.width) { 120 fprintf(stderr, "bad width given\n"); 121 return 1; 122 } 123 out.height = strtoul(argv[2], &end, 10); 124 if (!end || !out.height) { 125 fprintf(stderr, "bad height given\n"); 126 return 1; 127 } 128 129 mid.width = out.width; 130 mid.height = out.height; 131 132 if (fread(&hdr, 1, sizeof(hdr), stdin) != sizeof(hdr)) { 133 fprintf(stderr, "incomplete header\n"); 134 return 1; 135 } 136 if (memcmp("farbfeld", hdr.sig, strlen("farbfeld"))) { 137 fprintf(stderr, "invalid magic\n"); 138 return 1; 139 } 140 in.width = ntohl(hdr.width); 141 in.height = ntohl(hdr.height); 142 if (!in.width || !in.height) { 143 fprintf(stderr, "bad input image\n"); 144 return 1; 145 } 146 147 /* Fix the aspect ratio. */ 148 if (mid.width / (double)in.width > mid.height / (double)in.height) { 149 mid.height = in.height * mid.width / in.width; 150 mid.height = mid.height ? mid.height : 1; 151 } else { 152 mid.width = in.width * mid.height / in.height; 153 mid.width = mid.width ? mid.width : 1; 154 } 155 156 hdr.width = htonl(out.width); 157 hdr.height = htonl(out.height); 158 if (fwrite(&hdr, sizeof(hdr), 1, stdout) != 1) { 159 fprintf(stderr, "unable to write header\n"); 160 return 1; 161 } 162 163 tmp.width = in.height; 164 tmp.height = mid.width; 165 166 in_len = in.width * in.height * 4; 167 out_len = out.width * out.height * 4; 168 169 in.data = alloc_img(in.width, in.height); 170 mid.data = alloc_img(mid.width, mid.height); 171 out.data = alloc_img(out.width, out.height); 172 tmp.data = alloc_img(tmp.width, tmp.height); 173 174 if (!in.data || !out.data || !tmp.data) { 175 fprintf(stderr, "unable to allocate memory.\n"); 176 return 1; 177 } 178 179 if (fread(in.data, sizeof(uint16_t), in_len, stdin) != in_len) { 180 fprintf(stderr, "unexpected EOF\n"); 181 return 1; 182 } 183 for (i = 0; i < in_len; i++) { 184 in.data[i] = ntohs(in.data[i]); 185 } 186 187 xscale_transpose(in, tmp); 188 xscale_transpose(tmp, mid); 189 crop(mid, out); 190 191 for (i = 0; i < out_len; i++) { 192 out.data[i] = htons(out.data[i]); 193 } 194 if (fwrite(out.data, sizeof(uint16_t), out_len, stdout) != out_len) { 195 fprintf(stderr, "write error\n"); 196 return 1; 197 } 198 return 0; 199 }