如何使用glReadPixels()和ImageIO水平翻转图像?

5
我该如何翻转屏幕截图?我在其他地方找不到解决方法。
示例代码:
/*
*@param fileLoc //Location of fileoutput destination
*@param format  //"png"
*@param WIDTH   //Display.width();
*@param HEIGHT  //Display.height();
*/
private void getScreenImage(){
             int[] pixels = new int[WIDTH * HEIGHT];
             int bindex;
             // allocate space for RBG pixels
             ByteBuffer fb = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 3);//.order(ByteOrder.nativeOrder());
             // grab a copy of the current frame contents as RGB

             glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);

             BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
             // convert RGB data in ByteBuffer to integer array
             for (int i=0; i < pixels.length; i++) {
                 bindex = i * 3;
                 pixels[i] =
                     ((fb.get(bindex) << 16))  +
                     ((fb.get(bindex+1) << 8))  +
                     ((fb.get(bindex+2) << 0));
             }
             try {
                //Create a BufferedImage with the RGB pixels then save as PNG
                 image.setRGB(0, 0, WIDTH, HEIGHT, pixels, 0 , WIDTH);

                 ImageIO.write(image, format , fileLoc);
             }
             catch (Exception e) {
                 System.out.println("ScreenShot() exception: " +e);
             }
         }

基本上这段代码可以捕获屏幕并以“png”格式存储。
但是由于glReadPixels();从左下角向右上角读取,输出的图像会水平翻转。
那么,在我使用ImageIO.write();之前,如何水平翻转图像呢?
感谢您的帮助, Rose。

在绘制到新图像时,我会使用“AffineTransform”翻转它。然后使用“ImageIO”保存新图像。 - Andrew Thompson
2个回答

8
使用AffineTransform水平翻转图像的示例。

flipping an image horizontally

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Test001 {

    public static BufferedImage getFlippedImage(BufferedImage bi) {
        BufferedImage flipped = new BufferedImage(
                bi.getWidth(),
                bi.getHeight(),
                bi.getType());
        AffineTransform tran = AffineTransform.getTranslateInstance(bi.getWidth(), 0);
        AffineTransform flip = AffineTransform.getScaleInstance(-1d, 1d);
        tran.concatenate(flip);

        Graphics2D g = flipped.createGraphics();
        g.setTransform(tran);
        g.drawImage(bi, 0, 0, null);
        g.dispose();

        return flipped;
    }

    Test001(BufferedImage bi) {
        JPanel gui = new JPanel(new GridLayout(1,2,2,2));

        gui.add(new JLabel(new ImageIcon(bi)));
        gui.add(new JLabel(new ImageIcon(getFlippedImage(bi))));

        JOptionPane.showMessageDialog(null, gui);
    }

    public static void main(String[] args) throws AWTException {
        final Robot robot = new Robot();
        Runnable r = new Runnable() {

            @Override
            public void run() {
                final BufferedImage bi = robot.createScreenCapture(
                        new Rectangle(0, 360, 200, 100));
                new Test001(bi);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

希望能看到一个使用ImageIo.write()的例子,但还是谢谢。 - Maarten
1
请查看此示例中drawImage()方法的最后一部分:http://stackoverflow.com/a/13796268/418556。 - Andrew Thompson

0
值得注意的是,按你想要的顺序直接从缓冲区中读取像素可能比反向读取并进行昂贵的转换操作更快。此外,由于您确定BufferedImage是TYPE_INT_RGB,因此可以安全地直接写入其光栅。
ByteBuffer fb = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for (int i = pixels.length - 1; i >= 0; i--) {
    int x = i % WIDTH, y = i / WIDTH * WIDTH;
    pixels[y + WIDTH - 1 - x] = (fb.get() & 0xff) << 16 | (fb.get() & 0xff) << 8 | fb.get() & 0xff;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接