Hacker News new | ask | show | jobs
by Retr0id 927 days ago
I've also been pondering a backwards-compatible fork of PNG - but rather than a fork, mine would be a subset. Specifically, it would be an as-simple-as-possible uncompressed* bitmap format, suitable for use in low-complexity embedded systems etc. (e.g. bootloaders, wink wink). By being backwards compatible, you get the added benefit of retaining compatibility with existing image viewers, but without having to implement "all of PNG" in decoders and encoders. Now, the base PNG spec isn't even that big, but the more you constrain the spec, the easier it is to be sure you've implemented it securely.

* If you're wondering how that works in a backwards-compatible way, DEFLATE already supports uncompressed blocks.

5 comments

> I've also been pondering a backwards-compatible fork of PNG - but rather than a fork, mine would be a subset. Specifically, it would be an as-simple-as-possible uncompressed* bitmap format, suitable for use in low-complexity embedded systems etc. (e.g. bootloaders, wink wink).

Look at the NetPBM formats (PPM, PGM, PGM). They are about as simple as they can possibly get (a tiny, ASCII, header, followed by binary bitmap data), and are also uncompressed.

https://en.wikipedia.org/wiki/Netpbm

They're simple, but they're nowhere near as widely supported as PNG (or BMP)
BMP already exists for uncompressed bitmap data.
This is true, but BMP became a bit of a kitchen-sink format, supporting all sorts of pixel formats, and optionally, compression.

i.e. you'd still want to pick a subset to implement. To be honest, you're probably right - BMP would be more sensible starting point, but I'm interested to see how far PNG can be pushed.

You may want to look at my PNG/DEFLATE implementation:

http://public-domain.advel.cz/

It contains various implementations of the compression, from simple uncompresssed to more complex variants and a quite small PNG loader. There is also a minimalistic PNG writer with uncompressed data.

I would think that something like a bootloader would have fixed input and be able to rely on that, with signing if necessary, rather than the robustness of the decoder. Otherwise, someone who could replace the image would probably be able to replace the code as well.

Without Deflate compression, PNG would have no compression at all, as the predictor mechanism gives no savings on its own. TARGA with RLE would be a better choice than PNG-0.

I thought that too, but then the "LogoFAIL" vulnerabilities came out.[1]

It's possible to define a subset of the deflate bitstream that only does simple RLE compression, and I've done so: https://gist.github.com/DavidBuchanan314/b223bce114ec715a66f...

But, for logo/icon sized bitmaps, you can generally get away without needing compression at all. A 128x128 1bpc image is a mere 2KB.

[1] discussed here https://news.ycombinator.com/item?id=38515571

ok thats pretty wild, you would take the zlib deflate/inflate code, (for example in a library like lodepng) and then like chunk 95% of it in the garbage? so basically every block would just be uncompressed? kind of funny but it would probably work pretty well and your code size could get down way way smaller than the current typical png code.

seems like the downside is that this is "worse than nothing" compression, the image file would be bigger than the original blit of the data. for example 1024x1024x32bit color means 3 megabytes for one image. or do i miss something?

Many PNG compressors allow you to specify the zlib compression level, where 0 = no compression. This will effectively give you an uncompressed image, perhaps with some format overhead.

Your math is a bit off - a 1024x1024 at 32bpp would be 4MB, ignoring overhead.

I've actually done something like this in the past - create PNGs with 0 compression, then compress it with something stronger than Deflate (like LZMA). Because the PNG filtering is still applied, this allows greater compression relative to PNG by itself (or a BMP compressed with LZMA).

right but the "compression/decompression" code essentially becomes, like what, 10 lines of C? down from several thousand
Certainly, if your aim is the simplest code with no regard to compression, you could achieve a PNG writer with a small amount of code.

In such a case, you could also skip the PNG filtering as well (whilst for my case, you wouldn't want to).

I think it'd make more sense to go with BMP for a 'simple as possible' image format, that has wide support, than with PNG. PNG is definitely more geared towards a compressed image (as well as all sorts of other features you may not care about).

There's no need to take anyone else's code, emitting uncompressed DEFLATE blocks is trivial. I'm not sure what you mean by garbage?

> for example 1024x1024x32bit color means 3 megabytes for one image.

You do miss something, that's 4 megabytes, plus any header/format overhead - but you'd get similar performance out of any uncompressed format, that's just the tradeoff.

i mean the PNG code, youd have to have some PNG code in addition to the DEFLATE code yes?