IndexColorModel Help needed by eager student

I’ve been “lurking” around these forums for a while and finally have a problem that I can’t find the answer to.

My Problem
------------------

I’m making a sports game in which the player sprites contain no more than about 16 colours (though at the moment they’re all 256 colour PNGs) and are BufferedImages. Eventually the game will have different players and teams so I need to find a way to change the pallette for each player as required.

The solution I was considering
--------------------------------------------

I plan to have an array in in each instance of team with the colors of the Shirts/shorts/socks and another in every instance of player with colours for skin and hair. When a player is drawn the values from the two arrays will be read and used by some class (IndexColourModel???) to replace all instances of colour A(original) with Colour B(from array) and All instances of Colour C(original) with Colour D(from array) e.t.c.

I’ve spent some time looking up solutions on this forum and now think that the IndexColorModel class could hold the key. I looked on the SUN pages and even borrowed a book on “2d Graphics in Java” but I still don’t understand how to use it. Please can someone give me an example (even a very simple one) that will allow me to create/edit a pallette or even better use one created in a program like PaintShop Pro.

This is very important for my “Project” because if it’s not going to work or if it’s too slow(as I suspect it will be), I’ll have to think about whether I should be doing something else, which will be a pity.

Thanks!

Hi,
You need to create a new IndexColorModel and a new Image each time you want to change the palettes.
I’ve asked for a better way to do it (changing data in the model), but it seems there is no other way.
If you have questions about creating the model or the image, I can post parts of my code when I get home.

Rafael.-

A while back I had a go at hacking in a subclass of IndexColorModel that was mutable. I got it working (sort of), though as I expected it was pitifully slow.
This was back in 1.4, before all types of BufferedImage were accelerated - if you tried to do the same in 1.5 It’d most probably not work - or break horribly.
(the cached version in vram would be almost certainly a DirectColorModel version, and wouldn’t know about the changes you made to the base image)

Recreating the image isn’t that expensive, the BufferedImage constructor doesn’t copy any of its parameters, and the class itself is quite light weight.
The only problem you have, is that it will require a recache into vram with each construction - so changing the palette every frame won’t be feasable. (no color cycling effects ;))

Ofcourse, if you want to do it all yourself you could write your own rendering routines that support rendering of palettized images.
(though im sure there are some APIs already out there to do it for you)
If you go that route though, you will forgo hardware acceleration.

Thanks for the replys guys I was beginning to lose faith. I’d expected most of what you’re telling me but I think I’ll try it out anyway just to see how things work out and I’ve reduced the images to 16 colours so that should help in terms of speed.

rdcarvallo please post your code I’d really appreciate that.

Another solution I was thinking of would be to create a huge “sprite-sheet” (if that’s the correct name) with all the frames of animation in one image and then change the pallete at load time before putting it into memory instead of doing every frame at once. Would this work?

Hello.
I have same problem… just need to change color of an image for the other team. I was thinking make one image with white dressed player and then manipulating it to create other colors of dresses when I need it instead of making lots of images with different colors. Anyway I’ve searched for tutorials, read books and many stuff and didn’t find out how to do that. I’m starting to get frustrated that there’s no such tutorial that would simply explain how to do it (there are books and official 2d tutorial, but completely useless since they all list API methodes and explaining them in extreame techical concept).
So, how about some reference or sample code please?

If you just want to load in the same image, with 2 different palettes - thats easy.

You can either do it at the raw png stage, by swapping the PLTE (palette) chunk, with a palette you have pre-made (Photoshop has reasonable palette support, but debabelizer is the ideal tool. Don’t even bother trying with PSP; its palette manipulation support is complete crap.)

You will have to do a little reading on the png specification (rfc2083); its a realy well documented format, and simple to manipulate (atleast at the level required to swap a palette chunk)

Alternatively, you could try and use the classes provided in the java.awt.image package, grab a copy of the BufferedImage’s ColorModel; clone it, modify the palette as you need, and then create a duplicate png using the original images raster, and the new ColorModel.

I’m torn between which method is easier/better.

Manipulating the png data directly ties your application to a single file format.
Manipulating the image once loaded will tie your application to a single API.

If you do opt for using the java.awt.image package, I’ll warn you in advance - it is a very complex API, and will at times seem overbearing.
it contains a great deal of functionality, masked in many layers of abstraction which is all well and good when you need a powerful and flexible API.
However when you want to solve a specific problem, having to learn how a large complex API functions in order to solve what is fundamentally a very simple problem can be rather frustrating.
More documentation and examples would certainly improve the accessability of the package.

the player sprites contain no more than about 16 colours (though at the moment they’re all 256 colour PNGs)

Using an 8bit palette is usually smaller even if the number of colors would allow 4, 2 or even 1 bit. There are only a handful of images known to mankind where thats not the case.

Well, in this case realtime palette manipulation isnt required. So, just put the colors into some image (by using whatever method) and then copy it over for getting it accelerated. It doesnt really matter how slow it (relatively) is, if its only done once.

Whoops, I actually worked out how to do this a while ago but I didn’t come on here cos I was tied up with exams and such.

The code:

  1. loads the original image

2)Creates a new indexColorModel using 16 sets of RGB values
specified somewhere (eventually this will be from some XML file but for now it’s
still hard coded). This new colour model has 16 x 3 entries i.e. one for each colour
in the array and which is further divided into 3 for RED/GREEN/BLUE values.

3)The new colour model is applied to our image

4)Voila

Well sort of, there’s a bit of a problem with transparencies, because I don’t know how to tell it that a certain colour is a trasparent.

I’ll post the code here for people to check out and use if they want, but I’ll have to do it tomorrow because I’ll have to find the version of my code with that in it.

/******************************************************************************************************************************/
/This code creates the color model/

            byte[] reds = new byte[16];
	byte[] greens = new byte[16];
	byte[] blues = new byte[16];

	reds[0] = (byte)254; greens[0] = (byte)1; blues[0] = (byte)24;
	reds[1] = (byte)28; greens[1] = (byte)174; blues[1] = (byte)112;
	reds[2] = (byte)198; greens[2] = (byte)198; blues[2] = (byte)198;
	reds[3] = (byte)254; greens[3] = (byte)1; blues[3] = (byte)24;
	reds[4] = (byte)28; greens[4] = (byte)174; blues[4] = (byte)112;
	reds[5] = (byte)28; greens[5] = (byte)174; blues[5] = (byte)112;
	reds[6] = 0; greens[6] = 0; blues[6] = 0;
	reds[7] = 0; greens[7] = 0; blues[7] = 0;
	reds[8] = 0; greens[8] = 0; blues[8] = 0;
	reds[9] = 0; greens[9] = 0; blues[9] = 0;
	reds[10] = 0; greens[10] = 0; blues[10] = 0;
	reds[11] = 0; greens[11] = 0; blues[11] = 0;
	reds[12] = 0; greens[12] = 0; blues[12] = 0;
	reds[13] = 0; greens[13] = 0; blues[13] = 0;
	reds[14] = 0; greens[14] = 0; blues[14] = 0;
	reds[15] = 0; greens[15] = 0; blues[15] = 0;

	IndexColorModel cm = new IndexColorModel(4, 16, reds, greens, blues);

           g.drawImage(remodelSprite("imageName.png", cm), 55, 69,this);/

/*****************************************************************************************************************/
/This is the method that the last line above calls which creates the new image with the new colormodel/

public BufferedImage remodelSprite(String name, IndexColorModel cm)
{
BufferedImage img = (BufferedImage)sprites.get(name);
if (img == null)
{
img = loadImage(“images/”+name);
sprites.put(name,img);
System.out.println(“The image was null”);
}
BufferedImage newImage = new BufferedImage(cm, img.getRaster(), false, null);

		return newImage;

}/

Thats should be about it, sorry it’s a bit messy but it I couldn’t fin the old code so I has to rewrite it all, still it gives you the gist.

Oh yeah and I only needed about 5 colours so I skipped the rest, obviously you shouldn’t.