Как перевернуть изображение по горизонтали с помощью glReadPixels() Bufferedimage и вывести с помощью ImageIO?

Как перевернуть снимок экрана? Я больше нигде не могу найти свою проблему.
Пример кода:

/*
*@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();?

Заранее спасибо, Роуз.


person Maarten    schedule 06.12.2012    source источник
comment
Я бы перевернул его с помощью AffineTransform при рисовании на новом изображении. Затем сохраните новое изображение с помощью ImageIO.   -  person Andrew Thompson    schedule 07.12.2012


Ответы (2)


НАПРИМЕР. переворачивания изображения по горизонтали с помощью AffineTransform.

переворот изображения по горизонтали

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);
    }
}
person Andrew Thompson    schedule 07.12.2012
comment
Хотелось бы увидеть один с использованием ImageIo.write() Но спасибо - person Maarten; 10.12.2012
comment
См. последнюю часть метода drawImage() в этом примере. - person Andrew Thompson; 10.12.2012

Стоит отметить, что может быть быстрее просто прочитать пиксели из буфера в нужном вам порядке, чем читать их в обратном порядке и выполнять дорогостоящую операцию преобразования. Кроме того, поскольку вы точно знаете, что 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;
}
person krispy    schedule 02.04.2014