如何使用JOGL保存屏幕图像

希望这是一个更好的地方来问这样的事情。 我有一个2D场景,其中一些在Swing框架中绘制的小精灵。 我需要他们被保存为一个图像。 问题是我发现每一个教程似乎已经过时了。

我发现使用glReadPixels并把结果放到一个BufferedImage应该会有所帮助,但所有这些片段看起来陈旧,API已经改变。 我正在使用目前的JOGL 2.1.5。

我有一种感觉,这应该是一个广为人知的专业用例。 任何帮助,将不胜感激!

更新:我采用了一些陈旧的片段(请不要告诉我API没有明显改变,有几十个动作和重新命名)没问题是我越来越黑屏在PNG文件。 它来自字节缓冲区读取仅零。

public static void main(String[] args) { TestPNGSaver saver = new TestPNGSaver(); saver.run(); } private void writeBufferToFile(GLAutoDrawable drawable, File outputFile) { int width = drawable.getWidth(); int height = drawable.getHeight(); ByteBuffer pixelsRGB = Buffers.newDirectByteBuffer(width * height * 3); GL2 gl = drawable.getGL().getGL2(); gl.glReadBuffer(GL.GL_BACK); gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); gl.glReadPixels(0, 0, width, height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, pixelsRGB); int[] pixels = new int[width * height]; int firstByte = width * height * 3; int sourceIndex; int targetIndex = 0; int rowBytesNumber = width * 3; for (int row = 0; row < height; row++) { firstByte -= rowBytesNumber; sourceIndex = firstByte; for (int col = 0; col < width; col++) { if (pixelsRGB.get(sourceIndex) != 0) { System.out.println(sourceIndex); } int iR = pixelsRGB.get(sourceIndex++); int iG = pixelsRGB.get(sourceIndex++); int iB = pixelsRGB.get(sourceIndex++); pixels[targetIndex++] = 0xFF000000 | ((iR & 0x000000FF) << 16) | ((iG & 0x000000FF) << 8) | (iB & 0x000000FF); } } BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); bufferedImage.setRGB(0, 0, width, height, pixels, 0, width); try { ImageIO.write(bufferedImage, "PNG", outputFile); } catch (Exception e) { e.printStackTrace(); } } @Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); gl.glClear(GL.GL_COLOR_BUFFER_BIT); gl.glBegin(GL.GL_TRIANGLES); gl.glColor3f(1, 0, 0); gl.glVertex2f(-1, -1); gl.glColor3f(0, 1, 0); gl.glVertex2f(0, 1); gl.glColor3f(0, 0, 1); gl.glVertex2f(1, -1); gl.glEnd(); } private void run() { GLProfile.initSingleton(); GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); final GLCanvas canvas = new GLCanvas(caps); canvas.addGLEventListener(this); Frame frame = new Frame(); frame.setSize(400, 400); frame.add(canvas); frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { writeBufferToFile(canvas, new File("/whatever/text.png")); System.exit(0); } }); } 

好吧,你似乎很困惑,所以这里是一些代码,我用LWJGL这是非常类似于JOGL。 可能你将不得不交换与数组的缓冲区,但代码将几乎相同。

下面是通过将屏幕数据写入BufferedImage来获取屏幕截图的方法(宽度和高度是屏幕的尺寸,缓冲区获取缓冲区中的下一个元素 – 本例中的下一个字节):

 public BufferedImage makeScreenshot() { BufferedImage screenshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = screenshot.getGraphics(); ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 3); glReadPixels(0, 0, width, height, GL_RGB, GL_BYTE, buffer); for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { // The color are the three consecutive bytes, it's like referencing // to the next consecutive array elements, so we got red, green, blue.. // red, green, blue, and so on.. graphics.setColor(new Color( buffer.get()*2, buffer.get()*2, buffer.get()*2 )); graphics.drawRect(w,height - h, 1, 1); // height - h is for flipping the image } } return screenshot; } 

在这里,如何将这些数据写入一个文件:

  try { BufferedImage screenshot = makeScreenshot(); ImageIO.write(screenshot, "png", new File("D:/screen.png")); } catch (IOException ex) { // You know ... what to do here :P } 

希望我已经帮助:)