Code Monkey home page Code Monkey logo

unpng's Introduction

unPNG - Uncompressed PNG (WIP)

A backward-compatible subset of the PNG file format, for storing uncompressed bitmaps. unPNG files can be decoded with a simple zero-copy parser.

annotated hexdump of example file ^ Annotated hexdump of an 8x8 8-bit greyscale unPNG file

Why?

Parsing image file formats is hard. Most image file formats in common usage are rather flexible, and PNG is no exception. Flexibility breeds bugs, and this is an experiment in cutting it down to the bare minimum.

All unPNGs are valid PNGs, and can be viewed in standard image viewers.

However, most PNGs are not valid unPNGs - you need to use a special encoder (like the one in this repo).

Why not?

  • There's 8 bytes of overhead per row. If you're dealing with very small images, that's a lot.

  • BMP already exists - although it's a rather crufty format. It would be interesting to compare unPNG to a minimal BMP encoder/decoder.

  • libpng (and others) are well documented and battle-tested.

  • Parsing itself is not the only source of unsafety when dealing with image formats.

What's in this repo?

This repo contains an encoder and a decoder program. The encoder is written in Python, and the decoder is a single-header C library.

Notably, the decoder never copies any buffers. It simply verifies the structure of the buffer you give it, and returns the metadata you need to view/process it - the width, height, pixel format, stride (aka pitch).

The decoder also doesn't bother verifying checksums, for simplicity - but it could if it wanted to. The encoder on the other hand emits files with valid checksums, passing checks from pngfix et al.

demo.c is a simple demo program that hooks up unpng.h to SDL2, allowing you to view decoded images.

Although unPNG is designed to be implemented securely, this implementation is prototype-quality, mostly untested, and should not be especially trusted. I may also make breaking changes to the spec.

How?

The non-compression is achieved using uncompressed DEFLATE blocks. The maximum length of an uncompressed DEFLATE block is 0xffff bytes - smaller than most image files. To avoid having to parse and re-assemble blocks, each row of the image is encapsulated within its own DEFLATE block. This gives a theoretical maximum horizontal resolution of 16383 pixels (assuming RGBA8888 pixel format), although unPNG further limits itself to 8192px in width and height, just to stay on the safe side. These limits also ensure that the whole image can always fit in a single IDAT chunk.

Always using a single IDAT chunk negates the need for chunk reassembly etc.

PNG supports ancilliary chunks and other sources of flexibility. unPNG does not - we only support a specific chunk layout. The unPNG decoder never attempts to "parse" chunks (or parse zlib, or parse DEFLATE), it simply treats the expected values as magic byte sequences, and bails out if they don't match.

That specific chunk layout is:

IHDR
unPn
IDAT
IEND

The unPn chunk contains a single byte - ascii G, meaning that if you inspect the file in a hexeditor you'll see the string unPnG. This chunk has two purposes - firstly it makes the file more easily identifiable as an unPNG file (to humans and machines alike), and secondly it acts as padding, ensuring that the first byte of pixel data occurs 0x40 bytes into the file. Alignment is nice to have!

If I end up adding support for palette modes, there'll be a PLTE chunk too.

Until I write proper docs/specs, looking at the source is perhaps the easiest way to understand the details.

TODO

  • Implement pixel formats other than RGB888, RGBA8888

  • Write a spec!

  • Document unpng.h

  • Make unpng.h more portable.

  • Set up tests and fuzzing.

  • Consider also writing an encoder in C, and a decoder in Python.

Some other things you may be interested in:

unpng's People

Contributors

davidbuchanan314 avatar felixonmars avatar suburbgira avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.