How can I create a PNG image file from a list of pixel values in Python?

前端 未结 2 1321
野趣味
野趣味 2021-01-19 00:58

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\"         


        
相关标签:
2条回答
  • 2021-01-19 01:47

    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
    
    0 讨论(0)
  • 2021-01-19 01:49

    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')
    
    0 讨论(0)
提交回复
热议问题