summaryrefslogtreecommitdiff
path: root/ff2ppm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ff2ppm.c')
-rw-r--r--ff2ppm.c88
1 files changed, 27 insertions, 61 deletions
diff --git a/ff2ppm.c b/ff2ppm.c
index 2a67eb2..b34d870 100644
--- a/ff2ppm.c
+++ b/ff2ppm.c
@@ -9,109 +9,75 @@
#include <string.h>
#include "arg.h"
-
-char *argv0;
+#include "util.h"
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-b #rrggbb]\n", argv0);
+ fprintf(stderr, "usage: %s [-b colour]\n", argv0);
exit(1);
}
int
main(int argc, char *argv[])
{
- size_t rowlen;
+ size_t rowlen, rowoutlen;
uint64_t a;
- uint32_t hdr[4], width, height, i, j, k, l;
+ uint32_t width, height, i, j, k, l;
uint16_t *row, mask[3] = { 0xffff, 0xffff, 0xffff };
uint8_t *rowout;
- char *color, colfmt[] = "%#x%#x%#x";
- unsigned int collen, col[3], colfac;
- argv0 = argv[0];
+ /* arguments */
ARGBEGIN {
case 'b':
- color = EARGF(usage());
- if (color[0] == '#') {
- color++;
- }
- collen = strlen(color);
- if (collen != 3 && collen != 6 && collen != 12) {
- usage();
- }
- colfmt[1] = colfmt[4] = colfmt[7] = ((collen / 3) + '0');
- if (sscanf(color, colfmt, col, col + 1, col + 2) != 3) {
+ if (parse_mask(EARGF(usage()), mask)) {
usage();
}
- /* UINT16_MAX / 255 = 257; UINT16_MAX / 15 = 4369 */
- colfac = (collen == 3) ? 4369 : (collen == 6) ? 257 : 1;
- for (i = 0; i < 3; i++) {
- mask[i] = col[i] * colfac;
- }
break;
default:
usage();
} ARGEND
- if (argc)
+ if (argc) {
usage();
-
- /* header */
- if (fread(hdr, sizeof(*hdr), 4, stdin) != 4) {
- goto readerr;
- }
- if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) {
- fprintf(stderr, "%s: invalid magic value\n", argv0);
- return 1;
}
- width = ntohl(hdr[2]);
- height = ntohl(hdr[3]);
- if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) {
- fprintf(stderr, "%s: row length integer overflow\n", argv0);
- return 1;
- }
+ /* prepare */
+ ff_read_header(&width, &height);
+ row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t));
+ rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t));
rowlen = width * (sizeof("RGBA") - 1);
- if (!(row = malloc(rowlen * sizeof(uint16_t)))) {
- fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno));
- return 1;
- }
- if (!(rowout = malloc(width * (sizeof("RGB") - 1) * sizeof(uint8_t)))) {
- fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno));
- return 1;
- }
+ rowoutlen = width * (sizeof("RGB") - 1);
- /* PPM binary */
+ /* write data */
printf("P6\n%" PRIu32 " %" PRIu32 "\n255\n", width, height);
- /* write rows */
for (i = 0; i < height; ++i) {
if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) {
- goto readerr;
+ if (ferror(stdin)) {
+ fprintf(stderr, "%s: fread: %s\n", argv0,
+ strerror(errno));
+ } else {
+ fprintf(stderr, "%s: unexpected end of file\n",
+ argv0);
+ }
+ return 1;
}
for (j = 0, k = 0; j < rowlen; j += 4, k += 3) {
a = ntohs(row[j + 3]);
for (l = 0; l < 3; l++) {
+ /* alpha blending and 8-bit-reduction */
rowout[k + l] = (a * ntohs(row[j + l]) +
- (65535 - a) * mask[l]) /
- (257 * 65535);
+ (UINT16_MAX - a) * mask[l]) /
+ (UINT16_MAX *
+ (UINT16_MAX / UINT8_MAX));
}
}
- if (fwrite(rowout, 3, width, stdout) != width) {
+ if (fwrite(rowout, sizeof(uint8_t), rowoutlen, stdout) != rowoutlen) {
fprintf(stderr, "%s: fwrite: %s\n", argv0, strerror(errno));
return 1;
}
}
- return 0;
-readerr:
- if (ferror(stdin)) {
- fprintf(stderr, "%s: fread: %s\n", argv0, strerror(errno));
- } else {
- fprintf(stderr, "%s: unexpected end of file\n", argv0);
- }
-
- return 1;
+ return fshut(stdout, "<stdout>");
}