Skip to content

PNG decoder proxy that skips iCCP chunks

Matthias Käppler requested to merge 341-skip-iccp-chunk into master

Fixes #341 (closed)

This got pretty complex but I wanted to see how it might work.

The general approach is to create an adapter around os.Stdin from which Decode will read. This adapter takes ownership of reading through the initial signature and non-data chunks, and skips the iCCP chunk (this part is easy to generalize to any chunk, but let's keep it specific for now).

Once we're reading past PLTE or IDAT we relinquish control and forward all reads to the underlying reader, since an iCCP chunk can never appear past these points.

I ran it over two different images with broken iCCP chunks and it appears to work:

[17:33:09] gl-gck/gitlab-workhorse::341-skip-iccp-chunk ✔ cat ~/Downloads/broken_crc.png | DEBUG=1 GL_RESIZE_IMAGE_WIDTH=100 ./gitlab-resize-image > /tmp/out.png; pngcheck -vpt /tmp/out.png
Read magic
Read next chunk
Read chunk def
LEN: 13 TYP: IHDR
read next chunk IHDR
Read next chunk
Read chunk def
LEN: 13615 TYP: zTXt
read next chunk zTXt
Read remaining chunk bytes
Read remaining chunk bytes
Read remaining chunk bytes
Read next chunk
Read chunk def
LEN: 389 TYP: iCCP
!! iCCP chunk found; skipping
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
Done (forward read)
File: /tmp/out.png (10743 bytes)
  chunk IHDR at offset 0x0000c, length 13
    100 x 100 image, 32-bit RGB+alpha, non-interlaced
  chunk IDAT at offset 0x00025, length 10686
    zlib: deflated, 32K window, default compression
  chunk IEND at offset 0x029ef, length 0
No errors detected in /tmp/out.png (3 chunks, 73.1% compression).

I also tested it against valid PNGs and also a JPEG to make sure that it doesn't break for other image formats.

Some more visual evidence it works (before vs after):

Screenshot_from_2020-12-30_14-21-22 Screenshot_from_2020-12-30_14-20-39

This solution is pretty complex and I am not sure how it will work or perform at scale. But I thought I'd take a stab at it. Let me know what you think.

Edited by Matthias Käppler

Merge request reports