How to flip BufferedImage in java
Asked Answered
S

6

13

I get RGB24 byte array and want to show it in Java.

public void getByteArray(byte byteArray[]){     
        int count1 = 0;
        byte temp1 = 0;

        for (int i = 0; i < byteArray.length; i++) {       //The order of RGB24 is red,green and blue.Change the
            //order to blue,green and red so that java can use TYPE_3BYTE_BGR to recognize it
            if (count1 == 0) {
                temp1 = byteArray[i];  
                count1++;
            } else if(count1 == 1) {
                //do nothing
                count1++;
            } else if(count1 == 2) {
                byteArray[i - 2] = byteArray[i];
                byteArray[i] = temp1;
                count1=0;
            }
        }
        image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        image.getWritableTile(0, 0).setDataElements(0, 0, width, height, byteArray);

        mainPanel.repaint();

However,the effect is not conform to my requirement and it is strange. enter image description here

How can I flip the BufferedImage to the correct direction like this? enter image description here

Sirup answered 4/5, 2014 at 15:5 Comment(6)
Do you want to rotate the image 180 degree?Piassava
It is unclear what you're asking. There are 3 answers: 1 telling you how to flip the image, one how to invert the colors, and one how to apply an AffineTransform. They're all different because the question is unclear. Please edit the question to give us more information about what you're trying to achieve.Urticaceous
Question has been modified.Actually there is no problem with color presentation and I just want the image to be what it really is.Sirup
Are you by any chance reading a BMP? :-) If so, you should just read each scanline from bottom to top, which is the correct way to read a BMP.Imputation
But how to convert the byte array of image in color space of RGB24 to BMP?Sirup
@upma If you want to swap the byte order from BGR to RGB, you can do that either while reading, or use a SampleModel with the bands inversed (BGR order). This has nothing to do with color space though. It is RGB in both cases.Imputation
R
24

There are 3 options: (EDIT ->: At least, there have been 3 options, until you edited the question <-)

  • You can flip the image vertically
  • You can rotate the image
  • You can invert the image

The difference is shown in this image:

ImageFlipTest01.png

Based on the image that you posted, I assume that you want to flip the image vertically. This can be done pixel by pixel, or (when it should be done efficiently) with an AffineTransformOp or by directly painting the image using a transformed Graphics2D.

import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ByteLookupTable;
import java.awt.image.LookupOp;
import java.awt.image.LookupTable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImageFlipTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridLayout(1, 1));

        BufferedImage image = null;
        try
        {
            image = convertToARGB(ImageIO.read(new File("lena512color.png")));
        }
        catch (IOException e1)
        {
            e1.printStackTrace();
        }

        JPanel panel = new JPanel(new GridLayout(2,2));
        panel.add(createComponent("Original", image));
        panel.add(createComponent("Flipped", createFlipped(image)));
        panel.add(createComponent("Rotated", createRotated(image)));
        panel.add(createComponent("Inverted", createInverted(image)));

        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static BufferedImage convertToARGB(BufferedImage image)
    {
        BufferedImage newImage = new BufferedImage(
            image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = newImage.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return newImage;
    }    

    private static BufferedImage createFlipped(BufferedImage image)
    {
        AffineTransform at = new AffineTransform();
        at.concatenate(AffineTransform.getScaleInstance(1, -1));
        at.concatenate(AffineTransform.getTranslateInstance(0, -image.getHeight()));
        return createTransformed(image, at);
    }

    private static BufferedImage createRotated(BufferedImage image)
    {
        AffineTransform at = AffineTransform.getRotateInstance(
            Math.PI, image.getWidth()/2, image.getHeight()/2.0);
        return createTransformed(image, at);
    }

    private static BufferedImage createTransformed(
        BufferedImage image, AffineTransform at)
    {
        BufferedImage newImage = new BufferedImage(
            image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = newImage.createGraphics();
        g.transform(at);
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return newImage;
    }

    private static BufferedImage createInverted(BufferedImage image)
    {
        if (image.getType() != BufferedImage.TYPE_INT_ARGB)
        {
            image = convertToARGB(image);
        }
        LookupTable lookup = new LookupTable(0, 4)
        {
            @Override
            public int[] lookupPixel(int[] src, int[] dest)
            {
                dest[0] = (int)(255-src[0]);
                dest[1] = (int)(255-src[1]);
                dest[2] = (int)(255-src[2]);
                return dest;
            }
        };
        LookupOp op = new LookupOp(lookup, new RenderingHints(null));
        return op.filter(image, null);
    }

    private static Component createComponent(
        String title, BufferedImage image)
    {
        JLabel label = new JLabel(new ImageIcon(image));
        JPanel panel = new JPanel(new GridLayout(1,1));
        panel.add(label);
        panel.setBorder(BorderFactory.createTitledBorder(title));
        return panel;
    }
}
Rutan answered 4/5, 2014 at 16:51 Comment(2)
Part of the intention in this (elaborate) answer was to point out the difference between flipping, rotating and inverting (before the question was clarified), and at the same time answering all three possible interpretations of the question. Now it may still serve as a snippet quarry, however.Rutan
You help me to understand my question more clearly and the flip function you provide actually worksSirup
R
5

you only have to draw the bufferedImage in negative width or negative height in drawImage method thats all

//flip horizontally
g.drawImage(bufferedImage , x,y,-width,height,null);

//flip vertically
g.drawImage(bufferedImage , x,y,width,-height,null);
Ruppert answered 1/2, 2016 at 5:10 Comment(1)
easy and works, but you have to remeber to offset the x and y respectively. so it should be something like g.drawImage(bufferedImage, x + width, y, -width, height, null); g.drawImage(bufferedImage, x, y + height, width, -height, null);Kaylor
P
3

Here is the code to flip the image at any angle

public static GraphicsConfiguration getDefaultConfiguration() {
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gd = ge.getDefaultScreenDevice();
    return gd.getDefaultConfiguration();
}

public static BufferedImage rotate(BufferedImage image, double angle) {
    int w = image.getWidth(), h = image.getHeight();
    GraphicsConfiguration gc = getDefaultConfiguration();
    BufferedImage result = gc.createCompatibleImage(w, h);
    Graphics2D g = result.createGraphics();
    g.rotate(Math.toRadians(angle), w / 2, h / 2);
    g.drawRenderedImage(image, null);
    g.dispose();
    return result;
}
Piassava answered 4/5, 2014 at 17:0 Comment(3)
This isn't the same as flipping an image. The horses will face a different direction on rotation.Haematozoon
@Haematozoon Thanks I haven't noticed this. Let me change my post.Piassava
I still like this snippet though. I'm going to bookmark it. I don't think you should remove it.Haematozoon
T
2

You could flip the image like this:

public void flip(BufferedImage image)
{
    for (int i=0;i<image.getWidth();i++)
        for (int j=0;j<image.getHeight()/2;j++)
        {
            int tmp = image.getRGB(i, j);
            image.setRGB(i, j, image.getRGB(i, image.getHeight()-j-1));
            image.setRGB(i, image.getHeight()-j-1, tmp);
        }
}
Trailer answered 4/5, 2014 at 15:14 Comment(0)
F
1

If you are using paintComponent() method of swing.

With

 graphic.drawImage(img,
                   dx1, dy1, dx2, dy2,
                   sx1, sy1, sx2, sy2,
                   null);

Just flip the sx1 with sx2

TADA! Its done.

enter image description here


                Source Image                     Destination panel

 sx1, sy1      
    +---------------+---------+        +-----------------------------+
    |               |         |        |                             |
    | region to     |         |        | dx1, dy1                    |
    |        draw   |         |        |    +----------+             |    
    |               |         |        |    |          |             |
    +---------------+         |        |    |          |             | 
    |           sx2, sy2      |        |    +----------+             |     
    |                         |        |            dx2, dy2         |
    |                         |        |                             |
    +-------------------------+        +-----------------------------+

This could be good reference for: drawImage() method

Finfoot answered 17/9, 2016 at 3:25 Comment(0)
J
0

Maybe you can use AffineTransform.

AffineTransform transform = new AffineTransform();
transform.rotate(radians, bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
Juror answered 4/5, 2014 at 15:10 Comment(2)
will this essentially be equivalent to manually rearranging pixels in the byte array or will there be some loss of data during transformation?Athalie
You provide an example of how to rotate an image but not about how to flip an image.You can refer to https://mcmap.net/q/847751/-how-to-flip-bufferedimage-in-java which I accept as the best answer.Sirup

© 2022 - 2024 — McMap. All rights reserved.