commit d5f6f70d351239ee37b3d864c9a94dc49d66c052
parent 0b0fcaa7136d7de2e1bc5dc05a576f5fe5608995
Author: FRIGN <dev@frign.de>
Date: Mon, 9 Nov 2015 23:39:29 +0100
imagefile -> farbfeld
- Rename the format
- Change the format specification
- Drop old tools waiting to be fixed on a later date, just keep
fixed png for now
- Simplify other stuff
This is a direct consequence of my slcon2-talk on this topic.
At first I planned to have 64 bits per channel, but this is
overkill.
Diffstat:
M | LICENSE | | | 2 | +- |
M | Makefile | | | 40 | ++++++++++++++-------------------------- |
M | SPECIFICATION | | | 32 | +++++++++++++++++++------------- |
A | TODO | | | 3 | +++ |
M | config.mk | | | 2 | +- |
A | ff2png.c | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | gif2if.c | | | 177 | ------------------------------------------------------------------------------- |
D | if2png.c | | | 87 | ------------------------------------------------------------------------------- |
D | jpg2if.c | | | 121 | ------------------------------------------------------------------------------- |
A | png2ff.c | | | 75 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | png2if.c | | | 77 | ----------------------------------------------------------------------------- |
11 files changed, 203 insertions(+), 503 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -1,6 +1,6 @@
ISC-License
-(c) 2014 Laslo Hunhold <dev@frign.de>
+(c) 2014-2015 Laslo Hunhold <dev@frign.de>
(c) 2014 sin <sin@2f30.org>
(c) 2014 Hiltjo Posthuma <hiltjo@codemadness.org>
diff --git a/Makefile b/Makefile
@@ -1,15 +1,15 @@
-# imagefile - tools to convert between png and if
+# imagefile - tools to convert between png and ff
# See LICENSE file for copyright and license details
include config.mk
-SRC = png2if.c if2png.c jpg2if.c gif2if.c
+SRC = png2ff.c ff2png.c
OBJ = ${SRC:.c=.o}
-all: options png2if if2png jpg2if gif2if
+all: options png2ff ff2png
options:
- @echo imagefile build options:
+ @echo farbfeld build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@@ -20,40 +20,28 @@ options:
${OBJ}: config.mk
-gif2if: gif2if.o
+png2ff: png2ff.o
@echo CC -o $@
- @${CC} -o $@ gif2if.o ${GIF_LIBS} ${LDFLAGS}
+ @${CC} -o $@ png2ff.o ${PNG_LIBS} ${LDFLAGS}
-jpg2if: jpg2if.o
+ff2png: ff2png.o
@echo CC -o $@
- @${CC} -o $@ jpg2if.o ${JPEG_LIBS} ${LDFLAGS}
-
-png2if: png2if.o
- @echo CC -o $@
- @${CC} -o $@ png2if.o ${PNG_LIBS} ${LDFLAGS}
-
-if2png: if2png.o
- @echo CC -o $@
- @${CC} -o $@ if2png.o ${PNG_LIBS} ${LDFLAGS}
+ @${CC} -o $@ ff2png.o ${PNG_LIBS} ${LDFLAGS}
clean:
@echo cleaning
- @rm -f png2if if2png jpg2if gif2if ${OBJ}
+ @rm -f png2ff ff2png ${OBJ}
install: all
@echo installing executable files to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
- @cp -f png2if jpg2if if2png gif2if ${DESTDIR}${PREFIX}/bin
- @chmod 755 ${DESTDIR}${PREFIX}/bin/png2if
- @chmod 755 ${DESTDIR}${PREFIX}/bin/jpg2if
- @chmod 755 ${DESTDIR}${PREFIX}/bin/if2png
- @chmod 755 ${DESTDIR}${PREFIX}/bin/gif2if
+ @cp -f png2ff ff2png ${DESTDIR}${PREFIX}/bin
+ @chmod 755 ${DESTDIR}${PREFIX}/bin/png2ff
+ @chmod 755 ${DESTDIR}${PREFIX}/bin/ff2png
uninstall:
@echo removing executable files from ${DESTDIR}${PREFIX}/bin
- @rm -f ${DESTDIR}${PREFIX}/bin/png2if
- @rm -f ${DESTDIR}${PREFIX}/bin/jpg2if
- @rm -f ${DESTDIR}${PREFIX}/bin/if2png
- @rm -f ${DESTDIR}${PREFIX}/bin/gif2if
+ @rm -f ${DESTDIR}${PREFIX}/bin/png2ff
+ @rm -f ${DESTDIR}${PREFIX}/bin/ff2png
.PHONY: all options clean install uninstall
diff --git a/SPECIFICATION b/SPECIFICATION
@@ -1,18 +1,18 @@
-The imagefile-format is meant to be parsed easily
+The farbfeld-format is meant to be parsed easily
and used to pipe images losslessly.
-# WHY IMAGEFILE?
+# WHY FARBFELD?
Most current image-formats have their compression
incorporated in their format itself.
This has some advantages, but reaches its limits
with lossless formats (e.g. PNG).
-The basic idea of the imagefile-format is to separate
+The basic idea of the farbfeld-format is to separate
these to and having a completely transparent image-format.
Pattern resolution is done while compressing, not while
converting the image.
-For example, imagefile always stores an alpha-channel,
+For example, farbfeld always stores an alpha-channel,
even if the image doesn't have alpha-variation.
This may sound like a big waste, but as soon as you
compress an image of this kind, the bzip2-algorithm
@@ -20,24 +20,30 @@ takes care of the easy pattern, that each 4th character
has the same value.
This leads to almost no overhead while keeping parsing
really simple.
+Same applies to the idea of having 64 bits per channel.
+It sounds excessive, but if you only have 8 bits of
+entropy, the compression will take care of it, while
+you only need to do the endian-handling for 64 bit
+chunks.
# FORMAT:
Bytes Description
-9 imagefile
-4 32 bit BE Integer (width)
-4 32 bit BE Integer (height)
-[1111] RGBA-row-aligned-pixel-array
+8 farbfeld
+4 32 bit BE Unsigned Integer (width)
+4 32 bit BE Unsigned Integer (height)
+[2222] RGBA-row-aligned-pixel-array
+ 16 bit BE Unsigned Integers (per channel)
# EXAMPLES:
encoding:
-png2if < example.png > example.if
-png2if < example.png | bzip2 > example.if.bz2
+png2ff < example.png > example.ff
+png2ff < example.png | bzip2 > example.ff.bz2
decoding:
-if2png < example.if > example.png
-bzcat example.if.bz2 | if2png > example.png
+ff2png < example.ff > example.png
+bzcat example.ff.bz2 | ff2png > example.png
# WHY BZ2?
@@ -47,4 +53,4 @@ For normal pictures, the bz2-compression yields roughly
the same sizes as png does.
Always keep in mind that using PNG involves having to
rely on libpng to decode the image for you, whereas
-imagefile is a completely transparent format.
+farbfeld is a completely transparent format.
diff --git a/TODO b/TODO
@@ -0,0 +1,3 @@
+ o handle truecolor PNG's properly (libpng is painful to use)
+ o write simpler Makefile
+ o re-add the old imagefile-tools for gif, jpg, ...
diff --git a/config.mk b/config.mk
@@ -16,7 +16,7 @@ CPPFLAGS =
#CFLAGS = -std=c99 -pedantic -Wall -Wextra -O0 -g -ggdb ${CPPFLAGS}
#LDFLAGS = ${LIBS}
# optimized
-CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os ${CPPFLAGS}
+CFLAGS = -std=c99 -pedantic -Wall -Wextra -D_DEFAULT_SOURCE -Os ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
# compiler and linker
diff --git a/ff2png.c b/ff2png.c
@@ -0,0 +1,90 @@
+/* See LICENSE file for copyright and license details. */
+#include <endian.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <png.h>
+
+#include "arg.h"
+
+char *argv0;
+
+#define HEADER_FORMAT "farbfeld########"
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s\n", argv0);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ png_structp png_struct_p;
+ png_infop png_info_p;
+ uint8_t hdr[17], *png_row;
+ uint16_t tmp16;
+ png_uint_32 width, height, i;
+ png_size_t png_row_len, j;
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ /* header */
+ if (fread(hdr, 1, strlen(HEADER_FORMAT), stdin) != strlen(HEADER_FORMAT)) {
+ fprintf(stderr, "failed to read from stdin or input too short\n");
+ return 1;
+ }
+ if (memcmp("farbfeld", hdr, strlen("farbfeld"))) {
+ fprintf(stderr, "invalid magic in header\n");
+ return 1;
+ }
+ width = be32toh((hdr[9] << 0) | (hdr[10] << 8) | (hdr[11] << 16) | (hdr[12] << 24));
+ height = be32toh((hdr[13] << 0) | (hdr[14] << 8) | (hdr[15] << 16) | (hdr[16] << 24));
+
+ /* load png */
+ png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_info_p = png_create_info_struct(png_struct_p);
+
+ if (!png_struct_p || !png_info_p || setjmp(png_jmpbuf(png_struct_p))) {
+ fprintf(stderr, "failed to initialize libpng\n");
+ return 1;
+ }
+ png_init_io(png_struct_p, stdout);
+ png_set_IHDR(png_struct_p, png_info_p, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ png_write_info(png_struct_p, png_info_p);
+
+ /* write rows */
+ png_row_len = strlen("RGBA") * width * sizeof(uint8_t);
+ png_row = malloc(png_row_len);
+ if (!png_row) {
+ fprintf(stderr, "failed to allocate row-buffer\n");
+ return 1;
+ }
+
+ for (i = 0; i < height; ++i) {
+ for (j = 0; j < png_row_len; ++j) {
+ if (fread(&tmp16, 1, sizeof(uint16_t), stdin) != sizeof(uint16_t)) {
+ fprintf(stderr, "unexpected EOF or row-skew\n");
+ return 1;
+ }
+ png_row[j] = be16toh(tmp16) / (1 << 8);
+ }
+ png_write_row(png_struct_p, png_row);
+ }
+ png_write_end(png_struct_p, NULL);
+
+ /* clean up */
+ png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1);
+ png_destroy_write_struct(&png_struct_p, NULL);
+ free(png_row);
+ return 0;
+}
diff --git a/gif2if.c b/gif2if.c
@@ -1,177 +0,0 @@
-/* See LICENSE file for copyright and license details.
- * code borrowed from util/gif2rgb.c from giflib-5.0 */
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <gif_lib.h>
-#include "arg.h"
-
-char *argv0;
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s\n", argv0);
- exit(EXIT_FAILURE);
-}
-
-static void
-die(const char *s) {
- fputs(s, stderr);
- exit(EXIT_FAILURE);
-}
-
-void *
-emalloc(size_t size) {
- void *p;
-
- if(!(p = malloc(size)))
- die("can't malloc\n");
- return p;
-}
-
-int
-main(int argc, char *argv[])
-{
- GifRecordType recordtype;
- GifFileType *giffile;
- GifRowType * gifrows;
- GifByteType *extension;
- GifColorType *colormapentry;
- ColorMapObject *colormap;
- uint32_t width, height, rwidth, rheight, val_be;
- uint32_t i, j, k;
- size_t gif_row_len;
- uint8_t *if_row;
- int extcode, row, col, imagenum = 0;
- int interlacedoffset[] = { 0, 4, 2, 1 };
- int interlacedjumps[] = { 8, 8, 4, 2 };
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 0)
- usage();
-
- /* load gif */
-#if GIFLIB_MAJOR >= 5
- if ((giffile = DGifOpenFileHandle(0, NULL)) == NULL)
- die("gif error\n");
-#else
- if ((giffile = DGifOpenFileHandle(0)) == NULL)
- die("gif error\n");
-#endif
-
- width = (uint32_t)giffile->SWidth;
- height = (uint32_t)giffile->SHeight;
- gif_row_len = giffile->SWidth * sizeof(GifPixelType);
- gifrows = emalloc(giffile->SHeight * sizeof(GifRowType));
- gifrows[0] = emalloc(gif_row_len);
-
- /* set color to BackGround. */
- for (i = 0; i < width; i++)
- gifrows[0][i] = giffile->SBackGroundColor;
- for(i = 1; i < height; i++) {
- gifrows[i] = emalloc(gif_row_len);
- memcpy(gifrows[i], gifrows[0], gif_row_len);
- }
-
- /* scan the content of the GIF file and load the image(s) in: */
- do {
- if (DGifGetRecordType(giffile, &recordtype) == GIF_ERROR)
- die("gif error\n");
-
- switch (recordtype) {
- case IMAGE_DESC_RECORD_TYPE:
- if (DGifGetImageDesc(giffile) == GIF_ERROR)
- die("gif error\n");
-
- /* image position relative to Screen. */
- row = giffile->Image.Top;
- col = giffile->Image.Left;
- rwidth = giffile->Image.Width;
- rheight = giffile->Image.Height;
- if (giffile->Image.Left + giffile->Image.Width > giffile->SWidth ||
- giffile->Image.Top + giffile->Image.Height > giffile->SHeight) {
- fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n", imagenum);
- exit(EXIT_FAILURE);
- }
- if (giffile->Image.Interlace) {
- /* need to perform 4 passes on the images: */
- for (i = 0; i < 4; i++) {
- for (j = row + interlacedoffset[i]; j < row + rheight; j += interlacedjumps[i]) {
- if (DGifGetLine(giffile, &gifrows[j][col], rwidth) == GIF_ERROR)
- die("gif error\n");
- }
- }
- } else {
- for (i = 0; i < rheight; i++) {
- if (DGifGetLine(giffile, &gifrows[row++][col], rwidth) == GIF_ERROR)
- die("gif error\n");
- }
- }
- /* this is set to disallow multiple images */
- recordtype = TERMINATE_RECORD_TYPE;
- imagenum++;
- break;
- case EXTENSION_RECORD_TYPE:
- /* Skip any extension blocks in file: */
- if (DGifGetExtension(giffile, &extcode, &extension) == GIF_ERROR)
- die("gif error\n");
- while (extension != NULL) {
- if (DGifGetExtensionNext(giffile, &extension) == GIF_ERROR)
- die("gif error\n");
- }
- break;
- case TERMINATE_RECORD_TYPE:
- break;
- default:
- break;
- }
- } while (recordtype != TERMINATE_RECORD_TYPE);
-
- if(giffile->Image.ColorMap)
- colormap = giffile->Image.ColorMap;
- else
- colormap = giffile->SColorMap;
-
- if(colormap == NULL)
- die("Gif Image does not have a colormap\n");
-
- /* write header with big endian width and height-values */
- fprintf(stdout, "imagefile");
- val_be = htonl(width);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
- val_be = htonl(height);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
-
- gif_row_len = width * strlen("RGBA");
- if_row = emalloc(gif_row_len);
-
- /* write data */
- for (i = 0; i < height; i++) {
- for(j = 0, k = 0; j < width; j++, k += 4) {
- colormapentry = &colormap->Colors[gifrows[i][j]];
- if_row[k] = colormapentry->Red;
- if_row[k+1] = colormapentry->Green;
- if_row[k+2] = colormapentry->Blue;
- if_row[k+3] = 255; /* TODO: mask? */
- }
- if (fwrite(if_row, 1, gif_row_len, stdout) != gif_row_len)
- die("fwrite() failed\n");
- }
-
- /* cleanup */
- for(i = 0; i < height; i++)
- free(gifrows[i]);
- free(gifrows);
- free(if_row);
-
- return EXIT_SUCCESS;
-}
diff --git a/if2png.c b/if2png.c
@@ -1,87 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <png.h>
-#include "arg.h"
-
-char *argv0;
-
-#define HEADER_FORMAT "imagefile########"
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s\n", argv0);
- exit(EXIT_FAILURE);
-}
-
-int
-main(int argc, char *argv[])
-{
- png_structp png_struct_p;
- png_infop png_info_p;
- uint8_t hdr[17], *png_row;
- png_uint_32 width, height, i;
- png_size_t png_row_len;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 0)
- usage();
-
- /* header */
- if (fread(hdr, 1, strlen(HEADER_FORMAT), stdin) != strlen(HEADER_FORMAT)) {
- fprintf(stderr, "failed to read from stdin or input too short\n");
- return EXIT_FAILURE;
- }
- if (memcmp("imagefile", hdr, 9)) {
- fprintf(stderr, "invalid magic in header\n");
- return EXIT_FAILURE;
- }
- width = ntohl((hdr[9] << 0) | (hdr[10] << 8) | (hdr[11] << 16) | (hdr[12] << 24));
- height = ntohl((hdr[13] << 0) | (hdr[14] << 8) | (hdr[15] << 16) | (hdr[16] << 24));
-
- /* load png */
- png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- png_info_p = png_create_info_struct(png_struct_p);
-
- if (!png_struct_p || !png_info_p || setjmp(png_jmpbuf(png_struct_p))) {
- fprintf(stderr, "failed to initialize libpng\n");
- return EXIT_FAILURE;
- }
- png_init_io(png_struct_p, stdout);
- png_set_IHDR(png_struct_p, png_info_p, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- png_write_info(png_struct_p, png_info_p);
-
- /* write rows */
- png_row_len = strlen("RGBA") * width * sizeof(uint8_t);
- png_row = malloc(png_row_len);
- if (!png_row) {
- fprintf(stderr, "failed to allocate row-buffer\n");
- return EXIT_FAILURE;
- }
-
- for (i = 0; i < height; ++i) {
- if (fread(png_row, 1, png_row_len, stdin) != png_row_len) {
- fprintf(stderr, "unexpected EOF or row-skew at %lu\n", (unsigned long)i);
- return EXIT_FAILURE;
- }
- png_write_row(png_struct_p, png_row);
- }
- png_write_end(png_struct_p, NULL);
-
- /* clean up */
- png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1);
- png_destroy_write_struct(&png_struct_p, NULL);
- free(png_row);
- return EXIT_SUCCESS;
-}
diff --git a/jpg2if.c b/jpg2if.c
@@ -1,121 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <setjmp.h>
-#include <jpeglib.h>
-#include "arg.h"
-
-char *argv0;
-
-static jmp_buf setjmp_buffer;
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s\n", argv0);
- exit(EXIT_FAILURE);
-}
-
-METHODDEF(void)
-if_jpeg_error(j_common_ptr cinfo)
-{
- /* Always display the message. */
- /* We could postpone this until after returning, if we chose. */
- (*cinfo->err->output_message) (cinfo);
-
- /* Return control to the setjmp point */
- longjmp(setjmp_buffer, 1);
-}
-
-int
-main(int argc, char *argv[])
-{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- uint32_t width, height, val_be;
- uint8_t *if_row = NULL;
- size_t jpeg_row_len, if_row_len, i, dx, sx;
- int status = EXIT_FAILURE;
- JSAMPARRAY buffer; /* output row buffer */
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 0)
- usage();
-
- /* load jpeg */
- cinfo.err = jpeg_std_error(&jerr);
-
- jerr.error_exit = if_jpeg_error;
- /* Establish the setjmp return context for my_error_exit to use. */
- if (setjmp(setjmp_buffer)) {
- /* If we get here, the JPEG code has signaled an error.
- * We need to clean up the JPEG object, close the input file, and return. */
- goto cleanup;
- }
-
- jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, stdin);
-
- jpeg_read_header(&cinfo, TRUE);
- width = cinfo.image_width;
- height = cinfo.image_height;
-
- /* change output for imagefile */
- cinfo.output_components = 3; /* # of color components per pixel */
- cinfo.out_color_space = JCS_RGB; /* colorspace of input image */
-
- jpeg_start_decompress(&cinfo);
- jpeg_row_len = width * cinfo.output_components;
-
- /* Make a one-row-high sample array that will go away when done with image */
- buffer = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, jpeg_row_len, 1);
- if_row_len = strlen("RGBA") * width;
- if(!(if_row = malloc(if_row_len))) {
- fprintf(stderr, "Can't malloc\n");
- return EXIT_FAILURE;
- }
-
- /* write header with big endian width and height-values */
- fprintf(stdout, "imagefile");
- val_be = htonl(width);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
- val_be = htonl(height);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
-
- while (cinfo.output_scanline < cinfo.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. */
- (void)jpeg_read_scanlines(&cinfo, buffer, 1);
-
- for(i = 0, dx = 0, sx = 0; i < width; i++, sx += 3, dx += 4) {
- if_row[dx] = buffer[0][sx];
- if_row[dx+1] = buffer[0][sx+1];
- if_row[dx+2] = buffer[0][sx+2];
- if_row[dx+3] = 255;
- }
- /* write data */
- if (fwrite(if_row, 1, if_row_len, stdout) != if_row_len) {
- fprintf(stderr, "fwrite() failed\n");
- goto cleanup;
- }
- }
- jpeg_finish_decompress(&cinfo);
- status = EXIT_SUCCESS;
-
-cleanup:
- free(if_row);
- jpeg_destroy_decompress(&cinfo);
-
- return status;
-}
diff --git a/png2ff.c b/png2ff.c
@@ -0,0 +1,75 @@
+/* See LICENSE file for copyright and license details. */
+#include <endian.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+
+#include "arg.h"
+
+char *argv0;
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage:%s\n", argv0);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ png_structp png_struct_p;
+ png_infop png_info_p;
+ png_bytepp png_row_p;
+ int depth, color, interlace;
+ uint32_t width, height, png_row_len, tmp32, r, i;
+ uint16_t tmp16;
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND
+
+ if (argc)
+ usage();
+
+ /* load png */
+ png_struct_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
+ NULL, NULL);
+ png_info_p = png_create_info_struct(png_struct_p);
+
+ if (!png_struct_p || !png_info_p || setjmp(png_jmpbuf(png_struct_p))) {
+ fprintf(stderr, "failed to initialize libpng\n");
+ return 1;
+ }
+ png_init_io(png_struct_p, stdin);
+ png_set_add_alpha(png_struct_p, 255, PNG_FILLER_AFTER);
+ png_set_gray_to_rgb(png_struct_p);
+ png_read_png(png_struct_p, png_info_p, PNG_TRANSFORM_STRIP_16 |
+ PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
+ png_get_IHDR(png_struct_p, png_info_p, &width, &height, &depth,
+ &color, &interlace, NULL, NULL);
+ png_row_len = png_get_rowbytes(png_struct_p, png_info_p);
+ png_row_p = png_get_rows(png_struct_p, png_info_p);
+
+ /* write header */
+ fprintf(stdout, "farbfeld");
+ tmp32 = htobe32(width);
+ fwrite(&tmp32, sizeof(uint32_t), 1, stdout);
+ tmp32 = htobe32(height);
+ fwrite(&tmp32, sizeof(uint32_t), 1, stdout);
+
+ /* write data */
+ /* TODO: allow 16 bit PNGs to be converted losslessly */
+ for (r = 0; r < height; ++r) {
+ for (i = 0; i < png_row_len; i++) {
+ tmp16 = htobe16((uint16_t)png_row_p[r][i]);
+ fwrite(&tmp16, sizeof(uint16_t), 1, stdout);
+ }
+ }
+
+ /* cleanup */
+ png_destroy_read_struct(&png_struct_p, &png_info_p, NULL);
+ return 0;
+}
diff --git a/png2if.c b/png2if.c
@@ -1,77 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <png.h>
-#include "arg.h"
-
-char *argv0;
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s\n", argv0);
- exit(EXIT_FAILURE);
-}
-
-int
-main(int argc, char *argv[])
-{
- png_structp png_struct_p;
- png_infop png_info_p;
- png_bytepp png_row_p;
- png_uint_32 width, height, i;
- png_size_t png_row_len;
- uint32_t val_be;
- int depth, color, interlace;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 0)
- usage();
-
- /* load png */
- png_struct_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- png_info_p = png_create_info_struct(png_struct_p);
-
- if (!png_struct_p || !png_info_p || setjmp(png_jmpbuf(png_struct_p))) {
- fprintf(stderr, "failed to initialize libpng");
- return EXIT_FAILURE;
- }
- png_init_io(png_struct_p, stdin);
- png_set_add_alpha(png_struct_p, 255, PNG_FILLER_AFTER);
- png_set_gray_to_rgb(png_struct_p);
- png_read_png(png_struct_p, png_info_p, PNG_TRANSFORM_STRIP_16 |
- PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND , NULL);
- png_get_IHDR(png_struct_p, png_info_p, &width, &height, &depth,
- &color, &interlace, NULL, NULL);
- png_row_len = png_get_rowbytes(png_struct_p, png_info_p);
- png_row_p = png_get_rows(png_struct_p, png_info_p);
-
- /* write header with big endian width and height-values */
- fprintf(stdout, "imagefile");
- val_be = htonl(width);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
- val_be = htonl(height);
- fwrite(&val_be, sizeof(uint32_t), 1, stdout);
-
- /* write data */
- for (i = 0; i < height; i++) {
- if (fwrite(png_row_p[i], 1, png_row_len, stdout) != png_row_len) {
- fprintf(stderr, "fwrite() failed\n");
- return EXIT_FAILURE;
- }
- }
-
- /* clean up */
- png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1);
- png_destroy_read_struct(&png_struct_p, &png_info_p, NULL);
- return EXIT_SUCCESS;
-}