Как да обърна изображение хоризонтално с 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