I'm using LWJGL (OpenGL for Java) library for texture mapping. Here is the code to read Image from file:
BufferedImage image = ImageIO.read(new File(url));
The code for getting Data Raster (Pixels of image) as byte array:
DataBufferByte imageByteBuffer = ((DataBufferByte)image.getRaster().getDataBuffer());
byte[] bytePixels = imageByteBuffer.getData();
Now the code of creating and putting the "bytePixels" array in byte buffer:
pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();
Here for binding all of that to buffer:
id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, image.getWidth(), image.getHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixels);
The problem is, the colors of image textured aren't as the original image colors!!
Original Picture:
Textured image:
This answer to OpenGL Renders texture with different color than original image?, can't solve this issue, because GL_BGR
is not valid in lwjgl Class GL11!
The issue is that the red and blue color channel are swapped.
At OpenGL there is the possibility, to use the GL_BGR
format, which specifies a internal format where the color channels are swapped (in compare to GL_RGB
).
See OpenGL 4 Refpages - glTexImage2D
and OpenGL Renders texture with different color than original image?.
At OpenGL ES you have to manually swap the red and blue color channel, because the internal format GL_BGR
is missing.
See OpenGL ES 3.0 Refpages - glTexImage2D
and lwjgl - class GL11
.
pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();
for (int i = 0; i < pixels.length; i += 3) {
byte t = pixels[i];
pixels[i] = pixels[i+2];
pixels[i+2] = t;
}
Another possibility would be given in OpenGL ES 3.0 or by OpenGL extension EXT_texture_swizzle
:
Since OpenGL ES 3.0 you can use the texture swizzle parameters to swap the color channels. See glTexParameter
:
GL_TEXTURE_SWIZZLE_R
Sets the swizzle that will be applied to the r component of a texel before it is returned to the shader. Valid values for param are
GL_RED
,GL_GREEN
,GL_BLUE
,GL_ALPHA
,GL_ZERO
andGL_ONE
. IfGL_TEXTURE_SWIZZLE_R
isGL_RED
, the value for r will be taken from the first channel of the fetched texel. IfGL_TEXTURE_SWIZZLE_R
isGL_GREEN
, the value for r will be taken from the second channel of the fetched texel. ...
This means the color channels will be swapped when the texture is looked up, by setting the following texture parameters to the texture object:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
The relevant part in the specification can be found at OpenGL ES 3.0.5 Specification; 3.8.14 Texture State; page 162
To check if an OpenGL extension is valid, glGetString(GL_EXTENSIONS)
can be use, which returns a space-separated list of supported extensions.