0

I am trying to save a 2D list as an image in python (greyscale image) so 0 values in the array would be black and 255 would be white. For example:

255 255 255
255  0  255
255  0  255
255  0  255
255 255 255 

Would save an l like shape. I have tried the following code utilising the PIL library as suggested by other questions on stack overflow:

WIDTH, HEIGHT = img.size
imgData = list(img.getdata()) 
imgData = [imgData[offset:offset + WIDTH] for offset in range(0, WIDTH * HEIGHT, WIDTH)]
#to print the image 
for row in data:
    print(' '.join('{:3}'.format(value) for value in row))
imgData = np.array(imgData)
**IMG VALUES AUGMENTED HERE**
newimg = Image.new('L', (WIDTH, HEIGHT), 'white')
newimg.putdata(imgData)
newimg.save('C:/File/Name.png')

However the image this creates does not reflect the list at all. If I was to have the 0s and 255s in different positions the same image is created. Anyone know a solution?

8
  • What's the exact structure of imgData? is it [[255, 255, 255], [255, 0, 255], ..., or [255, 255, 255, 255, 0, 255, ...]`? Commented Mar 28, 2020 at 20:20
  • So for the code I am using it is a much bigger list around 40 x 60 and I am using the code: WIDTH, HEIGHT = img.size imgData = list(img.getdata()) imgData = [imgData[offset:offset + WIDTH] for offset in range(0, WIDTH * HEIGHT, WIDTH)] Does that help? Commented Mar 28, 2020 at 20:23
  • Can you edit that code into the question? And put the rest of the for loop? Commented Mar 28, 2020 at 20:24
  • 1
    Sorry had issues formatting the reply there. You're right, would be better to add this to the main question Commented Mar 28, 2020 at 20:27
  • 1
    Thats all the relevant code added now. Hope that helps! Commented Mar 28, 2020 at 20:30

2 Answers 2

1

As your example is lacking any input data, I have just typed it in as you describe, made the image and then enlarged it. I also artificially added a red border so you can see the extent of it on StackOverflow's white background:

#!/usr/bin/env python3

from PIL import Image
import numpy as np

pixels = [[255,255,255],
          [255,0,255],
          [255,0,255],
          [255,0,255],
          [255,255,255]]

# Make list of pixels into Image
im = Image.fromarray(np.array(pixels,dtype=np.uint8))
im.save('result.png')

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

Instead of:

newimg.putdata(imgData)

you need the line:

newimg.putdata([j[0] for i in imgData for j in i])

The grayscale data is specified in a 1d list, not a 2d list.

This creates the list:

>>> [j[0] for i in imgData for j in i]
[255, 255, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 255, 255]

Which is:

[255, 255, 255,
 255,  0 , 255, 
 255,  0 , 255, 
 255,  0 , 255, 
 255, 255, 255]

EDIT The above solution works if you edit imgData with imgData[0][0] = [0, 0, 0, 255]. If you're editing imgData with imgData[0][0] = 0, then you'll need the line to be:

[j[0] if hasattr(j, '__iter__') else j for i in imgData for j in i]

or, you can make it nicer with:

imgData = np.array([[j[0] for j in i] for i in imgData])
imgData[0][0] = 0
newimg.putdata(imgData.flatten())

3 Comments

thanks for the suggestion although I am getting the error "IndexError: invalid index to scalar variable." for that new line. Any ideas on how to resolve that?
I'm still encountering an error with 'imgData = np.array([[j[0] for j in i] for i in imgData])' line. Now the error is ''int object' is not subscriptable' Just to make sure I'm piecing the code together properly should it be in this order: gyazo.com/19eb248e7f68fb85cb36a5f6ebc4cbc3
@JackTimber Interesting, that code works on my system. It must be that our img.getdata outputs are different. How are you loading the image?

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.