I have a set of 24-bit png files and I want to transform them into 8-bit png files. I used PIL's Image.convert() method for solving this problem. However, after using mode 'P' as the argument, I found out that pixels with same RGB values can be converted differently.
I transferred an example image into a numpy array and the original 24-bit png file has values like this:
RGB array
...,
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
[204, 102, 119],
...
After using the convert function with mode 'P', the images value became like this:
8-bit array
..., 98, 98, 134, 98, 98, 98, 134, 98, 98, 98, 134, ...
Code Example:
from PIL import Image
import numpy as np
img = Image.open("path-to-file.png")
p_img = img.convert("P")
I expect that pixels with same RGB values are converted in the same way. I know pixels are converted into palette index, but this still doesn't make sense to me. I'm not familiar with the PIL library. Can someone please explain why this happens? Thanks in advance.
Implemented a little something following Mark's examples
import numpy as np
from PIL import Image
#from improc import GenerateNColourImage
# Set image height and width
N = 6
h, w = 100, 100
# Generate repeatable random Numpy image with N^3 unique colours at most
n = np.random.randint(N, size=(h, w, 3), dtype=np.uint8)
# Work out indices of diagonal elements
diags = np.diag_indices(h)
# Intentionally set all diagonal elements same shade of blue
n[diags] = [10,20,200]
# Make Numpy image into PIL Image, palettise, convert back to Numpy array and check diagonals
a0 = Image.fromarray(n)
unique_colors = np.unique(n.reshape(-1, n.shape[2]), axis=0).shape
print(unique_colors) #e.g. print (217, 3)
a1 = a0.convert('P')
a2 = np.array(a1)
# Look at diagonals - should all be the same
print(a2[diags])
print(' %s %d' % ("Number of unique colors: ", np.unique(a2).shape[0]))
Diagonal pixels' values printed
... 154 154 154 154 154 154 124 154 160 160 160 154 160 ...
The 8-bit image in mode 'P' contains 125 unique palette indexes. It seems PIL will perform dithering no matter what.