有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在重写的paintComponent(…)中旋转图像方法

我只是想知道如何使用JLabel component的paintComponent()方法旋转矩形图像,并正确设置其新的宽度和高度

我试着旋转(见附图),图像比例变大了,但JLabel比例保持不变,是什么使图像超出JLabel边界或其他:所以我的问题是如何以更优化的方式动态设置图像新的宽度和高度到组件

enter image description here


共 (3) 个答案

  1. # 1 楼答案

    好的,那么您希望JLabel保留其尺寸,并调整图像大小

    不管怎么说,你可能已经在使用仿射变换了,所以你可以使用一些三角学和最小/最大来找到旋转图像的AABB。适当缩放(我假设您已经在使用仿射变换来进行旋转)

    编辑:

    AABB=Axis Aligned Bounding Box,其边对应于旋转图像的最小/最大x,y坐标。只是一种更简洁的表达方式

  2. # 2 楼答案

    +1可添加评论和链接

    使用link中的方法(稍加编辑以省略GraphicsConfigurationdrawRenderImage(..)和更改的变量名):

    //https://stackoverflow.com/questions/4156518/rotate-an-image-in-java
    public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
        double sin = Math.abs(Math.sin(angle));
        double cos = Math.abs(Math.cos(angle));
        int originalWidth = image.getWidth();
        int originalHeight = image.getHeight();
        int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
        int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
        BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
        Graphics2D g2d = rotatedBI.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
        g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return rotatedBI;
    }
    

    下面是一个例子:

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class RotateImage {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new MyRotatableImage(createImage(), -45));
                    frame.pack();
                    frame.setVisible(true);
                }
            });
        }
    
        public static BufferedImage createImage() {
            BufferedImage img = new BufferedImage(100, 50, BufferedImage.TRANSLUCENT);
            Graphics2D g2d = img.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Calibri", Font.BOLD, 20));
            FontMetrics fm = g2d.getFontMetrics();
            String text = "Hello world";
            int textWidth = fm.stringWidth(text);
            g2d.drawString(text, (img.getWidth() / 2) - textWidth / 2, img.getHeight() / 2);
            g2d.dispose();
            return img;
        }
    }
    
    class MyRotatableImage extends JPanel {
    
        private BufferedImage transformedImage;
    
        public MyRotatableImage(BufferedImage img, int angle) {
            transformedImage = createTransformedImage(img, angle);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.drawImage(transformedImage, 0, 0, null);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(transformedImage.getWidth(), transformedImage.getHeight());
        }
    
        //https://stackoverflow.com/questions/4156518/rotate-an-image-in-java
        public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
            double sin = Math.abs(Math.sin(angle));
            double cos = Math.abs(Math.cos(angle));
            int originalWidth = image.getWidth();
            int originalHeight = image.getHeight();
            int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
            int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
            BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
            Graphics2D g2d = rotatedBI.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
            g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
            g2d.drawImage(image, 0, 0, null);
            g2d.dispose();
            return rotatedBI;
        }
    }
    

    参考:

  3. # 3 楼答案

    好的,我试过大卫·克鲁坎普给我看的样品。谢谢,大卫,你给我指明了正确的方向。我认为这是可以依靠的

    public static BufferedImage rotateImage(Image image, int angle)
        {
            double sin = Math.abs(Math.sin(angle));
            double cos = Math.abs(Math.cos(angle));
            int originalWidth = image.getWidth(null);
            int originalHeight = image.getHeight(null);
            int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
            int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
            BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
            Graphics2D g2d = rotatedBI.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
            g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
            g2d.drawImage(image, 0, 0, null);
            g2d.dispose();
            return rotatedBI;
        }
    

    David Kroukamp's result image preview

    我测试了代码片段,结果图像+其组件的比例都发生了动态变化。 但我得到的结果是,组件宽度总是比它的内部图像宽一点:s

    例如,这里是我的图像版本,旋转45度

    snippet based result image

    。。。正如我发现的(在蓝色背景上),它的宽度并不完全适合环绕白色图像。。。实际上,我正在寻找某种标准Java图像处理旋转解决方案,但我找不到它:(因此,我必须深入研究这个问题,至少找出如何解决“更广泛的影响”避免每次重新绘制时创建新的BuffereImage对象

    好吧,作为我研究的结果,我试着写一些我的旋转代码改编。这是:

    >;测试

    public static void rotateImage(Graphics g, Image image,int tilt,JComponent component)
        {
    
            // create the transform, note that the transformations happen
    
                      // in reversed order (so check them backwards)
                      AffineTransform at = new AffineTransform();
    
                      //5. modify component scale ...
    
                      double sin = Math.abs(Math.sin(Math.toRadians(tilt)));
                      double cos = Math.abs(Math.cos(Math.toRadians(tilt)));
    
                      int w=image.getWidth(null);
                      int h=image.getHeight(null);
                      int newW=(int) Math.floor(w * cos + h * sin);
                      int newH=(int) Math.floor(h * cos + w * sin);
    
                      component.setSize(newW, newH);
    
                      int width=component.getWidth();
                      int height=component.getHeight();
    
                      // 4. translate it to the center of the component
                      at.translate(width / 2, height / 2);
    
                      // 3. do the actual rotation
                      at.rotate(Math.toRadians(tilt));
    
                      // 2. just a scale because this image is big
        //              at.scale(1, 1);
    
    
                      // 1. translate the object so that you rotate it around the
                      //    center (easier :))
                      at.translate(-image.getWidth(null)/2, -image.getHeight(null)/2);
    
    
    
                      // draw the image
                      ((Graphics2D) g).drawImage(image, at, null);
    
    
            }
    

    。。。因此,以-30度倾斜旋转的结果图像如下所示

    enter image description here

    我衷心希望这条建议能挽救一天:)


    谢谢大家的帮助