

The problem is that when a color is replaced at a specific pixel position, ALL instances of that color are replace by the new RGB. This would mean that the color that was at pixel 0,0 would be at pixel 0,1 in the next palette, 0,2 in the next palette and so on. My intention was to make a few palettes that would basically have their colors shifted over by 1 position in the palette. I find that it is easier to do it using a uniform array so I use that.The clever idea I had sort of bit me in the butt, I guess. There are two strategies to pass the palette to the shader: by using a texture or a uniform array.

Now, that we have preprocessed our images, we are ready to write the shader to finally swap the palettes. Nothing fancy, all the hard work is done by Pillow. Then, it reinterprets it as a grayscale image. fromarray ( palette_colors, mode = 'RGBA' ) return grayscale_image, palette_imageįirstly, the function converts the image to the palette mode. astype ( 'uint8' ) palette_image = Image. asarray ( + ] \įor i in range ( palette_size )]]). getpalette () transparency = list ( indexed_image. asarray ( indexed_image ), 'L' ) # Create the palette open ( f ) # Reinterpret the indexed image as a grayscale image save ( f, 'png' ) indexed_image = Image.
#Palette swap au update#
# Save and load the image to update the info (transparency field in particular)į = io. convert ( mode = 'P', dither = 'NONE', colors = palette_size ) # Be careful it can remove colors Import io import numpy as np from PIL import Image def convert_to_indexed_image ( image, palette_size ): # Convert to an indexed image To do that, I use a little Python function that uses the Pillow library: The image is in grayscale mode and the gray level of each pixel corresponds to the index of its color in the palette. it replaces indices by the corresponding color in the palette.Ĭonsequently, to avoid this problem, I store separately the image and the palette. It uses stb_image under the hood which automatically “depalettizes” images i.e. It is the case of SFML, the library I used. Unfortunately, many libraries that load images will provide an array of colors even if the image was stored in indexed mode. For instance, the PNG image format has an indexed color option. In fact, several image formats support this way of storing images.

This way, we decouple the structure of the image (the areas with the same color) with the real colors. What we would like instead is that each pixel contains the index of its color in a palette. In a raster image, each pixel contains a color. The first step is to prepare your images for palette swapping. Now, it is used in procedural generation to produce new assets, I will show many examples in later devlogs. It was a useful technique in the old days to add variety in the assets without using too much memory. Here, we will do that at runtime using shaders. Palette swapping is simply changing the palette of a texture. In this devlog, I will show you a technique that I love and that I will abuse in Vagabond: palette swapping.
