Image to ByteBuffer

Started by technik3k, August 23, 2015, 16:30:02

Previous topic - Next topic

technik3k

I need to convert an image to a ByteBuffer for openGL.
private static final int BYTES_PER_PIXEL = 4;
	
	public static ByteBuffer convertImage(BufferedImage image)
	{      
		int[] pixels = new int[image.getWidth() * image.getHeight()];
		image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
		
		ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		
		for(int y = 0; y < image.getHeight(); y++)
		{
            for(int x = 0; x < image.getWidth(); x++)
            {
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
                buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
                buffer.put((byte) (pixel & 0xFF));               // Blue component
                buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
            }
        }

        buffer.flip();
		
		return buffer;
	}

When I do glGenTextures(textureID, convertImage(image)) then draw it onto the screen it seems to come out white. Is this a problem with the convertImage function.

abcdef

glGenTextures is only used to generate the texture buffer. glTexImage2D is what is used to define the data that the buffer points to

glGenTextures(textureID, convertImage(image))

this should actually be

glGenTextures(number of texture buffers to create, a byte buffer that will be full of these texture buffers once the method returns)

Go read up a  bit more of the opengl functions used to upload texture data to the graphics card

technik3k

Ok, I look through many tutorials I just can't find the right one for me. By the, I'm using lwjgl 3. Can some one help me. :(

abcdef

You don't need a LWJGL 3 tutorial, any tutorial on textures will explain things. Example below

https://open.gl/textures

You just need to then convert the opengl calls to from a c++ format to a java format (as the mirror 1-1).

technik3k

Yes I saw that page befor but the code from there does dosen't work and I can't figure it out. And what do you mean
Quote from: abcdef on August 24, 2015, 08:23:57
You just need to then convert the opengl calls to from a c++ format to a java format (as the mirror 1-1).

abcdef

LWJGL mirrors the function calls of the c libraries, the only difference is when you pass a reference (or arrays as they are essentially pointers) to opengl in c, you can't do this in java so the equivalent is to pass a buffer.

Here are some examples to get you going (I haven't tested this code as I am not at a PC with a dev env on so apologies if there are typo's)...

*** Generate textures ***

GLuint tex;
glGenTextures(1, &tex);


becomes (check the java doc, there are other more convenient helper methods)

ByteBuffer textureBuffer = BufferUtils.createByteBuffer((Integer.SIZE/Byte.SIZE));
GL11.glGenTextures(1,textureBuffer);


*** Bind Buffer ***

glBindTexture(GL_TEXTURE_2D, tex);


becomes

GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureBuffer.getInt());


*** load the data ***

float pixels[] = {
    0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels);


float pixels[] = {
    0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
};
FloatBuffer pixelData = BufferUtils.createFloatBuffer(12);
pixelData.put(pixels);
pixelData.flip();
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 2, 2, 0, GL11.GL_RGB, GL11.GL_FLOAT, pixelData);


This should get you going. Just read lots of tutorials and if you are having trouble post specific code you can't covert to java with the original code and your attempt.

technik3k

Ok so since my preves code was correcrt what's wrong with how tell openGL the textures and then draw.
i = ImageIO.read(new File("/home/dennis/Black Hole Breakers/Graphics/test.png"));
			glGenTextures(textureID, convertImage(i));

              glPushMatrix();
			
			glBindTexture(GL_TEXTURE_2D, textureID);
			
			glBegin(GL_QUADS);
			
			glTexCoord2f(0,0);
			glVertex2f(0,0);
			
			glTexCoord2f(1,0);
			glVertex2f(800,0);
			
			glTexCoord2f(1,1);
			glVertex2f(800,600);
			
			glTexCoord2f(0,1);
			glVertex2f(0,600);
			
			glEnd();
			
			glPopMatrix();

I do swap buffers.

abcdef

No!! Your previous code was totally incorrect for the reasons I said. You really do have no idea what you are doing.

technik3k

I'm sorry.  :'( I'm new, especially to openGL. But I've bin trying to make
float pixels[] = {
    0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
};
FloatBuffer pixelData = BufferUtils.createFloatBuffer(12);
pixelData.put(pixels);
pixelData.flip();
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 2, 2, 0, GL11.GL_RGB, GL11.GL_FLOAT, pixelData);

work. That should mke checkerboard pattern. I read throught open.gl/textures and other help too. So far I found out that I should use something like glGenTextures then glBindTexture and finaly glTexImage2D to load textures into openGL. It doesn't work. So is that not what I should use or could I be mising something. And by the way if you put
import static org.lwjgl.opengl.GL11.*;

you don't need GL11.
How I'm not terribly wrong this time.  ::)

quew8

OK, here's a quick rundown of textures in OpenGL.

glGenTexture() gives you the ID of an OpenGL texture object. The texture will be empty to start with. (which doesn't mean blank image, it means there is nothing)

glBindTexture() binds a particular OpenGL texture object to a particular target (the target is the type of the texture. GL_TEXTURE_2D is a "regular" texture). Most functions operate on the currently bound texture and when drawing, the currently bound texture will be used as a source.

glTexImage2D() fills the OpenGL texture object currently bound to the target you specify in the parameters with image data.

It's a simple setup that any OpenGL tutorial would have taught you. And a tutorial is what you need to read now. There are plenty out there.

technik3k

So about the only tutorials for openGL in java use slick2D which is not in lwjgl3 and I use lwjgl3. Instead I fallowed a c++ tutorial, but I'm have trouble puting it into java. (I also tryed to use what quew8 posted.) What would be wrong here.
              ByteBuffer BB = BufferUtils.createByteBuffer(12);

		float pixels[] = {ge(image);
		
			    0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
			    1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
			};
		FloatBuffer pixelData = BufferUtils.createFloatBuffer(12);
		pixelData.put(pixels);
		pixelData.flip();
		
		glGenTextures(ID, BB);
		
		glBindTexture(GL_TEXTURE_2D, ID);
		
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_FLOAT, pixelData);

I don't know much. ???

abcdef

I'm going to say this one more time, your glGenTextures is completely wrong!! The answers are already in this post.

technik3k

I finally got it to work!!! :o ;D Here's my code...
        private static int loadTex(String loc)
	{
		BufferedImage image = null;
		
		try
		{
			image = ImageIO.read(new File(loc));
		}
		catch(Exception a) {}
		
		ByteBuffer BB = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		
		BB = convertImage(image);
		
		int ID = glGenTextures();
		
		glBindTexture(GL_TEXTURE_2D, ID);
		
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, BB);
		
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		
		return ID;
	}


        private static final int BYTES_PER_PIXEL = 4;
	
	public static ByteBuffer convertImage(BufferedImage image)
	{      
		int[] pixels = new int[image.getWidth() * image.getHeight()];
		image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
		
		ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		
		for(int y = 0; y < image.getHeight(); y++)
		{
            for(int x = 0; x < image.getWidth(); x++)
            {
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
                buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
                buffer.put((byte) (pixel & 0xFF));               // Blue component
                buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
            }
        }

        buffer.flip();
		
		return buffer;
	}


By the way can somone tell me what
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
does?

quew8

Quote from: technik3k on August 29, 2015, 18:01:40
By the way can somone tell me what
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
does?

That tells OpenGL what to do if it is trying to draw the texture at a smaller resolution to the texture's resolution. Eg drawing one pixel for every 4 in the texture. GL_NEAREST means just use the pixel closest to the desired point. You could also have GL_LINEAR which gives you linear interpolation of all the near pixels.

Here's a tip. Whenever you don't know what a function does, check the reference pages https://www.opengl.org/sdk/docs/man2/