0

I need to do a palette swap for character sprites for a game I am working on, so if more than one player chooses the same character, they will be in different colors. I have stored all the sprites in BufferedImages and would like to change the palette dynamically.

For example, I want to change any pixel that's red to blue, any pixel that's black to orange, and any pixel that's yellow to pink. I'll need to swap around 25 colors.

I've done some research already, and it looks like I'm going to have to create some sort of ColorModel and create a new BufferedImage from that model? I have no idea how to go about creating a ColorModel, so if there's a tutorial for that, that would be greatly helpful.

Thanks!

jedyobidan
  • 876
  • 1
  • 8
  • 14

2 Answers2

2

The following code swaps the palette by constructing a new BufferedImage that shares the original raster data. So it runs quickly and does not take much memory.

static BufferedImage switchPalette(BufferedImage bi,
        IndexColorModel icm) {
    WritableRaster wr = bi.getRaster();
    boolean bAlphaPremultiplied = bi.isAlphaPremultiplied();
    return new BufferedImage(icm, wr, bAlphaPremultiplied, new Hashtable());
}
Adam Gawne-Cain
  • 1,347
  • 14
  • 14
  • In my case the original buffered image has a different color model. I seem to get an exception thrown to say that the raster is incompatible with the color model. Any ideas of what I can do to get around this? – Perry Monschau May 15 '19 at 12:22
1

if speed doesn't matter i'd opt for the most silly solution: simply swap the colors manually.

you can get all the pixel values with BufferedImage.getRGB(...). then check if the color is on your list and replace it accordingly. later you can use setRGB to save the new color.

here's an example:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import javax.imageio.ImageIO;

public class Equ{
    public static void main(String[] args) throws IOException {
        BufferedImage img = new BufferedImage( 20, 20, BufferedImage.TYPE_INT_ARGB );
        Graphics2D g = img.createGraphics();
        g.setColor( Color.white ); 
        g.fillRect( 0, 0, 20, 20 ); 
        g.setColor( Color.black ); 
        g.fillRect( 5, 5, 10, 10 ); 


        Color[] mapping = new Color[]{
            Color.black, Color.white, // replace black with white 
            Color.white, Color.green // and white with green
        };

        ImageIO.write( img, "png", new File( "original.png" ) ); 
        swapColors( img, mapping );     
        ImageIO.write( img, "png", new File( "swapped.png" ) ); 
    }


    public static void swapColors( BufferedImage img, Color ... mapping ){
        int[] pixels = img.getRGB( 0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth() );
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); 
        for( int i = 0; i < mapping.length/2; i++ ){
            map.put( mapping[2*i].getRGB(), mapping[2*i+1].getRGB() ); 
        }


        for( int i = 0; i < pixels.length; i++ ){
            if( map.containsKey( pixels[i] ) )
                pixels[i] = map.get( pixels[i] ); 
        }

        img.setRGB( 0, 0, img.getWidth(), img.getHeight(), pixels, 0, img.getWidth() );  
    }
}
kritzikratzi
  • 19,662
  • 1
  • 29
  • 40
  • 1
    Sorry for the lateness, I asked the question last thing last night, so I just tried it out. Works great, thanks so much! – jedyobidan Mar 05 '13 at 23:28