[dev] Introducing the imagefile-format

From: FRIGN <dev_AT_frign.de>
Date: Mon, 28 Jul 2014 18:55:59 +0200


after literally dozens of mails discussing a new suckless image-format,
I sat down last week to reflect on what could be the best of all
proposed format-specifications.
As a result I came up with the first implementation, the if-tools[0],
capable of easily converting between png and imagefiles.
In this mail, I'll give you a small overview on the format itself and
how it behaves in real situations.


Bytes Description
9 "imagefile"
4 32-bit BE - width
4 32-bit BE - height
[1111] RGBA


[if, if.bz2]
The latter is used for bzipped imagefiles. Explanation follows.


The examples intentionally leave out error-checks.

        3.1) Writing an imagefile-header
        uint32_t tmp, width = x, height = y;

        fprintf(fd, "imagefile");
        tmp = htonl(width);
        fwrite(&tmp, sizeof(uint32_t), 1, fd);
        tmp = htonl(height);
        fwrite(&tmp, sizeof(uint32_t), 1, fd);

        3.2) Reading an imagefile-header

        Every header is 17 bytes long (9 + 4 + 4).

        uint8_t hdr[17];
        uint32_t width, height;

        fread(hdr, 1, 17, fd);
        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));

        3.3) Reading data

        After the header has been read, reading the corresponding
        data segments is trivial.


The imagefile[0]-tools provide a way to convert between png and if using pipes.

        4.1) Trivial conversions
        $ png2if < image.png > image.if
        $ if2png < image.if > image.png
        $ if2png < image.if | feh -

        4.2) Bzipped conversions

        $ png2if < image.png | bzip2 > image.if.bz2
        $ bzcat image.if.bz2 | if2png > image.png

5) Why BZIP2?

Basically all lossless image-formats implement their compression inside the
format itself.
This is the reason why it's not trivial to write a png-parser, given you
have to know the compression-method to extract the pixels again.
The idea behind bzipping an imagefile is combining a transparent interface
with the advantages of file compression, and in many cases, this beats png
by far!
Even normal photographs reach comparable results to png, but the real strength
lies in line-drawings.

                      png if if.bz2
waterfall.png[1] 649K 1.4M 718K
bio_hazard.png[2] 21K 588K 9.2K

This is due to the fact that png takes an analytical approach to lossless
compression and applies a pre-filter, which however doesn't allow the
secondary deflate-algorithm to catch up large chunks of similar blocks.
The imagefile-format is 100% transparent and thus, if your image has large
chunks of similar data, or is greyscale (R = G = B), or only has one or two
color-channels (R = 0 || G = 0 || B = 0), bzip will take care of that.

What even surprised me is the fact bzip2 is so efficient with photographs,
which apparently also have the necessary patterns allowing lossless


- if-tools [0]
- xscreenshot [4]
- academics (Schlieren Photography Data)


The UNIX-philosophy strongly encourages to write software which does one
thing and does it well. Basically, a developer shouldn't have to worry
about the intrinsics of a given image-format, but instead should focus
on working on keeping his software as lean as possible.
Porting the xscreenshot-tool to imagefile cut almost half the LOC and
dramatically improved readability.
The conversion to png can now be done using if2png and using pipes.
That's the way to go!

Moreover, imagefile is a great way to store images. It may not be as good
as png when it comes to photographs, but it sure as hell beats it in regard
to all kinds of line art, greyscale and other off-scale photography if
you use bzip2 to compress it.

Join the cause to spread this suckless image-format!



[0]: http://git.2f30.org/imagefile/
[1]: http://frign.de/static/imagefile/waterfall.png
[2]: http://frign.de/static/imagefile/bio_hazard.png
[3]: http://git.2f30.org/xscreenshot/

FRIGN <dev_AT_frign.de>
Received on Mon Jul 28 2014 - 18:55:59 CEST

This archive was generated by hypermail 2.3.0 : Mon Jul 28 2014 - 19:00:11 CEST