Zanaca
Zanaca

Reputation: 45

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,

Upvotes: 0

Views: 4823

Answers (2)

interjay
interjay

Reputation: 110192

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))

Upvotes: 4

mattypiper
mattypiper

Reputation: 1232

png variable is uninitialized on the first call to Image.frombuffer(). You need to initialize it to something from stdin.

I'm not sure about your use of for linha in sys.stdin:. That gives you line-buffered input. You probably want to use block buffered input of size N, like sys.stdin.read(N). This will read a specific number of bytes and then you can parse the data, like cutting your filename delimiter out and filling the input buffer for Image.frombuffer().

Upvotes: 1

Related Questions