1

I have an integer numpy array representing image with few values (about 2-5). And I would like to save it to png file with custom color for every value. I was trying it like this:

import numpy as np
from PIL import Image

array = np.zeros([100, 200, 4], dtype=np.uint8)
array[:,:100] = [255, 128, 0, 255] #Orange left side
array[:,100:] = [0, 0, 255, 255]   #Blue right side

img = Image.fromarray(array)
img.save(r'D:\test.png')

The result is ok, but it has 4 channels. I need the result to be single channel with custom colors.

I was trying it this way:

array = np.zeros([100, 200], dtype=np.uint8)
array[:,:100] = 1 
array[:,100:] = 0   

the result is single channel, but it is of course graysale. I can't figure out how to assign color to values 1 and 0 and save it as single channel. Was trying play around with matplotlib colormaps, but with no success.

Any help will be very appreciated

Tarik
  • 10,810
  • 2
  • 26
  • 40
makak
  • 397
  • 1
  • 10
  • You can't simply save *colors* with just one single channel. None of the image formats has that feature. You can *translate* single channel to colors given a color map. – Quang Hoang Nov 04 '20 at 14:29
  • This answer shows you how to create a palette image https://stackoverflow.com/a/58837594/2836621 – Mark Setchell Nov 04 '20 at 14:56
  • There's also a description of how palette images work here https://stackoverflow.com/a/52307690/2836621 – Mark Setchell Nov 04 '20 at 14:59

1 Answers1

3

You can make a palette image like this:

#!/usr/bin/env python3

from PIL import Image
import numpy as np

# Make image with small random numbers
im = np.random.randint(0,5, (4,8), dtype=np.uint8)

# Make a palette
palette = [255,0,0,    # 0=red
           0,255,0,    # 1=green
           0,0,255,    # 2=blue
           255,255,0,  # 3=yellow
           0,255,255]  # 4=cyan
# Pad with zeroes to 768 values, i.e. 256 RGB colours
palette = palette + [0]*(768-len(palette))

# Convert Numpy array to palette image
pi = Image.fromarray(im,'P')

# Put the palette in
pi.putpalette(palette)

# Display and save
pi.show()
pi.save('result.png')

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • that is AWESOME, exactly what I was looking for... but I have one more thing, I need one of those values to be transparent in resultig png... let say 4 should not be cyan, but transparent... do you have an idea how to do it?... thank you... – makak Nov 05 '20 at 07:54
  • Try `pi.save('result.png', transparency=4)` – Mark Setchell Nov 05 '20 at 08:55
  • thank you, in the meantime I found that this also works `pi.info = {"transparency": transValue}`... thank you again, you really made my day... – makak Nov 05 '20 at 09:33