Simple formats are PPM / Netpbm; they’re ASCII text with an identifier line (“P1” for mono, “P2” for grayscale or “P3” for colour), a width and height in pixels (e.g. 320 200), then a stream of numbers for pixel values. Line breaks optional. Almost any language that can count and print can make them, your can write them from APL if you want
As ASCII they can pass through email and UUNET and clipboards without BASE64 or equivalent. With flexible line breaks they can even be laid out so the monochrome ones look like the image they describe in a text editor.
The Netbpm format is amazing if you quickly want to try something out and need to generate an image of some sorts. The P6 binary format is even simpler, you write the header followed by a raw pixel data blob, e.g.:
I use this all the time. I love that it's simple enough that I can type something like those two lines off the top of my head at this point. And as an alternative to that fwrite(), another common pattern that I use is:
for (int y = 0; y < HEIGHT; ++y)
for (int x = 0; x < WIDTH; ++x)
{
// ... compute r, g, and b one pixel at a time
printf("%c%c%c", r, g, b);
}
I also find ImageMagick very convenient for working with the format when my program writes a PPM to stdout:
Yea I know, that's not a complete example, endian issues, error checking.
Reading a PPM file is only simple if you already have something to read buffered strings and parse numbers etc... And it's slow and large, especially for todays files.
As ASCII they can pass through email and UUNET and clipboards without BASE64 or equivalent. With flexible line breaks they can even be laid out so the monochrome ones look like the image they describe in a text editor.
See the examples at https://en.wikipedia.org/wiki/Netpbm#