From 416f39e3d68a6b12a05751930a609cfbbde483ff Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 29 Mar 2017 17:51:41 +0200 Subject: Overhaul Build-system I didn't like the current Makefiles. They were too crufted and not elegant. Additionally, given I'm planning to put some utility functions into a util.{c|h}-prerequisite, I wrote this new Makefile with PREREQs in mind. --- Makefile | 60 +++++++++++++++++++++++++++++------------------------------- config.mk | 30 +++++------------------------- 2 files changed, 34 insertions(+), 56 deletions(-) diff --git a/Makefile b/Makefile index 72a5e3c..a764133 100644 --- a/Makefile +++ b/Makefile @@ -2,51 +2,49 @@ # See LICENSE file for copyright and license details include config.mk +PREREQ = +HDR = arg.h BIN = png2ff ff2png jpg2ff ff2jpg ff2pam ff2ppm SCRIPTS = 2ff -SRC = ${BIN:=.c} -HDR = arg.h -MAN1 = 2ff.1 ${BIN:=.1} +MAN1 = 2ff.1 $(BIN:=.1) MAN5 = farbfeld.5 -all: ${BIN} - -${BIN}: ${@:=.o} - -OBJ = ${SRC:.c=.o} +all: $(BIN) -${OBJ}: config.mk ${HDR} +$(BIN): % : %.o $(PREREQ:=.o) + $(CC) $^ $(LDFLAGS) -o $@ -.o: - ${CC} ${CFLAGS} ${$*-LDFLAGS} -o $@ $< +$(BIN:=.o): $(HDR) $(PREREQ:=.h) -.c.o: - ${CC} ${CFLAGS} ${$*-CFLAGS} ${CPPFLAGS} -c $< +%.o: %.c config.mk + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< clean: - rm -f ${BIN} ${OBJ} + rm -f $(BIN) $(BIN:=.o) $(PREREQ:=.o) dist: - rm -rf "farbfeld-${VERSION}" - mkdir -p "farbfeld-${VERSION}" - cp -R FORMAT LICENSE Makefile README TODO config.mk ${SCRIPTS} ${HDR} ${SRC} ${MAN1} ${MAN5} "farbfeld-${VERSION}" - tar -cf - "farbfeld-${VERSION}" | gzip -c > "farbfeld-${VERSION}.tar.gz" - rm -rf "farbfeld-${VERSION}" + rm -rf "farbfeld-$(VERSION)" + mkdir -p "farbfeld-$(VERSION)" + cp -R FORMAT LICENSE Makefile README TODO config.mk $(SCRIPTS) \ + $(HDR) $(BIN:=.c) $(PREREQ:=.c) $(PREREQ:=.h) \ + $(MAN1) $(MAN5) "farbfeld-$(VERSION)" + tar -cf - "farbfeld-$(VERSION)" | gzip -c > "farbfeld-$(VERSION).tar.gz" + rm -rf "farbfeld-$(VERSION)" install: all - mkdir -p "${DESTDIR}${PREFIX}/bin" - cp -f ${SCRIPTS} ${BIN} "${DESTDIR}${PREFIX}/bin" - for f in $(BIN) $(SCRIPTS); do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"; done - mkdir -p "${DESTDIR}${MANPREFIX}/man1" - cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1" - for m in $(MAN1); do chmod 644 "${DESTDIR}${MANPREFIX}/man1/$$m"; done - mkdir -p "${DESTDIR}${MANPREFIX}/man5" - cp -f ${MAN5} "${DESTDIR}${MANPREFIX}/man5" - for m in $(MAN5); do chmod 644 "${DESTDIR}${MANPREFIX}/man5/$$m"; done + mkdir -p "$(DESTDIR)$(PREFIX)/bin" + cp -f $(SCRIPTS) $(BIN) "$(DESTDIR)$(PREFIX)/bin" + for f in $(BIN) $(SCRIPTS); do chmod 755 "$(DESTDIR)$(PREFIX)/bin/$$f"; done + mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" + cp -f $(MAN1) "$(DESTDIR)$(MANPREFIX)/man1" + for m in $(MAN1); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done + mkdir -p "$(DESTDIR)$(MANPREFIX)/man5" + cp -f $(MAN5) "$(DESTDIR)$(MANPREFIX)/man5" + for m in $(MAN5); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done uninstall: - for f in $(BIN) $(SCRIPTS); do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; done - for m in $(MAN1); do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done - for m in $(MAN5); do rm -f "${DESTDIR}${MANPREFIX}/man5/$$m"; done + for f in $(BIN) $(SCRIPTS); do rm -f "$(DESTDIR)$(PREFIX)/bin/$$f"; done + for m in $(MAN1); do rm -f "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done + for m in $(MAN5); do rm -f "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done .PHONY: all clean dist install uninstall diff --git a/config.mk b/config.mk index 5fde97e..93988c4 100644 --- a/config.mk +++ b/config.mk @@ -7,33 +7,13 @@ VERSION = 2 PREFIX = /usr/local MANPREFIX = ${PREFIX}/man -PNGLIB = /usr/local/lib -PNGINC = /usr/local/include - -JPGLIB = /usr/local/lib -JPGINC = /usr/local/include - -INCS = -LIBS = - # flags CPPFLAGS = -D_DEFAULT_SOURCE -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} -LDFLAGS = -s ${LIBS} +CFLAGS = -std=c89 -pedantic -Wall -Os +LDFLAGS = -s + +png2ff ff2png: LDFLAGS += -lpng +jpg2ff ff2jpg: LDFLAGS += -ljpeg # compiler and linker CC = cc - -# flags per tool. - -png2ff-CFLAGS := -I${PNGINC} -png2ff-LDFLAGS := -L${PNGLIB} -lpng - -ff2png-CFLAGS := -I${PNGINC} -ff2png-LDFLAGS := -L${PNGLIB} -lpng - -jpg2ff-CFLAGS := -I${JPGINC} -jpg2ff-LDFLAGS := -L${JPGLIB} -ljpeg - -ff2jpg-CFLAGS := -I${JPGINC} -ff2jpg-LDFLAGS := -L${JPGLIB} -ljpeg -- cgit v1.2.3 From 65829635d9f5f9f4a23c2f890c60c315bcbafee2 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 29 Mar 2017 18:07:29 +0200 Subject: Rename PREREQ to REQ --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index a764133..dcbbeed 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # See LICENSE file for copyright and license details include config.mk -PREREQ = +REQ = HDR = arg.h BIN = png2ff ff2png jpg2ff ff2jpg ff2pam ff2ppm SCRIPTS = 2ff @@ -11,22 +11,22 @@ MAN5 = farbfeld.5 all: $(BIN) -$(BIN): % : %.o $(PREREQ:=.o) +$(BIN): % : %.o $(REQ:=.o) $(CC) $^ $(LDFLAGS) -o $@ -$(BIN:=.o): $(HDR) $(PREREQ:=.h) +$(BIN:=.o): $(HDR) $(REQ:=.h) %.o: %.c config.mk $(CC) $(CPPFLAGS) $(CFLAGS) -c $< clean: - rm -f $(BIN) $(BIN:=.o) $(PREREQ:=.o) + rm -f $(BIN) $(BIN:=.o) $(REQ:=.o) dist: rm -rf "farbfeld-$(VERSION)" mkdir -p "farbfeld-$(VERSION)" cp -R FORMAT LICENSE Makefile README TODO config.mk $(SCRIPTS) \ - $(HDR) $(BIN:=.c) $(PREREQ:=.c) $(PREREQ:=.h) \ + $(HDR) $(BIN:=.c) $(REQ:=.c) $(REQ:=.h) \ $(MAN1) $(MAN5) "farbfeld-$(VERSION)" tar -cf - "farbfeld-$(VERSION)" | gzip -c > "farbfeld-$(VERSION).tar.gz" rm -rf "farbfeld-$(VERSION)" -- cgit v1.2.3 From bbe28227eb80da62fec59aa79ba7a97f5c3937b4 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 30 Mar 2017 08:41:17 +0200 Subject: Make Makefile strictly POSIX compliant Thanks Hiltjo for the feedback! GNUisms need to be avoided like a plague, even if it means having to be a little more creative. Strict POSIX compliance means that I just worked within the bounds of the POSIX specification, hopefully without using any GNU or BSD extensions. If I did, please let me know. Tip to all Linux users: Test your Makefiles with pmake(1) instead of make(1) (= GNU make) and refer to the newest POSIX 2016 make specification[0]. [0]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html --- Makefile | 27 +++++++++++++-------------- config.mk | 6 ++++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index dcbbeed..5d9c213 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,32 @@ -# farbfeld - suckless image format with conversion tools # See LICENSE file for copyright and license details +# farbfeld - suckless image format with conversion tools +.POSIX: + include config.mk -REQ = HDR = arg.h BIN = png2ff ff2png jpg2ff ff2jpg ff2pam ff2ppm -SCRIPTS = 2ff +SCR = 2ff MAN1 = 2ff.1 $(BIN:=.1) MAN5 = farbfeld.5 all: $(BIN) -$(BIN): % : %.o $(REQ:=.o) - $(CC) $^ $(LDFLAGS) -o $@ +.o: $(REQ:=.o) + $(CC) $(CFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) -$(BIN:=.o): $(HDR) $(REQ:=.h) - -%.o: %.c config.mk +.c.o: $(CC) $(CPPFLAGS) $(CFLAGS) -c $< +$(BIN:=.o): config.mk $(HDR) $(REQ:=.h) + clean: rm -f $(BIN) $(BIN:=.o) $(REQ:=.o) dist: rm -rf "farbfeld-$(VERSION)" mkdir -p "farbfeld-$(VERSION)" - cp -R FORMAT LICENSE Makefile README TODO config.mk $(SCRIPTS) \ + cp -R FORMAT LICENSE Makefile README TODO config.mk $(SCR) \ $(HDR) $(BIN:=.c) $(REQ:=.c) $(REQ:=.h) \ $(MAN1) $(MAN5) "farbfeld-$(VERSION)" tar -cf - "farbfeld-$(VERSION)" | gzip -c > "farbfeld-$(VERSION).tar.gz" @@ -33,8 +34,8 @@ dist: install: all mkdir -p "$(DESTDIR)$(PREFIX)/bin" - cp -f $(SCRIPTS) $(BIN) "$(DESTDIR)$(PREFIX)/bin" - for f in $(BIN) $(SCRIPTS); do chmod 755 "$(DESTDIR)$(PREFIX)/bin/$$f"; done + cp -f $(SCR) $(BIN) "$(DESTDIR)$(PREFIX)/bin" + for f in $(BIN) $(SCR); do chmod 755 "$(DESTDIR)$(PREFIX)/bin/$$f"; done mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" cp -f $(MAN1) "$(DESTDIR)$(MANPREFIX)/man1" for m in $(MAN1); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done @@ -43,8 +44,6 @@ install: all for m in $(MAN5); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done uninstall: - for f in $(BIN) $(SCRIPTS); do rm -f "$(DESTDIR)$(PREFIX)/bin/$$f"; done + for f in $(BIN) $(SCR); do rm -f "$(DESTDIR)$(PREFIX)/bin/$$f"; done for m in $(MAN1); do rm -f "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done for m in $(MAN5); do rm -f "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done - -.PHONY: all clean dist install uninstall diff --git a/config.mk b/config.mk index 93988c4..d5bc6c7 100644 --- a/config.mk +++ b/config.mk @@ -12,8 +12,10 @@ CPPFLAGS = -D_DEFAULT_SOURCE CFLAGS = -std=c89 -pedantic -Wall -Os LDFLAGS = -s -png2ff ff2png: LDFLAGS += -lpng -jpg2ff ff2jpg: LDFLAGS += -ljpeg +png2ff-LDFLAGS = -lpng +ff2png-LDFLAGS = -lpng +jpg2ff-LDFLAGS = -ljpeg +ff2jpg-LDFLAGS = -ljpeg # compiler and linker CC = cc -- cgit v1.2.3 From ef433a6baa3449f5a5ec7a6fd09efdd0ea6fb57b Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 30 Mar 2017 08:52:22 +0200 Subject: No need to keep the implicit build rule --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index 5d9c213..92679b4 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,6 @@ all: $(BIN) .o: $(REQ:=.o) $(CC) $(CFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) -.c.o: - $(CC) $(CPPFLAGS) $(CFLAGS) -c $< - $(BIN:=.o): config.mk $(HDR) $(REQ:=.h) clean: -- cgit v1.2.3 From 0aaa36464a4ad965a3d747cc6df16137c7b5d6c5 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 30 Mar 2017 08:59:52 +0200 Subject: Pass LDFLAGS instead of CFLAGS in the linking stage --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 92679b4..e1e954d 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ include config.mk +REQ = util HDR = arg.h BIN = png2ff ff2png jpg2ff ff2jpg ff2pam ff2ppm SCR = 2ff @@ -13,7 +14,7 @@ MAN5 = farbfeld.5 all: $(BIN) .o: $(REQ:=.o) - $(CC) $(CFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) + $(CC) $(LDFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) $(BIN:=.o): config.mk $(HDR) $(REQ:=.h) -- cgit v1.2.3 From d0ce307972fbc95073666e92043fc7012ffbefdf Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 30 Mar 2017 09:29:06 +0200 Subject: Mark explicit dependency on requisites for BIN --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e1e954d..1f7446f 100644 --- a/Makefile +++ b/Makefile @@ -13,11 +13,13 @@ MAN5 = farbfeld.5 all: $(BIN) -.o: $(REQ:=.o) - $(CC) $(LDFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) +$(BIN): $(REQ:=.o) $(BIN:=.o): config.mk $(HDR) $(REQ:=.h) +.o: $(REQ:=.o) + $(CC) $(LDFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) + clean: rm -f $(BIN) $(BIN:=.o) $(REQ:=.o) -- cgit v1.2.3 From d25f3c73afa5beb83121c9b033bc0146c755ca3a Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 30 Mar 2017 09:49:48 +0200 Subject: Add util.{c|h} to deduplicate code --- ff2jpg.c | 19 +++++-------------- ff2pam.c | 18 ++++-------------- ff2png.c | 16 ++++------------ ff2ppm.c | 16 +++------------- jpg2ff.c | 15 ++++----------- png2ff.c | 15 ++++----------- util.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 10 ++++++++++ 8 files changed, 85 insertions(+), 75 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/ff2jpg.c b/ff2jpg.c index 6f88a23..51f1fe6 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -11,8 +11,7 @@ #include #include "arg.h" - -char *argv0; +#include "util.h" METHODDEF(void) jpeg_error(j_common_ptr js) @@ -37,7 +36,7 @@ main(int argc, char *argv[]) struct jpeg_error_mgr jerr; size_t rowlen; 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"; @@ -75,19 +74,11 @@ main(int argc, char *argv[]) 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]); + + read_ff_header(&width, &height); if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) { fprintf(stderr, "%s: row length integer overflow\n", argv0); diff --git a/ff2pam.c b/ff2pam.c index 93bd26c..aca15cb 100644 --- a/ff2pam.c +++ b/ff2pam.c @@ -8,12 +8,12 @@ #include #include -static char *argv0; +#include "util.h" int main(int argc, char *argv[]) { - uint32_t hdr[4], width, height; + uint32_t width, height; char buf[BUFSIZ]; size_t n, t; @@ -24,19 +24,9 @@ main(int argc, char *argv[]) return 1; } - /* header */ - if (fread(hdr, sizeof(*hdr), 4, stdin) != 4) { - fprintf(stderr, "%s: file too short\n", argv0); - return 1; - } - 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]); + read_ff_header(&width, &height); - /* write header */ + /* write PAM header */ printf("P7\n" "WIDTH %" PRIu32 "\n" "HEIGHT %" PRIu32 "\n" diff --git a/ff2png.c b/ff2png.c index 5731082..360ab00 100644 --- a/ff2png.c +++ b/ff2png.c @@ -9,11 +9,12 @@ #include -static char *argv0; +#include "util.h" void pngerr(png_structp pngs, const char *msg) { + (void)pngs; fprintf(stderr, "%s: libpng: %s\n", argv0, msg); exit(1); } @@ -24,7 +25,7 @@ main(int argc, char *argv[]) png_structp pngs; png_infop pngi; size_t rowlen; - uint32_t hdr[4], width, height, i; + uint32_t width, height, i; uint16_t *row; argv0 = argv[0], argc--, argv++; @@ -34,16 +35,7 @@ main(int argc, char *argv[]) return 1; } - /* 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]); + read_ff_header(&width, &height); /* load png */ pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngerr, diff --git a/ff2ppm.c b/ff2ppm.c index 2a67eb2..f0f3956 100644 --- a/ff2ppm.c +++ b/ff2ppm.c @@ -9,8 +9,7 @@ #include #include "arg.h" - -char *argv0; +#include "util.h" static void usage(void) @@ -24,7 +23,7 @@ main(int argc, char *argv[]) { size_t rowlen; 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"; @@ -58,16 +57,7 @@ main(int argc, char *argv[]) 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]); + read_ff_header(&width, &height); if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) { fprintf(stderr, "%s: row length integer overflow\n", argv0); diff --git a/jpg2ff.c b/jpg2ff.c index 8ebc81d..85c935d 100644 --- a/jpg2ff.c +++ b/jpg2ff.c @@ -8,7 +8,7 @@ #include -static char *argv0; +#include "util.h" METHODDEF(void) jpeg_error(j_common_ptr js) @@ -23,7 +23,7 @@ main(int argc, char *argv[]) { struct jpeg_decompress_struct js; struct jpeg_error_mgr jerr; - uint32_t width, height, tmp32; + uint32_t width, height; uint16_t *row; size_t rowlen, i; JSAMPARRAY jpgrow; @@ -63,14 +63,8 @@ main(int argc, char *argv[]) return 1; } - /* write header */ - fputs("farbfeld", stdout); - tmp32 = htonl(width); - if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) - goto writerr; - tmp32 = htonl(height); - if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) - goto writerr; + /* write data */ + write_ff_header(width, height); while (js.output_scanline < js.output_height) { /* jpeg_read_scanlines expects an array of pointers to @@ -87,7 +81,6 @@ main(int argc, char *argv[]) row[4*i + 3] = htons(65535); } - /* write data */ if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) goto writerr; } diff --git a/png2ff.c b/png2ff.c index 55456e3..515979d 100644 --- a/png2ff.c +++ b/png2ff.c @@ -8,7 +8,7 @@ #include -static char *argv0; +#include "util.h" void pngerr(png_structp pngs, const char *msg) @@ -22,7 +22,7 @@ main(int argc, char *argv[]) { png_structp pngs; png_infop pngi; - uint32_t width, height, rowlen, tmp32, r, i; + uint32_t width, height, rowlen, r, i; uint16_t *row; uint8_t **pngrows; @@ -66,16 +66,9 @@ main(int argc, char *argv[]) return 1; } - /* write header */ - fputs("farbfeld", stdout); - tmp32 = htonl(width); - if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) - goto writerr; - tmp32 = htonl(height); - if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) - goto writerr; - /* write data */ + write_ff_header(width, height); + switch(png_get_bit_depth(pngs, pngi)) { case 8: for (r = 0; r < height; ++r) { diff --git a/util.c b/util.c new file mode 100644 index 0000000..b374df9 --- /dev/null +++ b/util.c @@ -0,0 +1,51 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include +#include +#include +#include +#include + +#include "util.h" + +char *argv0; + +void +read_ff_header(uint32_t *width, uint32_t *height) +{ + uint32_t hdr[4]; + + if (fread(hdr, sizeof(*hdr), LEN(hdr), stdin) != LEN(hdr)) { + fprintf(stderr, "%s: fread: %s", argv0, strerror(errno)); + exit(1); + } + + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { + fprintf(stderr, "%s: invalid magic value\n", argv0); + exit(1); + } + + *width = ntohl(hdr[2]); + *height = ntohl(hdr[3]); +} + +void +write_ff_header(uint32_t width, uint32_t height) +{ + uint32_t tmp; + + fputs("farbfeld", stdout); + + tmp = htonl(width); + if (fwrite(&tmp, sizeof(tmp), 1, stdout) != 1) { + fprintf(stderr, "%s: write: %s", argv0, strerror(errno)); + exit(1); + } + + tmp = htonl(height); + if (fwrite(&tmp, sizeof(tmp), 1, stdout) != 1) { + fprintf(stderr, "%s: write: %s", argv0, strerror(errno)); + exit(1); + } +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..02aee25 --- /dev/null +++ b/util.h @@ -0,0 +1,10 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +extern char *argv0; + +#define LEN(x) (sizeof (x) / sizeof *(x)) + +void read_ff_header(uint32_t *width, uint32_t *height); +void write_ff_header(uint32_t width, uint32_t height); -- cgit v1.2.3 From cef01ad97b1e215b0879c369e42e31bb3e5188a1 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Sun, 2 Apr 2017 20:53:55 +0200 Subject: Remove prerequisite from single-suffix inference rule This is against the standard: "The application shall ensure that the makefile does not specify prerequisites for inference rules;"[0] We are still fine though as we explicitly state the dependency on the requisite-objects in the $(BIN)-target. Thanks Lucas for pointing this out! [0]:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1f7446f..4752fb6 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ $(BIN): $(REQ:=.o) $(BIN:=.o): config.mk $(HDR) $(REQ:=.h) -.o: $(REQ:=.o) +.o: $(CC) $(LDFLAGS) $($*-LDFLAGS) -o $@ $< $(REQ:=.o) clean: -- cgit v1.2.3 From 4ee1dee12fc4680504cb0a75c4b8a6862fd38db2 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Sun, 2 Apr 2017 20:56:15 +0200 Subject: config.mk: C89 -> C99 We are using stdint.h, which is a C99 feature. Syntactically, the code is C89 though. --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index d5bc6c7..4cd5ce2 100644 --- a/config.mk +++ b/config.mk @@ -9,7 +9,7 @@ MANPREFIX = ${PREFIX}/man # flags CPPFLAGS = -D_DEFAULT_SOURCE -CFLAGS = -std=c89 -pedantic -Wall -Os +CFLAGS = -std=c99 -pedantic -Wall -Os LDFLAGS = -s png2ff-LDFLAGS = -lpng -- cgit v1.2.3 From aa873108425a500d8f47edb56fb476f248cb09d0 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:34:40 +0200 Subject: Rename header-functions and add more util functions parse_mask() -> parse a mask-color #xxxxxx ereallocarray() estrtonum() These will come in handy in the respective tools. --- util.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- util.h | 14 +++++- 2 files changed, 178 insertions(+), 4 deletions(-) diff --git a/util.c b/util.c index b374df9..7b59d19 100644 --- a/util.c +++ b/util.c @@ -12,7 +12,7 @@ char *argv0; void -read_ff_header(uint32_t *width, uint32_t *height) +ff_read_header(uint32_t *width, uint32_t *height) { uint32_t hdr[4]; @@ -31,7 +31,7 @@ read_ff_header(uint32_t *width, uint32_t *height) } void -write_ff_header(uint32_t width, uint32_t height) +ff_write_header(uint32_t width, uint32_t height) { uint32_t tmp; @@ -49,3 +49,167 @@ write_ff_header(uint32_t width, uint32_t height) exit(1); } } + +int +parse_mask(const char *s, uint16_t mask[3]) +{ + size_t slen, i; + unsigned int col[3], colfac; + char fmt[] = "%#x%#x%#x"; + + if ((s++)[0] != '#') { + return 1; + } + + slen = strlen(s); + if (slen != 3 && slen != 6 && slen != 12) { + return 1; + } + + fmt[1] = fmt[4] = fmt[7] = ((slen / 3) + '0'); + if (sscanf(s, fmt, col, col + 1, col + 2) != 3) { + return 1; + } + + colfac = (slen == 3) ? UINT16_MAX / 0xf : + (slen == 6) ? UINT16_MAX / 0xff : + UINT16_MAX / 0xffff; + + for (i = 0; i < 3; i++) { + mask[i] = col[i] * colfac; + } + + return 0; +} + +void * +ereallocarray(void *optr, size_t nmemb, size_t size) +{ + void *p; + + if (!(p = reallocarray(optr, nmemb, size))) { + fprintf(stderr, "%s: reallocarray: out of memory\n", argv0); + exit(1); + } + + return p; +} + +long long +estrtonum(const char *numstr, long long minval, long long maxval) +{ + const char *errstr; + long long ll; + + ll = strtonum(numstr, minval, maxval, &errstr); + if (errstr) { + fprintf(stderr, "%s: strtonum %s: %s\n", argv0, numstr, errstr); + exit(1); + } + + return ll; +} + +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} + +/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} diff --git a/util.h b/util.h index 02aee25..93492a5 100644 --- a/util.h +++ b/util.h @@ -6,5 +6,15 @@ extern char *argv0; #define LEN(x) (sizeof (x) / sizeof *(x)) -void read_ff_header(uint32_t *width, uint32_t *height); -void write_ff_header(uint32_t width, uint32_t height); +void ff_read_header(uint32_t *width, uint32_t *height); +void ff_write_header(uint32_t width, uint32_t height); + +int parse_mask(const char *, uint16_t mask[3]); + +#undef reallocarray +void *reallocarray(void *, size_t, size_t); +void *ereallocarray(void *optr, size_t nmemb, size_t size); + +#undef strtonum +long long strtonum(const char *, long long, long long, const char **); +long long estrtonum(const char *, long long, long long); -- cgit v1.2.3 From f22282e99a963f5935ea68a583cc7d928a787ce1 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:36:06 +0200 Subject: Also print extra warnings --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 4cd5ce2..b6b0ce4 100644 --- a/config.mk +++ b/config.mk @@ -9,7 +9,7 @@ MANPREFIX = ${PREFIX}/man # flags CPPFLAGS = -D_DEFAULT_SOURCE -CFLAGS = -std=c99 -pedantic -Wall -Os +CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os LDFLAGS = -s png2ff-LDFLAGS = -lpng -- cgit v1.2.3 From 9a992f810d2a11751026ac352f435be1717e0979 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:36:47 +0200 Subject: Refactor jpg-conversion-utilities First of all, there was lots of libjpeg-specific cruft that just didn't have any right to exist (METHODDEF(), strange typedefs, use of the internal memory pool for no reason). This is gone now. Additionally, we make use of the save and proven utility functions and in general the code should be more well-separated now. What is left to do is clear up the part where we mix the colors with the mask. --- ff2jpg.c | 112 ++++++++++++++++++++++++++------------------------------------- jpg2ff.c | 94 ++++++++++++++++++++++++++--------------------------- 2 files changed, 92 insertions(+), 114 deletions(-) diff --git a/ff2jpg.c b/ff2jpg.c index 51f1fe6..78cb122 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -13,7 +13,7 @@ #include "arg.h" #include "util.h" -METHODDEF(void) +static void jpeg_error(j_common_ptr js) { fprintf(stderr, "%s: libjpeg: ", argv0); @@ -21,6 +21,29 @@ jpeg_error(j_common_ptr js) exit(1); } +static void +jpeg_setup_writer(struct jpeg_compress_struct *s, struct jpeg_error_mgr *e, + uint32_t w, uint32_t h, int quality, int opt) +{ + jpeg_create_compress(s); + e->error_exit = jpeg_error; + s->err = jpeg_std_error(e); + + jpeg_stdio_dest(s, stdout); + s->image_width = w; + s->image_height = h; + s->input_components = 3; /* color components per pixel */ + s->in_color_space = JCS_RGB; /* output color space */ + jpeg_set_defaults(s); + + if (opt) { + s->optimize_coding = 1; + } + jpeg_set_quality(s, quality, 1); + + jpeg_start_compress(s, 1); +} + static void usage(void) { @@ -31,44 +54,27 @@ usage(void) int main(int argc, char *argv[]) { - JSAMPROW row_pointer[1]; /* pointer to a single row */ - struct jpeg_compress_struct cinfo; + struct jpeg_compress_struct jcomp; struct jpeg_error_mgr jerr; size_t rowlen; uint64_t a; 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, quality = 85, optimize = 0; + int optimize = 0, quality = 85; - argv0 = argv[0]; + /* arguments */ ARGBEGIN { case 'b': - color = EARGF(usage()); - if (color[0] == '#') { - color++; - } - collen = strlen(color); - if (collen != 3 && collen != 6 && collen != 12) { + if (parse_mask(EARGF(usage()), mask)) { usage(); } - colfmt[1] = colfmt[4] = colfmt[7] = ((collen / 3) + '0'); - if (sscanf(color, colfmt, col, col + 1, col + 2) != 3) { - 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; case 'o': optimize = 1; break; case 'q': - if ((quality = atoi(EARGF(usage()))) > 100) - usage(); + quality = estrtonum(EARGF(usage()), 0, 100); break; default: usage(); @@ -78,43 +84,24 @@ main(int argc, char *argv[]) usage(); } - read_ff_header(&width, &height); - - 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); + jpeg_setup_writer(&jcomp, &jerr, width, height, quality, optimize); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_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; - } - row_pointer[0] = rowout; - - jerr.error_exit = jpeg_error; - - jpeg_create_compress(&cinfo); - cinfo.err = jpeg_std_error(&jerr); - jpeg_stdio_dest(&cinfo, stdout); - cinfo.image_width = width; - cinfo.image_height = height; - cinfo.input_components = 3; /* color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* output color space */ - jpeg_set_defaults(&cinfo); - if (optimize) - cinfo.optimize_coding = TRUE; - jpeg_set_quality(&cinfo, quality, TRUE); - - jpeg_start_compress(&cinfo, TRUE); + rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); /* 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]); @@ -124,19 +111,12 @@ main(int argc, char *argv[]) (257 * 65535); } } - jpeg_write_scanlines(&cinfo, row_pointer, 1); + jpeg_write_scanlines(&jcomp, &rowout, 1); } - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); + /* clean up */ + jpeg_finish_compress(&jcomp); + jpeg_destroy_compress(&jcomp); 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; } diff --git a/jpg2ff.c b/jpg2ff.c index 85c935d..8d51fb6 100644 --- a/jpg2ff.c +++ b/jpg2ff.c @@ -5,12 +5,13 @@ #include #include #include +#include #include #include "util.h" -METHODDEF(void) +static void jpeg_error(j_common_ptr js) { fprintf(stderr, "%s: libjpeg: ", argv0); @@ -18,6 +19,31 @@ jpeg_error(j_common_ptr js) exit(1); } +static void +jpeg_setup_reader(struct jpeg_decompress_struct *s, struct jpeg_error_mgr *e, + uint32_t *w, uint32_t *h) +{ + jpeg_create_decompress(s); + e->error_exit = jpeg_error; + s->err = jpeg_std_error(e); + + jpeg_stdio_src(s, stdin); + jpeg_read_header(s, 1); + *w = s->image_width; + *h = s->image_height; + s->output_components = 3; /* color components per pixel */ + s->out_color_space = JCS_RGB; /* input color space */ + + jpeg_start_decompress(s); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { @@ -25,72 +51,44 @@ main(int argc, char *argv[]) struct jpeg_error_mgr jerr; uint32_t width, height; uint16_t *row; + uint8_t *rowin; size_t rowlen, i; - JSAMPARRAY jpgrow; + /* arguments */ argv0 = argv[0], argc--, argv++; if (argc) { - fprintf(stderr, "usage: %s\n", argv0); - return 1; + usage(); } - /* load jpg */ - js.err = jpeg_std_error(&jerr); - jerr.error_exit = jpeg_error; - - jpeg_create_decompress(&js); - - jpeg_stdio_src(&js, stdin); - - jpeg_read_header(&js, 1); - width = js.image_width; - height = js.image_height; - - /* set output format */ - js.output_components = 3; /* color components per pixel */ - js.out_color_space = JCS_RGB; /* input color space */ - - jpeg_start_decompress(&js); - - /* create output buffers */ - jpgrow = (*js.mem->alloc_sarray)((j_common_ptr)&js, - JPOOL_IMAGE, width * - js.output_components, 1); + /* prepare */ + jpeg_setup_reader(&js, &jerr, &width, &height); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); rowlen = width * (sizeof("RGBA") - 1); - if(!(row = malloc(rowlen * sizeof(uint16_t)))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv0); - return 1; - } + rowin = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); /* write data */ - write_ff_header(width, height); + ff_write_header(width, height); while (js.output_scanline < js.output_height) { - /* jpeg_read_scanlines expects an array of pointers to - * scanlines. - * Here the array is only one element long, but you could - * ask for more than one scanline at a time if that's more - * convenient. */ - jpeg_read_scanlines(&js, jpgrow, 1); + jpeg_read_scanlines(&js, &rowin, 1); for (i = 0; i < width; ++i) { - row[4*i + 0] = htons(jpgrow[0][3*i + 0] * 257); - row[4*i + 1] = htons(jpgrow[0][3*i + 1] * 257); - row[4*i + 2] = htons(jpgrow[0][3*i + 2] * 257); - row[4*i + 3] = htons(65535); + row[4 * i + 0] = htons(rowin[3 * i + 0] * 257); + row[4 * i + 1] = htons(rowin[3 * i + 1] * 257); + row[4 * i + 2] = htons(rowin[3 * i + 2] * 257); + row[4 * i + 3] = htons(65535); } - if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) - goto writerr; + if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) { + fprintf(stderr, "%s: fwrite: %s\n", argv0, strerror(errno)); + return 1; + } } + + /* clean up */ jpeg_finish_decompress(&js); jpeg_destroy_decompress(&js); return 0; -writerr: - fprintf(stderr, "%s: fwrite: ", argv0); - perror(NULL); - - return 1; } -- cgit v1.2.3 From a78b5dc6efaca25830c31ac17ef3ff81a493314d Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:39:41 +0200 Subject: Refactor ff2pam(1) I chose to go with a row-based-approach here, which is a bit easier to read and is somewhat "closer" to the input data. --- ff2pam.c | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/ff2pam.c b/ff2pam.c index aca15cb..2c4922c 100644 --- a/ff2pam.c +++ b/ff2pam.c @@ -5,28 +5,39 @@ #include #include #include +#include #include #include #include "util.h" +static void +usage(void) +{ + fprintf(stderr, "usage: %s\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { - uint32_t width, height; - char buf[BUFSIZ]; - size_t n, t; + size_t rowlen; + uint32_t width, height, i; + uint16_t *row; + /* arguments */ argv0 = argv[0], argc--, argv++; if (argc) { - fprintf(stderr, "usage: %s\n", argv0); - return 1; + usage(); } - read_ff_header(&width, &height); + /* prepare */ + ff_read_header(&width, &height); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); + rowlen = width * (sizeof("RGBA") - 1); - /* write PAM header */ + /* write data */ printf("P7\n" "WIDTH %" PRIu32 "\n" "HEIGHT %" PRIu32 "\n" @@ -36,29 +47,20 @@ main(int argc, char *argv[]) "ENDHDR\n", width, height); - /* write image */ - t = (size_t)width * (size_t)height * sizeof(uint16_t) * (sizeof("RGBA") - 1); - for (; (n = fread(buf, 1, sizeof(buf) <= t ? sizeof(buf) : t, stdin)); ) { - t -= n; - fwrite(buf, 1, n, stdout); - - if (feof(stdin)) { - break; - } - if (ferror(stdin)) { - fprintf(stderr, "%s: read: %s\n", argv0, strerror(errno)); + for (i = 0; i < height; i++) { + if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) { + if (ferror(stdin)) { + fprintf(stderr, "%s: fread: %s\n", argv0, strerror(errno)); + } else { + fprintf(stderr, "%s: unexpected end of file\n", argv0); + } return 1; } - if (ferror(stdout)) { - fprintf(stderr, "%s: write: %s\n", argv0, strerror(errno)); + if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) { + fprintf(stderr, "%s: fwrite: %s\n", argv0, strerror(errno)); return 1; } } - if (t > 0) { - fprintf(stderr, "%s: file too short\n", argv0); - return 1; - } - return 0; } -- cgit v1.2.3 From da99b58226c8dbb0cf764bbc7b42b7e3a36ff292 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:41:00 +0200 Subject: Refactor png-conversion-utilities We split out the libpng-setup into a separate function, it is very very ugly. The code also received a general cleanup and aligns itself much better with the general coding style and structure. --- ff2png.c | 86 ++++++++++++++++++++++++++++++---------------------------- png2ff.c | 94 ++++++++++++++++++++++++++++++++++------------------------------ 2 files changed, 95 insertions(+), 85 deletions(-) diff --git a/ff2png.c b/ff2png.c index 360ab00..a00e257 100644 --- a/ff2png.c +++ b/ff2png.c @@ -11,73 +11,77 @@ #include "util.h" -void -pngerr(png_structp pngs, const char *msg) +static void +png_err(png_struct *pngs, const char *msg) { (void)pngs; fprintf(stderr, "%s: libpng: %s\n", argv0, msg); exit(1); } +static void +png_setup_writer(png_struct **s, png_info **i, uint32_t w, uint32_t h) +{ + *s = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_err, NULL); + *i = png_create_info_struct(*s); + + if (!*s || !*i) { + fprintf(stderr, "%s: failed to initialize libpng\n", argv0); + exit(1); + } + + png_init_io(*s, stdout); + png_set_IHDR(*s, *i, w, h, 16, PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + png_write_info(*s, *i); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { - png_structp pngs; - png_infop pngi; + png_struct *pngs; + png_info *pngi; size_t rowlen; uint32_t width, height, i; uint16_t *row; + /* arguments */ argv0 = argv[0], argc--, argv++; if (argc) { - fprintf(stderr, "usage: %s\n", argv0); - return 1; + usage(); } - read_ff_header(&width, &height); - - /* load png */ - pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngerr, - NULL); - pngi = png_create_info_struct(pngs); - - if (!pngs || !pngi) { - fprintf(stderr, "%s: failed to initialize libpng\n", argv0); - return 1; - } - png_init_io(pngs, stdout); - png_set_IHDR(pngs, pngi, width, height, 16, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - png_write_info(pngs, pngi); - - /* write rows */ - 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); + png_setup_writer(&pngs, &pngi, width, height); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); rowlen = width * (sizeof("RGBA") - 1); - if (!(row = malloc(rowlen * sizeof(uint16_t)))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv0); - return 1; - } + + /* write data */ 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; } png_write_row(pngs, (uint8_t *)row); } + + /* clean up */ png_write_end(pngs, NULL); png_destroy_write_struct(&pngs, NULL); 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; } diff --git a/png2ff.c b/png2ff.c index 515979d..dd9073c 100644 --- a/png2ff.c +++ b/png2ff.c @@ -5,69 +5,75 @@ #include #include #include +#include #include #include "util.h" void -pngerr(png_structp pngs, const char *msg) +png_err(png_struct *pngs, const char *msg) { + (void)pngs; fprintf(stderr, "%s: libpng: %s\n", argv0, msg); exit(1); } +void +png_setup_reader(png_struct **s, png_info **i, uint32_t *w, uint32_t *h) +{ + *s = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_err, NULL); + *i = png_create_info_struct(*s); + + if (!*s || !*i) { + fprintf(stderr, "%s: failed to initialize libpng\n", argv0); + exit(1); + } + + png_init_io(*s, stdin); + if (png_get_valid(*s, *i, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(*s); + } + png_set_add_alpha(*s, 255*257, PNG_FILLER_AFTER); + png_set_expand_gray_1_2_4_to_8(*s); + png_set_gray_to_rgb(*s); + png_set_packing(*s); + png_read_png(*s, *i, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); + *w = png_get_image_width(*s, *i); + *h = png_get_image_height(*s, *i); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { - png_structp pngs; - png_infop pngi; + png_struct *pngs; + png_info *pngi; uint32_t width, height, rowlen, r, i; uint16_t *row; uint8_t **pngrows; + /* arguments */ argv0 = argv[0], argc--, argv++; if (argc) { - fprintf(stderr, "usage: %s\n", argv0); - return 1; + usage(); } - /* load png */ - pngs = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngerr, - NULL); - pngi = png_create_info_struct(pngs); - - if (!pngs || !pngi) { - fprintf(stderr, "%s: failed to initialize libpng\n", argv0); - return 1; - } - png_init_io(pngs, stdin); - if (png_get_valid(pngs, pngi, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(pngs); - png_set_add_alpha(pngs, 255*257, PNG_FILLER_AFTER); - png_set_expand_gray_1_2_4_to_8(pngs); - png_set_gray_to_rgb(pngs); - png_set_packing(pngs); - png_read_png(pngs, pngi, PNG_TRANSFORM_PACKING | - PNG_TRANSFORM_EXPAND, NULL); - width = png_get_image_width(pngs, pngi); - height = png_get_image_height(pngs, pngi); - pngrows = png_get_rows(pngs, pngi); - - /* allocate output row buffer */ - if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) { - fprintf(stderr, "%s: row length integer overflow\n", argv0); - return 1; - } + /* prepare */ + png_setup_reader(&pngs, &pngi, &width, &height); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); rowlen = width * (sizeof("RGBA") - 1); - if (!(row = malloc(rowlen * sizeof(uint16_t)))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv0); - return 1; - } + pngrows = png_get_rows(pngs, pngi); /* write data */ - write_ff_header(width, height); + ff_write_header(width, height); switch(png_get_bit_depth(pngs, pngi)) { case 8: @@ -77,7 +83,9 @@ main(int argc, char *argv[]) } if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) { - goto writerr; + fprintf(stderr, "%s: fwrite: %s\n", argv0, + strerror(errno)); + return 1; } } break; @@ -85,7 +93,9 @@ main(int argc, char *argv[]) for (r = 0; r < height; ++r) { if (fwrite(pngrows[r], sizeof(uint16_t), rowlen, stdout) != rowlen) { - goto writerr; + fprintf(stderr, "%s: fwrite: %s\n", argv0, + strerror(errno)); + return 1; } } break; @@ -94,12 +104,8 @@ main(int argc, char *argv[]) return 1; } + /* clean up */ png_destroy_read_struct(&pngs, &pngi, NULL); return 0; -writerr: - fprintf(stderr, "%s: fwrite: ", argv0); - perror(NULL); - - return 1; } -- cgit v1.2.3 From 7a11656e9649247179bdae941683b4ac78e22586 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:42:19 +0200 Subject: Refactor ff2ppm(1) We make use of the utility functions for parsing the color mask and other things and generally align the code with the general coding style. --- ff2ppm.c | 66 ++++++++++++++++++++-------------------------------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/ff2ppm.c b/ff2ppm.c index f0f3956..f490d94 100644 --- a/ff2ppm.c +++ b/ff2ppm.c @@ -21,65 +21,47 @@ usage(void) int main(int argc, char *argv[]) { - size_t rowlen; + size_t rowlen, rowoutlen; uint64_t a; 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(); - - read_ff_header(&width, &height); - - 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]); @@ -89,19 +71,11 @@ main(int argc, char *argv[]) (257 * 65535); } } - 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; } -- cgit v1.2.3 From 2eef6816e870074494465346ca2879959faec9da Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:43:31 +0200 Subject: Update TODO The truncation issue is solved now by checking the return values. Maybe for small images where the FILE-buffer is not flushed early enough we can rethink that. The utility functions were written to the extent it was desired. I added a note not to forget to take a look at the part in the jpg-code which does the color mixing. --- TODO | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO b/TODO index f3eea7b..626e7cb 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,2 @@ + o make jpg-mixing a bit more readable o re-add the old imagefile-tools for gif, ... - o flush fp's (fflush()) so we correctly report on truncation - o write utility functions to solve duplicate tasks -- cgit v1.2.3 From bc03439e0e0c439bb9c6c3167d9c272f3b7d5632 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Wed, 12 Apr 2017 23:48:28 +0200 Subject: Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index fdc6d84..79a2d84 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ISC-License -(c) 2014-2016 Laslo Hunhold +(c) 2014-2017 Laslo Hunhold Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 17f09e2cea4dda0f54841f7a273e347b53f4996e Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Thu, 13 Apr 2017 00:07:10 +0200 Subject: Use fshut() to properly flush the output stream For small images, it could happen that the output stream would not be flushed before exit(), resulting in a lack of error-reporting on a full device. Using fflush(), a function I first introduced in sbase, we do the flushing before returning manually and report errors if they occurred. --- ff2jpg.c | 2 +- ff2pam.c | 2 +- ff2png.c | 2 +- ff2ppm.c | 2 +- jpg2ff.c | 2 +- png2ff.c | 2 +- util.c | 27 +++++++++++++++++++++++++++ util.h | 2 ++ 8 files changed, 35 insertions(+), 6 deletions(-) diff --git a/ff2jpg.c b/ff2jpg.c index 78cb122..213f90d 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -118,5 +118,5 @@ main(int argc, char *argv[]) jpeg_finish_compress(&jcomp); jpeg_destroy_compress(&jcomp); - return 0; + return fshut(stdout, ""); } diff --git a/ff2pam.c b/ff2pam.c index 2c4922c..9a18e6b 100644 --- a/ff2pam.c +++ b/ff2pam.c @@ -62,5 +62,5 @@ main(int argc, char *argv[]) } } - return 0; + return fshut(stdout, ""); } diff --git a/ff2png.c b/ff2png.c index a00e257..58b3d37 100644 --- a/ff2png.c +++ b/ff2png.c @@ -83,5 +83,5 @@ main(int argc, char *argv[]) png_write_end(pngs, NULL); png_destroy_write_struct(&pngs, NULL); - return 0; + return fshut(stdout, ""); } diff --git a/ff2ppm.c b/ff2ppm.c index f490d94..746425b 100644 --- a/ff2ppm.c +++ b/ff2ppm.c @@ -77,5 +77,5 @@ main(int argc, char *argv[]) } } - return 0; + return fshut(stdout, ""); } diff --git a/jpg2ff.c b/jpg2ff.c index 8d51fb6..af7b03c 100644 --- a/jpg2ff.c +++ b/jpg2ff.c @@ -90,5 +90,5 @@ main(int argc, char *argv[]) jpeg_finish_decompress(&js); jpeg_destroy_decompress(&js); - return 0; + return fshut(stdout, ""); } diff --git a/png2ff.c b/png2ff.c index dd9073c..d76d707 100644 --- a/png2ff.c +++ b/png2ff.c @@ -107,5 +107,5 @@ main(int argc, char *argv[]) /* clean up */ png_destroy_read_struct(&pngs, &pngi, NULL); - return 0; + return fshut(stdout, ""); } diff --git a/util.c b/util.c index 7b59d19..ea933ca 100644 --- a/util.c +++ b/util.c @@ -82,6 +82,33 @@ parse_mask(const char *s, uint16_t mask[3]) return 0; } +int +fshut(FILE *fp, const char *fname) +{ + int ret = 0; + + /* fflush() is undefined for input streams by ISO C, + * but not POSIX 2008 if you ignore ISO C overrides. + * Leave it unchecked and rely on the following + * functions to detect errors. + */ + fflush(fp); + + if (ferror(fp) && !ret) { + fprintf(stderr, "%s: ferror %s: %s\n", argv0, fname, + strerror(errno)); + ret = 1; + } + + if (fclose(fp) && !ret) { + fprintf(stderr, "%s: fclose %s: %s\n", argv0, fname, + strerror(errno)); + ret = 1; + } + + return ret; +} + void * ereallocarray(void *optr, size_t nmemb, size_t size) { diff --git a/util.h b/util.h index 93492a5..fcb5257 100644 --- a/util.h +++ b/util.h @@ -11,6 +11,8 @@ void ff_write_header(uint32_t width, uint32_t height); int parse_mask(const char *, uint16_t mask[3]); +int fshut(FILE *, const char *); + #undef reallocarray void *reallocarray(void *, size_t, size_t); void *ereallocarray(void *optr, size_t nmemb, size_t size); -- cgit v1.2.3 From 3a701d548362812f9c9b21e960c7abe50989a33e Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 16:04:14 +0200 Subject: Add PNG-LDFLAGS and JPG-LDFLAGS in config.mk instead of per-tool-settings. --- Makefile | 5 +++++ config.mk | 7 ++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 4752fb6..5bf9332 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,11 @@ SCR = 2ff MAN1 = 2ff.1 $(BIN:=.1) MAN5 = farbfeld.5 +png2ff-LDFLAGS = $(PNG-LDFLAGS) +ff2png-LDFLAGS = $(PNG-LDFLAGS) +jpg2ff-LDFLAGS = $(JPG-LDFLAGS) +ff2jpg-LDFLAGS = $(JPG-LDFLAGS) + all: $(BIN) $(BIN): $(REQ:=.o) diff --git a/config.mk b/config.mk index b6b0ce4..57e9eac 100644 --- a/config.mk +++ b/config.mk @@ -11,11 +11,8 @@ MANPREFIX = ${PREFIX}/man CPPFLAGS = -D_DEFAULT_SOURCE CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os LDFLAGS = -s - -png2ff-LDFLAGS = -lpng -ff2png-LDFLAGS = -lpng -jpg2ff-LDFLAGS = -ljpeg -ff2jpg-LDFLAGS = -ljpeg +PNG-LDFLAGS = -lpng +JPG-LDFLAGS = -ljpeg # compiler and linker CC = cc -- cgit v1.2.3 From 1510ddefc12775143fd05286e92c38d4aed7c3a9 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 16:21:06 +0200 Subject: Remove TODO It's not very useful for the reader any more. --- TODO | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 626e7cb..0000000 --- a/TODO +++ /dev/null @@ -1,2 +0,0 @@ - o make jpg-mixing a bit more readable - o re-add the old imagefile-tools for gif, ... -- cgit v1.2.3 From 65435b097b355105dc9a32f87ed80427d56b1c91 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 16:39:05 +0200 Subject: Staticize functions in png2ff(1) --- png2ff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/png2ff.c b/png2ff.c index d76d707..c7237c4 100644 --- a/png2ff.c +++ b/png2ff.c @@ -11,7 +11,7 @@ #include "util.h" -void +static void png_err(png_struct *pngs, const char *msg) { (void)pngs; @@ -19,7 +19,7 @@ png_err(png_struct *pngs, const char *msg) exit(1); } -void +static void png_setup_reader(png_struct **s, png_info **i, uint32_t *w, uint32_t *h) { *s = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_err, NULL); -- cgit v1.2.3 From 42678350147b13345174f1e4c637a89c442ffd3c Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 17:32:12 +0200 Subject: Refactor 2ff(1) The Unix philosophy teaches us that tools should strive to output only necessary diagnostic information and also reflect errors properly with the return value. There were three subtle problems with 2ff: 1) If the farbfeld-passthrough failed, it would return 1 instead of 1. 2) If the first 8 bytes contained a NUL byte, bash would print an ugly warning message. Passing it through tr -d '\0' fixes that. 3) Lack of comments. I added some to make the structure even clearer, also including using an if-else-structure. I removed the 2ff error message; the tools themselves print proper messages already. --- 2ff | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/2ff b/2ff index bf58e5b..ef6f02d 100755 --- a/2ff +++ b/2ff @@ -1,36 +1,38 @@ #!/bin/sh + +# arguments if [ "$#" -ne 0 ]; then echo "usage: $0" >&2 exit 1 fi +# write input into temporary file TMP=$(mktemp) trap 'rm "$TMP"' EXIT - cat > "$TMP" -if [ "$(dd if="$TMP" bs=1 count=8 2>/dev/null)" = "farbfeld" ]; then +# determine the mime-type +if [ "$(dd if="$TMP" bs=1 count=8 2>/dev/null | tr -d '\0')" = "farbfeld" ]; then cat "$TMP" - exit 0 -fi +else + MIME=$(file -ib "$TMP" | cut -d ";" -f 1) -FORMAT=$(file -ib "$TMP" | cut -d ";" -f 1) - -case "$FORMAT" in -image/png) - png2ff < "$TMP" - ;; -image/jpeg) - jpg2ff < "$TMP" - ;; -*) - convert "$TMP" png:- 2>/dev/null | png2ff 2>/dev/null - ;; -esac + case "$MIME" in + image/png) + png2ff < "$TMP" + ;; + image/jpeg) + jpg2ff < "$TMP" + ;; + *) + convert "$TMP" png:- 2>/dev/null | png2ff 2>/dev/null + ;; + esac +fi +# errors if [ $? -ne 0 ]; then - printf "%s: failed to convert from %s\n" "$0" "$FORMAT" >&2 exit 1 +else + exit 0 fi - -exit 0 -- cgit v1.2.3 From 1f9d0c28423ae3e422327a8ee5422aac23391231 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 17:39:25 +0200 Subject: Make comment in ff2jpg(1) more consistent --- ff2jpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ff2jpg.c b/ff2jpg.c index 213f90d..2f57a2f 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -91,7 +91,7 @@ main(int argc, char *argv[]) rowlen = width * (sizeof("RGBA") - 1); rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); - /* write rows */ + /* write data */ for (i = 0; i < height; ++i) { if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) { if (ferror(stdin)) { -- cgit v1.2.3 From 96d6bde7d9bb6a79b7f86fbbc285a49b9634cd63 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 17:51:40 +0200 Subject: Don't suppress imagemagick and png2ff(1) warnings Else the user might be left wondering what happened. The output from imagemagick might not be the nicest in the world, but it's bearable for some given edge-cases. --- 2ff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2ff b/2ff index ef6f02d..6ce91b9 100755 --- a/2ff +++ b/2ff @@ -25,7 +25,7 @@ else jpg2ff < "$TMP" ;; *) - convert "$TMP" png:- 2>/dev/null | png2ff 2>/dev/null + convert "$TMP" png:- | png2ff ;; esac fi -- cgit v1.2.3 From 3d73fbaa1aeab1000d7f77cd6ee21f06a9b02e04 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 18:21:22 +0200 Subject: Update the README Rework the introductory paragraph and show examples directly afterwards. If people are interested in the tl;dr-sections, they can then read on. --- README | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/README b/README index 89123a5..e0c6d03 100644 --- a/README +++ b/README @@ -8,9 +8,28 @@ WHAT IS FARBFELD? Farbfeld is a lossless image-format designed to be - parsed and piped easily. - It can be compressed easily and beats PNG's filesize + parsed and piped easily. It is probably the simplest + image-format you can find (see FORMAT). + It does not have integrated compression, but allows + compression algorithms to work with it easily by adding + little entropy to the image data itself. This beats PNG in many cases. + Given the free choice of compression algorithms, it + is trivial to switch to better and faster ones as they + show up in the future. + +HOW DO I USE THE TOOLS? + encoding: + png2ff < example.png > example.ff + png2ff < example.png | bzip2 > example.ff.bz2 + + decoding: + ff2png < example.ff > example.png + bzcat example.ff.bz2 | ff2png > example.png + + bzip2 is used in this example and a recommended + compression algorithm. Of course you are free + to use something else. WHY FARBFELD? Current image-formats have integrated compression, @@ -32,13 +51,13 @@ WHY FARBFELD? and farbfeld. HOW DOES IT WORK? - In Farbfeld, pattern resolution is not done while + In farbfeld, pattern resolution is not done while converting, but while compressing the image. For example, farbfeld always stores the alpha-channel, even if the image doesn't have alpha-variation. This may sound like a big waste at first, but as soon as you compress an image of this kind, the - compression-algorithm (e.g. bz2) recognizes the + compression-algorithm (e.g. bzip2) recognizes the pattern that every 48 bits the 16 bits store the same information. And the compression-algorithms get better and better @@ -49,19 +68,7 @@ HOW DOES IT WORK? the same value, which is recognized by the compression algorithm easily. This effectively leads to filesizes you'd normally only - reach with paletted images, and in some cases bz2 even + reach with paletted images, and in some cases bzip2 even beats png's compression, for instance when you're dealing with grayscale data, line drawings, decals and even photographs. - -HOW DO I USE THE TOOLS? - encoding: - png2ff < example.png > example.ff - png2ff < example.png | bzip2 > example.ff.bz2 - - decoding: - ff2png < example.ff > example.png - bzcat example.ff.bz2 | ff2png > example.png - - bz2 is recommended for compression, but you can use - any algorithm you want. -- cgit v1.2.3 From 48bd9e1f4c7c4c45957575f68b1ee0cdeba42fd3 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 20:04:40 +0200 Subject: Update and refactor the manpages Make them more consistent, and only maintain a list of the conversion tools in farbfeld.5. Refine the wording on the jpg-manpages. --- 2ff.1 | 18 ++++++------------ farbfeld.5 | 29 +++++++++++++++++++---------- ff2jpg.1 | 34 ++++++++++++++++------------------ ff2pam.1 | 7 ++----- ff2png.1 | 8 ++------ ff2ppm.1 | 29 ++++++++++++++--------------- jpg2ff.1 | 5 +---- png2ff.1 | 5 +---- 8 files changed, 61 insertions(+), 74 deletions(-) diff --git a/2ff.1 b/2ff.1 index 44eed4e..3592071 100644 --- a/2ff.1 +++ b/2ff.1 @@ -1,4 +1,4 @@ -.Dd 2016-01-05 +.Dd 2017-04-14 .Dt 2FF 1 .Os suckless.org .Sh NAME @@ -13,9 +13,9 @@ reads an image from stdin, converts it to and writes the result to stdout. .Pp .Nm -is a wrapper script around the *2ff-tools -with a soft fallback to obtaining a PNG from imagemagick's -.Xr convert 1 +is a wrapper script around the farbfeld conversion tools +with a fallback to obtaining a PNG using +.Xr ImageMagick 1 and passing it through .Xr png2ff 1 . .Pp @@ -27,9 +27,7 @@ writes a diagnostic message to stderr. .It 0 Image processed successfully. .It 1 -An error occurred or -.Xr convert 1 -was not found in the fallback. +An error occurred. .El .Sh EXAMPLES $ @@ -40,12 +38,8 @@ $ .Nm < image.* | bzip2 > image.ff.bz2 .Sh SEE ALSO -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr convert 1 , -.Xr ff2png 1 , -.Xr jpg2ff 1 , -.Xr png2ff 1 , +.Xr ImageMagick 1 , .Xr farbfeld 5 .Sh AUTHORS .An Laslo Hunhold Aq Mt dev@frign.de diff --git a/farbfeld.5 b/farbfeld.5 index b9308b1..accae57 100644 --- a/farbfeld.5 +++ b/farbfeld.5 @@ -1,4 +1,4 @@ -.Dd 2016-01-04 +.Dd 2017-04-14 .Dt FARBFELD 5 .Os suckless.org .Sh NAME @@ -17,17 +17,24 @@ BYTES DESCRIPTION 4 32-Bit BE unsigned integer (height) [2222] 4*16-Bit BE unsigned integers [RGBA] / pixel, row-major .Ed +.Pp The RGB-data should be sRGB for best interoperability and not alpha-premultiplied. .Sh USAGE .Nm -provides -.Xr png2ff 1 , -.Xr jpg2ff 1 , +provides the tools .Xr 2ff 1 , -.Xr ff2png 1 -for -.Em conversions ; +.Xr jpg2ff 1 , +.Xr png2ff 1 +and +.Xr ff2jpg 1 , +.Xr ff2pam 1 , +.Xr ff2png 1 , +.Xr ff2ppm 1 +to +.Em convert +to and from farbfeld images respectively. +.Pp .Xr bzip2 1 is recommended for .Em compression , @@ -42,8 +49,8 @@ appended (e.g. ".ff.bz2"). .Nm was created because the author was not satisfied with the boilerplate and inherent complexity involved in handling common image formats -(PNG, JPEG, GIF,...), having to rely on bloated libraries not being able -to focus on the task at hand for a given problem. +(PNG, JPEG, GIF,...), having to rely on bloated libraries while not being +able to focus on the task at hand for a given image processing problem. .Sh EXAMPLES Below is an example for a color inverter usable in a pipeline. No external libraries other than libc are needed to handle the image data: @@ -115,8 +122,10 @@ main(int argc, char *argv[]) .Ed .Sh SEE ALSO .Xr 2ff 1 , -.Xr bzip2 1 , +.Xr ff2jpg 1 , +.Xr ff2pam 1 , .Xr ff2png 1 , +.Xr ff2ppm 1 , .Xr jpg2ff 1 , .Xr png2ff 1 .Sh AUTHORS diff --git a/ff2jpg.1 b/ff2jpg.1 index d202988..5c8e97a 100644 --- a/ff2jpg.1 +++ b/ff2jpg.1 @@ -1,19 +1,19 @@ -.Dd 2016-03-23 +.Dd 2017-04-14 .Dt FF2JPG 1 .Os suckless.org .Sh NAME .Nm ff2jpg -.Nd convert farbfeld to JPEG +.Nd convert farbfeld to JPG .Sh SYNOPSIS .Nm -.Op Fl b Ar color +.Op Fl b Ar colour .Op Fl o .Op Fl q Ar quality .Sh DESCRIPTION .Nm reads a .Xr farbfeld 5 -image from stdin, converts it to a JPEG image (RGB) and writes the result to +image from stdin, converts it to JPG (8-bit RGB) and writes the result to stdout. .Pp In case of an error @@ -21,18 +21,16 @@ In case of an error writes a diagnostic message to stderr. .Sh OPTIONS .Bl -tag -width Ds -.It Fl b Ar color -.Ar color -to mix with the background alpha channel, the default is white. -.Pp -The following formats are supported: -"#rrggbb", "#rrrrggggbbbb" and the short-form "#rgb" which expands to "#rrggbb". +.It Fl b Ar colour +Mix the background alpha channel with +.Ar colour +specified as #rgb, #rrggbb or #rrrrggggbbbb. The default is #fff. .It Fl o -Optimize Huffman table (smaller file, but slow compression). +Optimize the Huffman table, which reduces the file size but takes longer. .It Fl q Ar quality -set JPEG output +Set the output .Ar quality -(range 0-100), the default is 85. +ranging from 0 to 100. The default is 85. .El .Sh EXIT STATUS .Bl -tag -width Ds @@ -43,14 +41,14 @@ An error occurred. .El .Sh EXAMPLES $ -png2ff < test.png | .Nm --b '#00ff00' -q 85 > test.jpg +< image.ff > image.jpg +.Pp +$ bunzip2 < image.ff.bz2 | +.Nm +-b '#00ff00' -q 90 > image.jpg .Sh SEE ALSO -.Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr png2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/ff2pam.1 b/ff2pam.1 index 1153c5a..250372e 100644 --- a/ff2pam.1 +++ b/ff2pam.1 @@ -1,4 +1,4 @@ -.Dd 2017-01-09 +.Dd 2017-04-14 .Dt FF2PAM 1 .Os suckless.org .Sh NAME @@ -10,7 +10,7 @@ .Nm reads a .Xr farbfeld 5 -image from stdin, converts it to a 16-bit RGBA PAM and writes the result +image from stdin, converts it to PAM (16-bit RGBA) and writes the result to stdout. .Pp In case of an error @@ -32,10 +32,7 @@ $ bunzip2 < image.ff.bz2 | .Nm > image.pam .Sh SEE ALSO -.Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr png2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Mattias Andrée Aq Mt maandree@kth.se diff --git a/ff2png.1 b/ff2png.1 index 9812d5b..6320d2f 100644 --- a/ff2png.1 +++ b/ff2png.1 @@ -1,4 +1,4 @@ -.Dd 2016-01-17 +.Dd 2017-04-14 .Dt FF2PNG 1 .Os suckless.org .Sh NAME @@ -10,7 +10,7 @@ .Nm reads a .Xr farbfeld 5 -image from stdin, converts it to a 16-Bit RGBA PNG and writes the result +image from stdin, converts it to PNG (16-bit RGBA) and writes the result to stdout. .Pp In case of an error @@ -32,11 +32,7 @@ $ bunzip2 < image.ff.bz2 | .Nm > image.png .Sh SEE ALSO -.Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr jpg2ff 1 , -.Xr png2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Laslo Hunhold Aq Mt dev@frign.de diff --git a/ff2ppm.1 b/ff2ppm.1 index 7ada6c8..9bebf7a 100644 --- a/ff2ppm.1 +++ b/ff2ppm.1 @@ -1,17 +1,17 @@ -.Dd 2016-03-21 +.Dd 2017-04-14 .Dt FF2PPM 1 .Os suckless.org .Sh NAME .Nm ff2ppm -.Nd convert farbfeld to PPM (binary) +.Nd convert farbfeld to PPM .Sh SYNOPSIS .Nm -.Op Fl b Ar color +.Op Fl b Ar colour .Sh DESCRIPTION .Nm reads a .Xr farbfeld 5 -image from stdin, converts it to a PPM image (P6 binary format, RGB) and +image from stdin, converts it to PPM (16-Bit RGB P6 binary format) and writes the result to stdout. .Pp In case of an error @@ -19,12 +19,11 @@ In case of an error writes a diagnostic message to stderr. .Sh OPTIONS .Bl -tag -width Ds -.It Fl b Ar color -.Ar color -to mix with the background alpha channel, the default is white. -.Pp -The following formats are supported: -"#rrggbb", "#rrrrggggbbbb" and the short-form "#rgb" which expands to "#rrggbb". +.It Fl b Ar colour +.Ar colour +Mix the background alpha channel with +.Ar colour +specified as #rgb, #rrggbb or #rrrrggggbbbb. The default is #fff. .El .Sh EXIT STATUS .Bl -tag -width Ds @@ -35,14 +34,14 @@ An error occurred. .El .Sh EXAMPLES $ -png2ff < test.png | .Nm --b '#00ff00' > test.ppm +< image.ff > image.ppm +.Pp +$ bunzip2 < image.ff.bz2 | +.Nm +-b '#00ff00' > image.ppm .Sh SEE ALSO -.Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr png2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/jpg2ff.1 b/jpg2ff.1 index ada337d..d565fd8 100644 --- a/jpg2ff.1 +++ b/jpg2ff.1 @@ -1,4 +1,4 @@ -.Dd 2016-01-19 +.Dd 2017-04-14 .Dt JPG2FF 1 .Os suckless.org .Sh NAME @@ -32,10 +32,7 @@ $ < image.jpg | bzip2 > image.ff.bz2 .Sh SEE ALSO .Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr ff2png 1 , -.Xr png2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Laslo Hunhold Aq Mt dev@frign.de diff --git a/png2ff.1 b/png2ff.1 index 9761ec5..a2e4275 100644 --- a/png2ff.1 +++ b/png2ff.1 @@ -1,4 +1,4 @@ -.Dd 2016-01-19 +.Dd 2017-04-14 .Dt PNG2FF 1 .Os suckless.org .Sh NAME @@ -32,10 +32,7 @@ $ < image.png | bzip2 > image.ff.bz2 .Sh SEE ALSO .Xr 2ff 1 , -.Xr bunzip2 1 , .Xr bzip2 1 , -.Xr ff2png 1 , -.Xr jpg2ff 1 , .Xr farbfeld 5 .Sh AUTHORS .An Laslo Hunhold Aq Mt dev@frign.de -- cgit v1.2.3 From 781cec031d8ebc40b36cf06e7c3bf1080745e1d2 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 20:10:27 +0200 Subject: Update the Makefile to reflect TODO has been removed --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5bf9332..ca1949b 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ clean: dist: rm -rf "farbfeld-$(VERSION)" mkdir -p "farbfeld-$(VERSION)" - cp -R FORMAT LICENSE Makefile README TODO config.mk $(SCR) \ + cp -R FORMAT LICENSE Makefile README config.mk $(SCR) \ $(HDR) $(BIN:=.c) $(REQ:=.c) $(REQ:=.h) \ $(MAN1) $(MAN5) "farbfeld-$(VERSION)" tar -cf - "farbfeld-$(VERSION)" | gzip -c > "farbfeld-$(VERSION).tar.gz" -- cgit v1.2.3 From 9fdfff98f15fb3f7a01d944aba5d75d9d34c66ed Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 21:40:20 +0200 Subject: Refactor invert.c in farbfeld.5 I noticed that it would be beneficial to release the invert.c code listing under a very permissive license. I like the style of the "Copy me if you can"-License, but thought that 0BSD would make it even clearer that everyone can do whatever he wants with this code. The code itself was not bad beforehand, but lacked some elementary features like checked flushing at the end and proper error messages. I also reworked the data structures a bit to make it more appealing and clearer where the "guts" of the code are (i.e. in invert()). --- farbfeld.5 | 101 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/farbfeld.5 b/farbfeld.5 index accae57..664075d 100644 --- a/farbfeld.5 +++ b/farbfeld.5 @@ -52,72 +52,117 @@ and inherent complexity involved in handling common image formats (PNG, JPEG, GIF,...), having to rely on bloated libraries while not being able to focus on the task at hand for a given image processing problem. .Sh EXAMPLES -Below is an example for a color inverter usable in a pipeline. No external -libraries other than libc are needed to handle the image data: +The following code listing +.Em invert.c +is a ready-to-use color inverter with all necessary error handling and +reporting. This program can be integrated into a farbfeld pipeline as +follows: +.Pp +$ png2ff < image.png | invert | ff2png > image-inverted.png +.Pp +It shall be noted here that due to the simplicity of the format no +external libraries are needed to handle the farbfeld image data. The +0BSD-License gives you the freedom to throw away the license block and +just use the code as you wish. Happy hacking! .Bd -literal -offset left +/* + * 0BSD-License + * + * (c) 2017 Laslo Hunhold + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ #include +#include #include #include -#include #include +#define LEN(x) (sizeof (x) / sizeof *(x)) + +static void +invert(uint16_t rgba[4]) +{ + rgba[0] = UINT16_MAX - rgba[0]; + rgba[1] = UINT16_MAX - rgba[1]; + rgba[2] = UINT16_MAX - rgba[2]; +} + int main(int argc, char *argv[]) { - uint32_t width, height, i, j, k; + uint32_t hdr[4], width, height, i, j, k; uint16_t rgba[4]; - uint8_t hdr[strlen("farbfeld") + 2 * sizeof(uint32_t)]; - if (argc > 1) { + /* arguments */ + if (argc != 1) { fprintf(stderr, "usage: %s\\n", argv[0]); return 1; } - if (fread(hdr, 1, sizeof(hdr), stdin) != sizeof(hdr)) { - fprintf(stderr, "incomplete header\\n"); - return 1; + /* read header */ + if (fread(hdr, sizeof(*hdr), LEN(hdr), stdin) != LEN(hdr)) { + goto readerr; } - if (memcmp("farbfeld", hdr, strlen("farbfeld"))) { - fprintf(stderr, "invalid magic\\n"); + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { + fprintf(stderr, "%s: invalid magic value\\n", argv[0]); return 1; } - width = ntohl(*((uint32_t *)(hdr + 8))); - height = ntohl(*((uint32_t *)(hdr + 12))); + width = ntohl(hdr[2]); + height = ntohl(hdr[3]); - if (fwrite(hdr, 1, sizeof(hdr), stdout) != sizeof(hdr)) { - fprintf(stderr, "write error\\n"); - return 1; + /* write data */ + if (fwrite(hdr, sizeof(*hdr), LEN(hdr), stdout) != 4) { + goto writerr; } for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { - if (fread(rgba, sizeof(uint16_t), 4, - stdin) != 4) { - fprintf(stderr, "unexpected EOF\\n"); - return 1; + if (fread(rgba, sizeof(*rgba), LEN(rgba), + stdin) != LEN(rgba)) { + goto readerr; } for (k = 0; k < 4; k++) { rgba[k] = ntohs(rgba[k]); } - /* invert colors */ - rgba[0] = 65535 - rgba[0]; - rgba[1] = 65535 - rgba[1]; - rgba[2] = 65535 - rgba[2]; + invert(rgba); for (k = 0; k < 4; k++) { rgba[k] = htons(rgba[k]); } - if (fwrite(rgba, sizeof(uint16_t), 4, - stdout) != 4) { - fprintf(stderr, "write error\\n"); - return 1; + if (fwrite(rgba, sizeof(*rgba), LEN(rgba), + stdout) != LEN(rgba)) { + goto writerr; } } } + /* clean up */ + if (fclose(stdout)) { + fprintf(stderr, "%s: fclose: %s\\n", argv[0], + strerror(errno)); + return 1; + } + return 0; +readerr: + fprintf(stderr, "%s: fread: Unexpected EOF\\n", argv[0]); + return 1; +writerr: + fprintf(stderr, "%s: fwrite: %s\\n", argv[0], strerror(errno)); + return 1; } .Ed .Sh SEE ALSO -- cgit v1.2.3 From f04abc0e2f995e95fda64230a2bd4c289b10d6bf Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 21:45:32 +0200 Subject: Update usage of ff2jpg(1) and ff2ppm(1) so they align with the manpages. --- ff2jpg.c | 2 +- ff2ppm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ff2jpg.c b/ff2jpg.c index 2f57a2f..1f87fdd 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -47,7 +47,7 @@ jpeg_setup_writer(struct jpeg_compress_struct *s, struct jpeg_error_mgr *e, static void usage(void) { - fprintf(stderr, "usage: %s [-b #rrggbb] [-o] [-q quality]\n", argv0); + fprintf(stderr, "usage: %s [-b colour] [-o] [-q quality]\n", argv0); exit(1); } diff --git a/ff2ppm.c b/ff2ppm.c index 746425b..4383dc4 100644 --- a/ff2ppm.c +++ b/ff2ppm.c @@ -14,7 +14,7 @@ static void usage(void) { - fprintf(stderr, "usage: %s [-b #rrggbb]\n", argv0); + fprintf(stderr, "usage: %s [-b colour]\n", argv0); exit(1); } -- cgit v1.2.3 From c73b142d053818cdafddf5c66cfc2a4f90de7aa1 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 21:52:42 +0200 Subject: Fix the R in the logo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index e0c6d03..f7c08c0 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ ███ ███ ██ ██ ███ ███ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ - ██ ███ ███ ███ ██ ██ █ █ █ + ██ ███ ██ ███ ██ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ ███ ███ ██ -- cgit v1.2.3 From 6afe09e729e3428a5317c57c8315897f7110bffa Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 21:54:27 +0200 Subject: Move the logo a bit to the left so it is centered --- README | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README b/README index f7c08c0..1fe1125 100644 --- a/README +++ b/README @@ -1,9 +1,9 @@ - ███ ███ ██ ██ ███ ███ █ ██ - █ █ █ █ █ █ █ █ █ █ █ █ - ██ ███ ██ ███ ██ ██ █ █ █ - █ █ █ █ █ █ █ █ █ █ █ █ - █ █ █ █ █ ██ █ ███ ███ ██ + ███ ███ ██ ██ ███ ███ █ ██ + █ █ █ █ █ █ █ █ █ █ █ █ + ██ ███ ██ ███ ██ ██ █ █ █ + █ █ █ █ █ █ █ █ █ █ █ █ + █ █ █ █ █ ██ █ ███ ███ ██ WHAT IS FARBFELD? -- cgit v1.2.3 From a5a5706f16408ce181775d319b264d03e67819f3 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 22:15:25 +0200 Subject: Improve readability of alpha-blending sections --- ff2jpg.c | 6 ++++-- ff2ppm.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ff2jpg.c b/ff2jpg.c index 1f87fdd..23a506b 100644 --- a/ff2jpg.c +++ b/ff2jpg.c @@ -106,9 +106,11 @@ main(int argc, char *argv[]) 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)); } } jpeg_write_scanlines(&jcomp, &rowout, 1); diff --git a/ff2ppm.c b/ff2ppm.c index 4383dc4..b34d870 100644 --- a/ff2ppm.c +++ b/ff2ppm.c @@ -66,9 +66,11 @@ main(int argc, char *argv[]) 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, sizeof(uint8_t), rowoutlen, stdout) != rowoutlen) { -- cgit v1.2.3 From 4aa840bd871694cca0ae1608eab1086eef7d228b Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 22:26:03 +0200 Subject: Remove the need of '#' for alpha masks To be honest, it can happen too easily that the user forgets to put the colour in quotation marks, yielding in the rest of the pipeline to be discarded as a comment. --- ff2jpg.1 | 4 ++-- ff2ppm.1 | 4 ++-- util.c | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ff2jpg.1 b/ff2jpg.1 index 5c8e97a..4555a66 100644 --- a/ff2jpg.1 +++ b/ff2jpg.1 @@ -24,7 +24,7 @@ writes a diagnostic message to stderr. .It Fl b Ar colour Mix the background alpha channel with .Ar colour -specified as #rgb, #rrggbb or #rrrrggggbbbb. The default is #fff. +specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. .It Fl o Optimize the Huffman table, which reduces the file size but takes longer. .It Fl q Ar quality @@ -46,7 +46,7 @@ $ .Pp $ bunzip2 < image.ff.bz2 | .Nm --b '#00ff00' -q 90 > image.jpg +-b 0f0 -q 90 > image.jpg .Sh SEE ALSO .Xr bzip2 1 , .Xr farbfeld 5 diff --git a/ff2ppm.1 b/ff2ppm.1 index 9bebf7a..feba2f3 100644 --- a/ff2ppm.1 +++ b/ff2ppm.1 @@ -23,7 +23,7 @@ writes a diagnostic message to stderr. .Ar colour Mix the background alpha channel with .Ar colour -specified as #rgb, #rrggbb or #rrrrggggbbbb. The default is #fff. +specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. .El .Sh EXIT STATUS .Bl -tag -width Ds @@ -39,7 +39,7 @@ $ .Pp $ bunzip2 < image.ff.bz2 | .Nm --b '#00ff00' > image.ppm +-b 0f0 > image.ppm .Sh SEE ALSO .Xr bzip2 1 , .Xr farbfeld 5 diff --git a/util.c b/util.c index ea933ca..ba139b4 100644 --- a/util.c +++ b/util.c @@ -57,10 +57,6 @@ parse_mask(const char *s, uint16_t mask[3]) unsigned int col[3], colfac; char fmt[] = "%#x%#x%#x"; - if ((s++)[0] != '#') { - return 1; - } - slen = strlen(s); if (slen != 3 && slen != 6 && slen != 12) { return 1; -- cgit v1.2.3 From 62b95f7f7b3dc6e9fc6add9a186ff5b4b0ece535 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 22:39:15 +0200 Subject: Improve the wording on alpha-blending --- ff2jpg.1 | 2 +- ff2ppm.1 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ff2jpg.1 b/ff2jpg.1 index 4555a66..bd9dd04 100644 --- a/ff2jpg.1 +++ b/ff2jpg.1 @@ -22,7 +22,7 @@ writes a diagnostic message to stderr. .Sh OPTIONS .Bl -tag -width Ds .It Fl b Ar colour -Mix the background alpha channel with +Blend the transparent colours with .Ar colour specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. .It Fl o diff --git a/ff2ppm.1 b/ff2ppm.1 index feba2f3..c611fba 100644 --- a/ff2ppm.1 +++ b/ff2ppm.1 @@ -20,8 +20,7 @@ writes a diagnostic message to stderr. .Sh OPTIONS .Bl -tag -width Ds .It Fl b Ar colour -.Ar colour -Mix the background alpha channel with +Blend the transparent colours with .Ar colour specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. .El -- cgit v1.2.3 From 00dd0ab39f634729ec5d99b8057b9cef6fa0f23e Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 14 Apr 2017 22:53:43 +0200 Subject: Bump version to 3 This is more or less a refactoring release, but with deep changes in the tools that I was hoping to look into for a long time. The codebase is in a very consistent state now, also thanks to the introduction of a set of common utility-functions. What really makes me think is the fact that it takes so many iterations and a high level of detail to get the library handling and I/O right. It just makes you wonder how much software is out there that is full of little subtle bugs that might blow up in your face some day. Thanks for all the feedback! --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 57e9eac..194ab86 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # farbfeld version -VERSION = 2 +VERSION = 3 # Customize below to fit your system -- cgit v1.2.3