Search code examples
pythonpngpython-imaging-library

Python PIL reading PNG from STDIN


I am having a problem reading png images from STDIN using PIL. When the image is written by PIL it is all scrambled, but if I write the file using simple file open, write and close the file is saved perfectly.

I have a program that dumps png files to stdout in a sequence, with no compression, and I read that stream using a python script which is suposed to read the data and do some routines on almost every png. The program that dumps the data writes a certain string to delimiter the PNGs files, the string is "{fim:FILE_NAME.png}"

The script is something like:

import sys
import re
from PIL import Image

png = None

for linha in sys.stdin: 
    if re.search('{fim:', linha):
        fname = linha.replace('{fim:','')[:-2]

        # writes data directly to file, works fine
        #f = open("/tmp/%s" % fname  , 'w')
        #f.write(png)
        #f.close()

        # create a PIL Image from data and writes to disk, fails fine
        im = Image.frombuffer("RGB",(640,480),png, "raw", "RGB", 0, 1)
        #im = Image.fromstring("RGB",(640,480),png)
        im.save("/tmp/%s" % fname)

        png = None

    else:
        if png is None:
            png = linha
        else:
            png+= linha

imagemagick identify from a wrong image:

/tmp/1349194042-24.png PNG 640x480 640x480+0+0 8-bit DirectClass 361KiB 0.010u 0:00.019

imagemagick identify from a working image:

/tmp/1349194586-01.png PNG 640x480 640x480+0+0 8-bit DirectClass 903KiB 0.010u 0:00.010

Does any one have an idea of what is happening? Is it something about little/big endians? I have tried Image.frombuffer, Image.fromstring, different modes, but nothing. It seems that there is more information on the buffer that the PIL expects.

Thanks,


Solution

  • If the png variable contains the binary data from a PNG file, you can't read it using frombuffer; that's used for reading raw pixel data. Instead, use io.StringIO and Image.open, i.e.:

    import io
    from PIL import Image
    
    img = Image.open(io.StringIO(png))