1

I was wondering if there is a way to iteratively write png files using PyPNG (as in, row-by-row, or chunk-by-chunk) without providing the png.Writer() with the entire data. I've looked through the documentation, but all the writer methods require all rows of the PNG at once (uses too much memory).

Thanks in advance!

David Jones
  • 4,766
  • 3
  • 32
  • 45
  • It could be a problem because a PNG expects the entire image *compressed*. So before it can be compressed, `pypng` needs the entire image. It may still be *possible*, but only for a sufficiently wide interpretation of "possible"; you may need to write custom compression code from scratch. – Jongware Oct 22 '14 at 22:34
  • 1
    @jongware, maybe pypng needs the entire image, but that's not due to a shortcoming of the PNG format itself, which was designed to be streamable. Libpng supports incremental reading and writing of PNG files, and zlib supports incremental compression. In fact, pngtest.c that comes with libpng demonstrates reading and writing an image one row at a time, using the same row buffer memory for each row. The pypng docs https://pythonhosted.org/pypng/png.html seem to indicate that the entire image is only required to be in memory when writing "interlaced" PNG output. – Glenn Randers-Pehrson Oct 23 '14 at 00:22
  • @GlennRanders-Pehrson I have attempted it with PyPNG, but the documentation is not clear as to which writer method to use (I tried all of them). I will definitely take a look at libpng though. Thanks for the advice. – Shonte Amato-Grill Oct 23 '14 at 00:48
  • @Jongware: I did this (I needed this) with [Java](https://code.google.com/p/pngj/) and later ported it to C#. It's certainly possible in principle, except for interlaced PNG. – leonbloy Oct 23 '14 at 19:27
  • Great -- I was not aware this is an option in `libpng`! Then the only question left is: is this function exposed to `pypng`? Browsing through its source I could not find it under a reasonable name. – Jongware Oct 24 '14 at 19:33

1 Answers1

1

If you supply an iterator, then PyPNG will use it. Full example:

#!/usr/bin/env python

import random

import png

def iter_rows():
    H = 4096
    for i in xrange(H):
        yield [random.randrange(i+1) for _ in range(4096)]


img = png.from_array(iter_rows(), mode="L;12",
                     info=dict(size=(4096,4096)))
img.save("big.png")
David Jones
  • 4,766
  • 3
  • 32
  • 45