FARBFELD(5)

πŸ’– FARBFELD(5) πŸ’–

okay bestie, sit down, hydrate, because we're about to talk about the most ✨iconic✨ image format in the whole suckless universe. this is the manual page for farbfeld, and yes it's a File Formats Manual entry, so it's technically about a file format and not a command. slay.


🌸 NAME 🌸

farbfeld β€” the suckless image format πŸŽ€ (yes that's literally the whole name, she's lowkey a minimalist queen)


πŸ¦‹ DESCRIPTION πŸ¦‹

so farbfeld is a lossless image format and the whole point is that it's easy to parse, easy to pipe, and easy to compress. no cap. here's the format, and bestie it is adorably simple:

  • 8 bytes β€” the "farbfeld" magic value ✨
  • 4 bytes β€” 32-Bit BE unsigned integer (width)
  • 4 bytes β€” 32-Bit BE unsigned integer (height)
  • [2222] bytes β€” 4*16-Bit BE unsigned integers [RGBA] / pixel, row-major

ngl the RGB-data should be sRGB for best interoperability, and it should not be alpha-premultiplied. it's giving "please be normal about color spaces."


πŸ’… USAGE πŸ’…

farbfeld comes with a whole friend group of tools for converting to and from farbfeld images respectively:

and for compression? bzip2(1) is recommended, periodt. it gives results comparable with PNG for photographs and much better results for other image types. the glow-up is real πŸ”₯

the file extension is ".ff" and compression extensions shall be appended, e.g. ".ff.bz2". yes bestie, stack them like accessories πŸ’…


πŸ‘‘ MOTIVATION πŸ‘‘

okay so why does farbfeld even exist? the author was not satisfied with the boilerplate and the inherent complexity involved in handling common image formats (PNG, JPEG, GIF,...). imagine having to rely on bloated libraries while not being able to focus on the task at hand for a given image processing problem. absolutely not. main character energy only. πŸ™ˆ


🌈 EXAMPLES 🌈

here's the moment you've been waiting for. the following code listing invert.c is a ready-to-use color inverter with all necessary error handling and reporting (she's responsible AND cute). this program can be integrated into a farbfeld pipeline like this:

$ png2ff < image.png | invert | ff2png > image-inverted.png

and 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! πŸ’œ

/*
 * 0BSD-License
 *
 * (c) 2017 Laslo Hunhold <dev@frign.de>
 *
 * 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 <arpa/inet.h>

#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#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 hdr[4], width, height, i, j, k;
    uint16_t rgba[4];

    /* arguments */
    if (argc != 1) {
        fprintf(stderr, "usage: %s\n", argv[0]);
        return 1;
    }

    /* read header */
    if (fread(hdr, sizeof(*hdr), LEN(hdr), stdin) != LEN(hdr)) {
        goto readerr;
    }
    if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) {
        fprintf(stderr, "%s: invalid magic value\n", argv[0]);
        return 1;
    }
    width = ntohl(hdr[2]);
    height = ntohl(hdr[3]);

    /* 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(*rgba), LEN(rgba),
                      stdin) != LEN(rgba)) {
                goto readerr;
            }
            for (k = 0; k < 4; k++) {
                rgba[k] = ntohs(rgba[k]);
            }

            invert(rgba);

            for (k = 0; k < 4; k++) {
                rgba[k] = htons(rgba[k]);
            }
            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;
}
fr fr, copy it, run it, become the pipeline icon you were always meant to be 🫢

πŸ“ SEE ALSO πŸ“

2ff(1), ff2jpg(1), ff2pam(1), ff2png(1), ff2ppm(1), jpg2ff(1), png2ff(1)


πŸ’€ AUTHORS πŸ’€

Laslo Hunhold <dev@frign.de>


and that's the whole page bestie!! this one came from suckless.org and it's dated 2018-04-11, filed under FARBFELD(5). go forth and pipe responsibly, ily, bye πŸ’–βœ¨πŸ¦‹