【问题标题】:How to flip BufferedImage in java如何在java中翻转BufferedImage
【发布时间】:2014-05-04 15:05:31
【问题描述】:

我得到 RGB24 字节数组并想用 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();

但是,效果不符合我的要求,很奇怪。

我怎样才能像这样将 BufferedImage 翻转到正确的方向?

【问题讨论】:

  • 要将图像旋转 180 度吗?
  • 不清楚你在问什么。有 3 个答案:1 个告诉您如何翻转图像,一个告诉您如何反转颜色,一个告诉您如何应用 AffineTransform。它们都是不同的,因为问题不清楚。请编辑问题,向我们提供有关您想要实现的目标的更多信息。
  • 问题已修改。其实颜色呈现没有问题,我只是希望图像是真实的。
  • 您是否有机会阅读 BMP? :-) 如果是这样,您应该从从下到上读取每条扫描线,这是读取 BMP 的正确方法。
  • 但是如何将RGB24色彩空间中图像的字节数组转换为BMP呢?

标签: java swing awt rgb bufferedimage


【解决方案1】:

有 3 个选项:(编辑 ->:至少, 有 3 个选项,直到您编辑问题

  • 您可以垂直翻转图像
  • 可以旋转图片
  • 您可以反转图像

区别如下图所示:

根据您发布的图片,我假设您想要垂直翻转该图片。这可以逐个像素地完成,或者(当它应该有效地完成时)使用AffineTransformOp 或通过使用转换后的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;
    }
}

【讨论】:

  • 这个(详尽的)答案的部分意图是指出翻转、旋转和反转之间的区别(在澄清问题之前),同时回答所有三种可能的解释问题。不过,现在它仍可用作 sn-p 采石场。
  • 您帮助我更清楚地理解我的问题,并且您提供的翻转功能确实有效
【解决方案2】:

这是任意角度翻转图像的代码

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;
}

【讨论】:

  • 这与翻转图像不同。马匹在旋转时将面对不同的方向。
  • @Brandon 谢谢我没有注意到这一点。让我换个帖子吧。
  • 我还是喜欢这个 sn-p。我要给它加书签。我认为你不应该删除它。
【解决方案3】:

你可以像这样翻转图像:

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);
        }
}

【讨论】:

    【解决方案4】:

    您只需要在drawImage方法中以负宽度或负高度绘制bufferedImage即可

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

    【讨论】:

    • 简单且有效,但您必须记住分别偏移 x 和 y。所以它应该类似于g.drawImage(bufferedImage, x + width, y, -width, height, null);g.drawImage(bufferedImage, x, y + height, width, -height, null);
    【解决方案5】:

    也许你可以使用 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);
    

    【讨论】:

    • 这本质上是否等同于手动重新排列字节数组中的像素,还是在转换过程中会丢失一些数据?
    • 您提供了如何旋转图像的示例,但没有说明如何翻转图像。您可以参考stackoverflow.com/a/23458883/3378204,我认为这是最佳答案。
    【解决方案6】:

    如果你使用的是swing的paintComponent()方法。

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

    只需用 sx2

    翻转 sx1

    多田!完成了。


                    Source Image                     Destination panel
    
     sx1, sy1      
        +---------------+---------+        +-----------------------------+
        |               |         |        |                             |
        | region to     |         |        | dx1, dy1                    |
        |        draw   |         |        |    +----------+             |    
        |               |         |        |    |          |             |
        +---------------+         |        |    |          |             | 
        |           sx2, sy2      |        |    +----------+             |     
        |                         |        |            dx2, dy2         |
        |                         |        |                             |
        +-------------------------+        +-----------------------------+
    

    这可能是一个很好的参考: drawImage() method

    【讨论】:

      猜你喜欢
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 2015-12-19
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      相关资源
      最近更新 更多