0

Whenever I convert a PNG image to a np.array and then convert it back to a PNG I lose all the colors of the image. I would like to be able to retain the colors of the original PNG when I am converting it back from a np.array.

Original PNG Image

enter image description here

My code:

from PIL import Image    

im = Image.open('2007_000129.png')
im = np.array(im)

#augmenting image
im[0,0] = 1

im = Image.fromarray(im, mode = 'P')

Outputs a black and white version of the image

enter image description here

I also try using getpalette and putpalette but this does not work it just returns a NonType object.

im = Image.open('2007_000129.png')
pat = im.getpalette()
im = np.array(im)
im[0,0] = 1
im = Image.fromarray(im, mode = 'P')
im= im.putpalette(pat)
Dre
  • 713
  • 1
  • 8
  • 27
  • 1
    The error is this line `im= im.putpalette(pat)`: `putpalette` works *in place*, so don't write the result of this operation back to `im`. It's just `im.putpalette(pat)`. Using that fix, the second code works fine for me. – HansHirse Oct 02 '20 at 07:16
  • let me know if you still encounter problems – Alex Rancea Oct 02 '20 at 11:07
  • @HansHirse ah, rather simple fix. That works please feel free to post your solution if you would like me to check it. – Dre Oct 02 '20 at 17:00

2 Answers2

3

Your image is using single channel color using palette. Try the code below. Also you can check more about this subject at What is the difference between images in 'P' and 'L' mode in PIL?

from PIL import Image    
import numpy as np


im = Image.open('gsmur.png')
rgb = im.convert('RGB')
np_rgb = np.array(rgb)
p = im.convert('P')
np_p = np.array(p)

im = Image.fromarray(np_p, mode = 'P')
im.show()
im2 = Image.fromarray(np_rgb)
im2.show()
  • Hey Alex, thanks for the answer. Your solution is definitely correct, but I was looking for a solution that I did not have to convert the image to 'RGB'. I want to keep the image as a single channel while I am augmenting it as an array. Hans' comment fixed what I needed. If Hans doesn't leave an answer then I'll go ahead and confirm yours. thanks. – Dre Oct 02 '20 at 17:04
1

Using the second code provided, the error comes from this line:

im= im.putpalette(pat)

If you refer to the documentation of Image.putpalette, you see that this function doesn't return any value, thus Image.putpalette is applied to the corresponding image directly. So, (re-)assigning the non-existent return value (which then is None) is not necessary – or, as seen here, erroneous.

So, the simple fix is just to use:

im.putpalette(pat)

Using this change, the second code provided works as intended.

HansHirse
  • 18,010
  • 10
  • 38
  • 67