What's the smallest file size for a 1 pixel image?
There are lots of new image compression formats out there. They excel at taking large, complex pictures and algorithmically reducing them to smaller file sizes. All of the comparisons I've seen show how good they are at squashing down big files.
I wanted to go the other way. How good are modern codecs at dealing with tiny files?
Using GIMP, I created an image which was a single white pixel, and saved it as a PNG. I then used Squoosh to convert it to a variety of modern formats using different encoding options. This is what I found:
Filetype | Bytes |
---|---|
AVIF | 303 |
JPG | 155 |
BMP 0 | 126 |
ICO 1 | 70 |
PNG 2 | 67 |
GIF 3 | 35 |
WEBP | 30 |
JXL | 24 |
QOI | 23 |
This is designed to be the "minimum viable viewable image". I loved Stoyan Stefanov's "Minimum viable no-image image src". That creates a 42 byte SVG with no image data in it - so I thought I'd see what happens if you make a displayable image.
Some important things to note:
- Older image formats like BMP and GIF are smaller than newer formats like AVIF.
- Some compression options make files larger in unexpected ways. The lossy WebP was larger than the lossless version.
- Similarly, increasing the effort on an AVIF can also result in a larger filesize.
- Neither JPEG XL nor QOI are supported in mainstream browsers yet.
- AVIF has a rather long and complex header - that makes sense for large images, but bloats it for smaller ones.
- Using Brotli, it is possible to further compress the AVIF (203 Bytes), JPG (69 Bytes), BMP (63 Bytes), and ICO (30 Bytes) files.
- WebP is the smallest file if you still need a Spacer.gif!
Here's my challenge to you - can you do any better? What's the smallest filesize you can find for a viewable image?
-
The BMP was created in ImageMagick and compressed with FileFormat.app. ↩︎
-
The ICO was created with
convert -size 1x1 canvas:white w.ico
↩︎ -
It is possible to go slightly smaller if you don't care about colour. ↩︎
Mⱺ℠ said on bsky.app:
i'd dig into the BMP formats a bit if i was going to take this seriously: it has different internal formats depending on colour depth and historical compatibility, and the ideal BMP must be smaller than the ideal ICO because the latter has a bigger overhead on what should be identical data that the BMP is nearly double the ICO suggests it's probably a 24-bit BMP optionally with transparency
(a 1-bit RLE image should i think be 2 bytes without header, and you could possibly cheat and make a 0-sized image if you hand-crafted it)
Julia said on mathstodon.xyz:
@Edent QOI is cool because it provides the smallest image in this case, but also because you could hand-assemble it using a hex editor and the one-page spec (https://qoiformat.org/qoi-specification.pdf):
Header: 3 * 4 bytes + 2 * 1 byte
QOI_OP_DIFF: [insert the correct bit pattern here, I’m sleepy and a little bit confused about how it works]
Stream end: 8 bytes
Tommy Carlier says:
If I open your BMP in Paint.net and save it with bit-depth "Auto detect", I get a BMP of 58 bytes.
dahlstrand.net said on dahlstrand.net:
Terence posted a challenge today:
The Netpbm project comes with a bunch of file formats I often reach for when I want to generate images without a lot of code or external dependencies. They have binary and ASCII versions, here’s how to generate a plain text, 1×1 white image using the monochrome pbm format:
If you copy and paste that into your favorite text editor and save it as
white-pixel.pbm
you should get a file that weighs 8 bytes. Here’s what that looks like on my machine:Bryce Wray said on fosstodon.org:
@Edent You said, “Neither JPEG XL nor QOI are supported in mainstream browsers yet.” I believe Safari began supporting JPEG XL as of v.17.x, which was part of the recent major Apple OS updates.
Julia said on mathstodon.xyz:
@Edent I did exactly this, and it was a fun exercise. I also discovered that Brotli can “compress” the file to 23 (different) bytes at compression level 11, meaning there’s no overhead, which seems pretty unusual.
ཀ།༨ཇ ་།་འ།སབཇའ said on mastodon.online:
@Edent I think you could do a .tga transparent pixel in 20 bytes but so few things read it these days, even though it’s the default output from 3DSmax still. Bane of my life as it also defaults to uncompressed so is huge
ཀ།༨ཇ ་།་འ།སབཇའ said on mastodon.online:
@Edent I should say that’s 18 bytes of headers and two bytes that contain a 5,5,5,1 RGBa pixel.
James says:
If you are willing to drop the 1px requirement the smallest possible JXL image is 12 bytes. It can skip some bits if the image is a multiple of 8 in both dimensions.
For example, these 12 bytes (in
xxd
order) are a black 512 × 256 JPEG XL image.James says:
You can get a 1px white square in JXL in 19 bytes, and a transparent one in a mere 17 bytes, but they require manual construction. Hurrah for bit packed headers and variable length encoding!
Source: https://docs.google.com/presentation/d/1LlmUR0Uoh4dgT3DjanLjhlXrk_5W2nJBDqDAMbhe8v8/edit#slide=id.gde87dfbe27_0_43
Ivan says:
At such small sizes, the size of the file header becomes more heavy than the data itself. This is basically the showdown of complex file headers.
The very minimum you'd need (assuming no compression, just raw data) is few bytes for image dimensions, followed by pixel data itself. Let's say you 'invent' a file format that assumes 24 bit rgb images, and has limits of 65535 pixels width * 65535 rows, that would be two 16 bit integers, followed by 3 byte pixel data (8 bits for each, red, green, and blue components of pixel).
This is extremely bare bones, but still functional enough to serve a purpose of storing true color images.
If you did some predefined dimensions file type, like .ico files of old, then you could use a single byte as an index into some standard predefined dimensions list (1x1, 4x4, 16x16, 32x32, 64x64...), and if you used basic rle compression you could reduce 24 bit white pixel data two bytes. That's 3 bytes in total. Again, completely bare bones.
There are such file types in the wild, mostly the ones from 90-ties when such things mattered. Off the top of my head pbm comes to mind, tga is also quite basic...
Emily S says:
@blog fun little experiment. From what I remember the smallest valid tif is something around 50 to 60 bytes.
8 bytes header
2 bytes ifd header
8 bytes per ifd, I think you need five, witdh height, colour encoding, colour layout, and pointer to row pointers
4 bytes of row pointer
3 bytes of data
One of the things I discovered when I was playing with tif files alot a few years back.
(Numbers likely wrong, I wrote this from memory on a train)
Andrew says:
Mathias Bynens did a similar thing for a whole bunch of file formats.
Daniel Jackson says:
I manually made a .bmp file of only 30 bytes by using the old "BITMAPCOREHEADER" format. As a data: URI: data:image/bmp;base64,Qk0eAAAAAAAAABoAAAAMAAAAAQABAAEAGAD///8A
More comments on Mastodon.