Changing the colours of an image

BlitzMax Forums/BlitzMax Programming/Changing the colours of an image

Apologies if this has already been covered. I'm looking for the quickest means to change a few colours of an image, for example changing the two colours of a football kit to whatever is relevant for the team.

In Blitz3D this was done using Imagebuffers and Masks, and I'm not about to open that can of worms again. I know it's impossible right now, and that's fine.

One easy way to do it is using LockImage and then Read/Write pixel. It certainly seems very fast (converts an entire 30*40 image in 0.64 ms on a 2.2GHz machine) but I wonder if there's a quicker method anywhere. I wouldn't want to miss out on a timesaver.

If anyone knows anything, that'd be great.

I dont know if you have multiple colors on your kits, but if you could isolate pixels of a given main color, into one image, then all you need to do is `SetColor` to apply a real-time tint to the image as it is drawn. If you keep your kits in white or grey, adding SetColor will properly color them whatever you like. This is probably a lot faster. If your kits have a range of tones of the same color then you could do them all at once in the same image. If you had a two-color kit, you could split it into two images and just do them separately.

This would also let you change kit colors on the fly at any time, which could be fun (psychadelic rainbow kits?)

Sample code:
' // Images //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%//
SetMaskColor 255, 0, 255
Global imgHunter:TImage = LoadImage(foldername$ + "/suit_c1.png", MASKEDIMAGE)

SetColor 255, 255, 255
SetClsColor 255, 0, 255
Cls

DrawImage imgHunter, 0, 0

myPix:TPixMap = GrabPixmap(0,0,ImageWidth(imgHunter), ImageHeight(imgHunter))

For y = 0 To ImageHeight(imgHunter) - 1
	For x = 0 To ImageWidth(imgHunter) - 1
		argb = ReadPixel(myPix, x, y)
		Red = ARGB Shr 16 & 255
		Green = ARGB Shr 8 & 255
		blue = ARGB Shr 0 & 255
		If Red = 104 And Green = 107 And Blue = 234 Then ' Brightest
			SetColor colorRed[0], colorGreen[0], colorBlue[0]
			DrawRect x, y, 1, 1
		ElseIf Red = 50 And Green = 54 And Blue = 216 Then 
			SetColor colorRed[1], colorGreen[1], colorBlue[1]
			DrawRect x, y, 1, 1
		ElseIf Red = 39 And Green = 39 And Blue = 141 Then 
			SetColor colorRed[2], colorGreen[2], colorBlue[2]
			DrawRect x, y, 1, 1
		ElseIf Red = 22 And Green = 23 And Blue = 56 Then 
			SetColor colorRed[3], colorGreen[3], colorBlue[3]
			DrawRect x, y, 1, 1
		EndIf		
		FlushMem
	Next
Next

SetColor colorRed[0], colorGreen[0], colorBlue[0]
DrawRect ImageWidth(imgHunter) - 16, ImageHeight(imgHunter) - 16, 16, 16

my_pixmap:tpixmap=GrabPixmap(0,0,ImageWidth(imgHunter), ImageHeight(imgHunter))

SavePixmapPNG my_pixmap, "tmp.png", 0
system_ "pngcrush.exe tmp.png " + foldername$ + "/suit_c" + colorNum + ".png"
DeleteFile "tmp.png"
Realtime manipulation is still too slow for all but the smallest sprites. It's best to render the color changes to file.

0.64 seconds, I posted. Was I asleep at the time? I meant 0.64 milliseconds.

The problem with rendering the changes to a file is that there will be quite a lot of frames of animation and many, many different teams, making it an awful lot of files that would end up stored. Not exactly practical.

Edit: what would be the best search terms to use to find non-language specific solutions for this in Google? For the life of me I can't find any good references - surely there are some out there?

AngelDaniel - I've been thinking more about your proposed solution and it seems like it could be the way to go - for power as much as anything. Being able to shade the graphics without having to call the pixelchanging function multiple times sounds like a timesaver.

Am I right in saying that Max2D uses the graphics hardware, and hence it ought to be very fast in doing such a thing? Working with composite images will require a little more work on my part (splitting the images into their components) but could be worth it in the end.

Apologies if I'm blabbing in this thread though. The problem is giving me a headache.

Max2D uses whatever system your OpenGL or DirectX drivers are set up to use. On my ibook the OpenGL is a software driver and doesn't use hardly anything hardware at all except to display the results. On my iMac everything is done in hardware as far as I know, except behind the scenes stuff maybe.

I think that even if you don't define a color with SetColor, and it defaults to white FF,FF,FF, it is STILL tinting your images, it's just using white which results in the same color you started with. So if your system is updating fast enough with no SetColor's, it ought to be almost the same speed by inserting these realtime color changes. The images are drawn with graphics hardware so it depends on the fill rate and stuff in the gfx card but I wouldn't think it's much of an overhead.

Whooo!

After plenty of playing around, I've got the system using SetColor and composite images, as you suggested.

The results astound me. One thousand 91*67 images take about 8000 millisecs to do using the Read-Write pixel translation.

Using the new method, a mere 26. Fantastic.