Search code examples
javalibgdxscreenshot

LibGDX screenshot strange behaviour


I encountered a rather strange behaviour of screenshotting my desktop application in LibGDX. I remade a small program to reproduce this "bug" which only renders a black background and a red rectangle. Those images are the results:

enter image description here enter image description here

The left one being a screenshot from window's screen clipping tool, this is what it looks like running the program. The right is from the screenshot code I posted a little further down. To clarify, I want the program's screenshot to get the left image's result, without the transparency getting all weird.

This is my render code, don't mind the coordinates. Since I can see the rectangle being rendered perfectly, it makes no sense to me for the error to be in the render method. But I'm posting it anyway.

@Override
public void render() {

    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

    shape.begin(ShapeType.Filled);
    shape.setColor(Color.BLACK);
    shape.rect(0, 0, 300, 300);

    shape.setColor(1f, 0f, 0f, 0.5f);
    shape.rect(100, 100, 100, 100);
    shape.end();

    Gdx.gl.glDisable(GL20.GL_BLEND);

}

This is the code to take a screenshot:

public static void screenshot() {

    Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    PixmapIO.writePNG(new FileHandle(Gdx.files.getLocalStoragePath() + "screenshots/test.png"), pixmap);
    pixmap.dispose();

}

private static Pixmap getScreenshot(int x, int y, int w, int h) {
    final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(x, y, w, h);

    // Flip the pixmap upside down
    ByteBuffer pixels = pixmap.getPixels();
    int numBytes = w * h * 4;
    byte[] lines = new byte[numBytes];
    int numBytesPerLine = w * 4;
    for(int i = 0; i < h; i++) {
        pixels.position((h - i - 1) * numBytesPerLine);
        pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
    }
    pixels.clear();
    pixels.put(lines);

    return pixmap;
}

I went and researched, I only found this topic, which is exactly same problem. It has slightly less information and no answer, though. I hope someone of you can answer this mystery.


Solution

  • My question was answered 23rd Feb 2017 by Tenfour04 but as he shows no interest in posting his solution as an answer, I am doing it to solve this thread. Huge thanks to him. What I did was to set every fourth element (the alpha value) in the ByteBuffer returned by getPixels() to (byte) 255 (opaque) this was my result:

    private static Pixmap getScreenshot(int x, int y, int width, int height) {
    
        final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(x, y, width, height);
    
        ByteBuffer pixels = pixmap.getPixels();
        for(int i = 4; i < pixels.limit(); i += 4) {
            pixels.put(i - 1, (byte) 255);
        }
    
        int numBytes = width * height * 4;
        byte[] lines = new byte[numBytes];
        int numBytesPerLine = width * 4;
        for(int i = 0; i < height; i++) {
            pixels.position((height - i - 1) * numBytesPerLine);
            pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
        }
        pixels.clear();
        pixels.put(lines);
        pixels.clear();
    
        return pixmap;
    }