user2190492
user2190492

Reputation: 1202

Java: dynamically create a png image from BufferedImage

I want to dynamically create an image, and the created image must meet some requirements. The created image should be a png, and it must have the same behavior as if it's a loaded png from a file. It's for creating a texture to use in LWJGL. When I load a png image as a file and have a BufferedImage, I can use the following code for my texture: (The Texture constructor is designed for using with loaded images)

public class Texture {

    public Texture(BufferedImage bi) {

        width = bi.getWidth();
        height = bi.getHeight();

        System.out.println(bi.toString());

        int[] pixels_raw = new int[width * height];
        pixels_raw = bi.getRGB(0, 0, width, height, null, 0, width); 

        ByteBuffer pixels = BufferUtils.createByteBuffer(width * height * 4);

        for(int i = 0; i < width; i++) {
            for(int j = 0; j < height; j++) {

                int pixel = pixels_raw[i * width + j]; // This is the error line.
                pixels.put((byte)((pixel >> 16) & 0xFF));   // red
                pixels.put((byte)((pixel >> 8) & 0xFF));    // green
                pixels.put((byte)(pixel & 0xFF));           // blue
                pixels.put((byte)((pixel >> 24) & 0xFF));   // alpha
            }
        }

        pixels.flip();

        id = glGenTextures();

        glBindTexture(GL_TEXTURE_2D, id);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    }
}

But when I try to create an image dynamically, without loading anything from a file, then I get an ArrayIndexOutOfBoundsException on line 18 of the above code (see comment in code). Of course it has something to do with the bits per pixel of the created BufferedImage. I tried changing the image type for my BufferedImage, and changing the array size when initializing the pixels_raw array. But I still get array exceptions. So, the above constructor method does only works when I pass a BufferedImage instance which comes from a loaded png. When I pass in a BurfferedImage I created dynamically with the code below, it gives me the exceptions I mentioned before.

public class TextDrawer {

    public BufferedImage drawText(String text, Font font, Color color) {

        BufferedImage graphicsGetterBi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics g = graphicsGetterBi.getGraphics();
        Graphics2D g2 = (Graphics2D) g;

        Rectangle2D bounds = font.getStringBounds(text, 0, text.length(), g2.getFontRenderContext());

        BufferedImage bi = new BufferedImage((int) bounds.getWidth(), (int) bounds.getHeight(), BufferedImage.TYPE_INT_ARGB);

        System.out.println("Created the image. \n");
        g2.setColor(color);
        g2.setFont(font);
        g2.drawString(text, 0, 0);

        return bi;
    }
}

Upvotes: 1

Views: 1242

Answers (1)

Coderino Javarino
Coderino Javarino

Reputation: 2896

instead of int pixel = pixels_raw[i * width + j]; it should be int pixel = pixels_raw[i * height + j]; or int pixel = pixels_raw[j * width + i];. Consider you have image of width = 2x and height = x. Then the array size is 2x^2, while the maximum index you request for is (2x - 1) * 2x + x - 1 = 4x^2 - x - 1, which is more than 2x^2 for x > 2

Upvotes: 1

Related Questions