Editing PNGDecoder image colors?

Started by paul_nicholls, May 14, 2012, 12:16:03

Previous topic - Next topic

paul_nicholls

Hi all,
 I have been following the LWJGL tutorial here to load a PNG file and use it as an OpenGL texture:
http://www.lwjgl.org/wiki/index.php?title=Loading_PNG_images_with_TWL%27s_PNGDecoder

I got that working ok, but now I want to test the pixels in that decoded image to see if it matches a colorkey color (r,g,b), and if so, change that matching pixel's alpha to 0.  This is prior to setting the OpenGL texture afterwards.

I guess I need to use the buf.get(index) method to get the R,G,B components of each pixel, test against the colorkey r,g,b, and the use the buf.put(index,0) to set the alpha, but I am not sure how to get this working...

I am rather new to Java.

Any ideas?
cheers,
Paul

matheus23

Thats right, I assume, you want to set Alpha to 0, if you have the colors 255, 255, 255?

The bigger problem is, that you only have a Buf with (R, G, B) values, but you need alpha too (R, G, B, A).
That means, you have to copy the Buffer 1 into Buffer 2, which is a bit bigger.

public static ByteBuffer convert(ByteBuffer data) {
		final byte alphaRed = (byte)255;
		final byte alphaGreen = (byte)255;
		final byte alphaBlue = (byte)255;
		ByteBuffer converted = BufferUtils.createByteBuffer((data.capacity()/3)*4);
		int dataIndex = 0;
		int convertedIndex = 0;
		for (int i = 0; i < data.capacity()/3; i++) {
			dataIndex = i*3;
			convertedIndex = i*4;
			byte red = data.get(dataIndex+0);
			byte green = data.get(dataIndex+1);
			byte blue = data.get(dataIndex+2);
			converted.put(convertedIndex+0, red);
			converted.put(convertedIndex+1, green);
			converted.put(convertedIndex+2, blue);
			if (red == alphaRed && green == alphaGreen && blue == alphaBlue) {
				converted.put(convertedIndex+3, (byte)0);
			} else {
				converted.put(convertedIndex+3, (byte)255);
			}
		}
		converted.flip();
		return converted;
	}


But I just thought of another version... I'll post it later.
Also, this version is untested.
My github account and currently active project: https://github.com/matheus23/UniverseEngine

matheus23

If the last version did not work, try this one:

public static ByteBuffer convert(ByteBuffer data) {
		final byte alphaRed = (byte)255;
		final byte alphaGreen = (byte)255;
		final byte alphaBlue = (byte)255;
		ByteBuffer converted = BufferUtils.createByteBuffer((data.capacity()/3)*4);
		for (int i = 0; i < data.capacity(); i++) {
			byte red = data.get();
			byte green = data.get();
			byte blue = data.get();
			converted.put(red);
			converted.put(green);
			converted.put(blue);
			if (red == alphaRed && green == alphaGreen && blue == alphaBlue) {
				converted.put((byte)0);
			} else {
				converted.put((byte)255);
			}
		}
		converted.flip();
		return converted;
	}


I think its coded much better.
My github account and currently active project: https://github.com/matheus23/UniverseEngine

paul_nicholls

Nice! Thanks for the code matheus23, I will try it out a bit later on :)

Just one question though:

Since in the tutorial they use RGBA as the image decoding format and OpenGL texture format, doesn't that mean that the ByteBuffer with the image in it already has 4 bytes per pixel (RGBA), not 3 (RGB)?

Of course my assumption could be completely wrong as my code I tried before posting here just didn't work and having only RGB bytes per pixel might explain that haha

paul_nicholls

hmm...for some reason I couldn't get your code (latest) to work properly, it gave a buffer underflow error (I think..)

Anyway, I managed to do it this way (using Oxygene for Java -a Pascal derivative that compiles to Java Byte code):

method DoColorKey(aData: ByteBuffer; aR,aG,aB: Integer);
var
  i       : Integer;
  r,g,b : Byte;
begin
  i := 0;
  while i < aData.capacity do
  begin
    r := aData.get(i+0);
    g := aData.get(i+1);
    b := aData.get(i+2);
			
    if (r = Byte(aR)) and (g = Byte(aG)) and (b = Byte(aB)) then
      aData.put(i+3,Byte(0));

    inc(i,4);
  end;
end;


Thanks for the help :)

Maybe this will help someone else!!

cheers,
Paul

matheus23

Quote from: paul_nicholls on May 15, 2012, 02:36:23
hmm...for some reason I couldn't get your code (latest) to work properly, it gave a buffer underflow error (I think..)

Anyway, I managed to do it this way (using Oxygene for Java -a Pascal derivative that compiles to Java Byte code):

method DoColorKey(aData: ByteBuffer; aR,aG,aB: Integer);
var
  i       : Integer;
  r,g,b : Byte;
begin
  i := 0;
  while i < aData.capacity do
  begin
    r := aData.get(i+0);
    g := aData.get(i+1);
    b := aData.get(i+2);
			
    if (r = Byte(aR)) and (g = Byte(aG)) and (b = Byte(aB)) then
      aData.put(i+3,Byte(0));

    inc(i,4);
  end;
end;


Thanks for the help :)

Maybe this will help someone else!!

cheers,
Paul

Okey :) Glad, I gave you an idea :)
My github account and currently active project: https://github.com/matheus23/UniverseEngine