5

I can generate a list of pixel values from an existing image file using a procedure like the following:

from PIL import Image
image = Image.open("test.png")
pixels = list(image.getdata())
width, height = image.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]

How could I convert this list of pixel values back to an image file?

0

2 Answers 2

8

Quick fix

First, you need to have your pixel tuples in a single un-nested list:

pixels_out = []
for row in pixels:
    for tup in row:
        pixels_out.append(tup)

Next, make a new image object, using properties of the input image, and put the data into it:

image_out = Image.new(image.mode,image.size)
image_out.putdata(pixels_out)

Finally, save it:

image_out.save('test_out.png')

Fundamental issue

Your list comprehension generates a list of lists, the latter being generated by the slicing (i*width:(i+1)*width). Your comprehension can be much easier: pixels = [pixel for pixel in pixels]. Obviously this outputs the same list, pixels, but you can use the idea to perform an operation on the pixels, e.g. pixels = [operation(pixel) for pixel in pixels].

Really, you overthought it. You don't have to manage the image dimensions. Getting the pixels in a list, and then putting them into an equal-sized image with putdata keeps the in order because they are linearized the same way by PIL.

In short, this is what your original snippet should have been:

from PIL import Image
image = Image.open("test.png")
image_out = Image.new(image.mode,image.size)

pixels = list(image.getdata())
image_out.putdata(pixels)
image_out.save('test_out.png')
Sign up to request clarification or add additional context in comments.

Comments

0

You can you cairo. Pretty easy.

#!/usr/bin/python

# Extracting pixels from an image ------
from PIL import Image
image = Image.open("test.png")
pixels = list(image.getdata())
width, height = image.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]


# Putting pixels back to an image ------

import cairo

Width=len(pixels[0])
Height=len(pixels)

surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, Width, Height)
context = cairo.Context (surface)

y=0
for row in pixels:
    x=0
    for rgb in row:
        r=rgb[0] /255.0
        g=rgb[1] /255.0
        b=rgb[2] /255.0
        context.set_source_rgb(r, g, b)
        context.rectangle(x, y, 1, 1)
        context.fill()
        x+=1
    y+=1

surface.write_to_png ("out.png") # Output to PNG

3 Comments

This is a neat idea, but overkill if you're already using PIL.
The OP didn't specify what he was using. He asked "How can I create a PNG image file from a list of pixel values in Python?" I gave an answer. Maybe, he wants to reuse the data later? Not allowed or what?
Cairo is certainly allowed. I'm not sure what it has to do with data reuse. The OP did specify that s/he's using PIL.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.