Search code examples
pythonreplacecolormap8-bitindexed

Replace colors in colormap


I use a simple line to break an indexed image 256 color into palette using

import numpy as np
from PIL import Image

im = Image.open('')
palette = np.array(im.getpalette(),dtype=np.uint8).reshape((256,3))

#####################
Printed result
[[  1   3   0]
[  2   4   1]
 [ 28   0   4]
 [ 20   2  26]
 [ 24   5  18]
 [ 33   7  22]
 [ 36   7  12]
 [  0  20  18]
 [ 42  15  16]
 [ 43  18  30]

... etc

Printing 'palette' lists the colors as RGB values as listed from index 0 onward. Index 0 is often dark color or black. In some engines it is used for alpha, transparency. I want to use commonly used colors for transparency like Magenta 255 0 255

I want to take each of my png files in a folder and do batch (I will have to manually add the color to the images, then save them as 8 bit so the color is part of the palette) then do:

  • exchange position of index 0 color with the Magenta in the color map
  • position of magenta color will vary for each file, just find the color 255 0 25 and replace color at index 0 with it but also take the index 0 color and put it on magenta place
  • do for all .png files in folder with a single run (magenta will be added and images indexed before running the script) enter image description here

This is an image where Magenta isnt first color of image palette Here is how it should be as final result


Solution

  • I think you want something like this:

    #!/usr/bin/env python3
    
    import numpy as np
    from PIL import Image
    
    # Open image
    im = Image.open('image.png')
    
    # Extract palette
    palette = np.array(im.getpalette(),dtype=np.uint8).reshape((256,3))
    
    # Look through palette
    for index,entry in enumerate(palette): 
        # Swap this entry with entry 0 if this is magenta
        if index>0 and np.all(entry==[255,0,255]): 
            print(f'DEBUG: Swapping entry {index} with entry 0') 
            palette[0], palette[index] = palette[index], palette[0]
            break
    else:
        print('ERROR: Did not find magenta entry in palette')
    
    # Replace palette with new one and save    
    im.putpalette(palette)
    im.save('result.png')
    

    You would probably code it to accept multiple files on the command line like this:

    for file in sys.argv[1:]:
        ...
        ...
    

    Then you could run:

    UpdatePalette.py *.png