当前位置: 首页 > 知识库问答 >
问题:

旋转时裁剪图像

常英资
2023-03-14

我正在用Java制作简单的图像编辑器。我的问题是,当我旋转被裁剪的图像时,我将尝试在图像上显示它:

轮换前http://i.imgur.com/KjtHslb.jpg

经过45度http://i.imgur.com/SKOEFP7.jpg

旋转90度后,i[dot]imgur[dot]com/4NrABIA.jpg

看起来 JPanel 将旋转图像裁剪为原始图像的大小,我不知道为什么:/所以我在寻求帮助。谢谢。

这是我的代码:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener;
import javax.swing.*;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import static java.awt.image.ImageObserver.WIDTH;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

public class OknoInterfejsu extends JFrame{

Container content;
BufferedImage image = null;
JLabel picLabel;
Image scaledImage;
private final JButton przyciski[];
private JComboBox wybor;
private String wybor_str[];
private int picHeight;
private int picWidth;
private int realHeight;
double picAspect;
private String path;


private class ObslugaPrzycisku implements ActionListener{

   private final JFrame ref_okno;

   ObslugaPrzycisku(JFrame okno){
        ref_okno = okno;
   }

   public void actionPerformed(ActionEvent e) {
        JButton bt = (JButton)e.getSource();
        if(bt==przyciski[0]){
           //-----------WCZYTAJ PRZYCISK-------------
        {
            JFileChooser fileChooser = new JFileChooser("C:\\Users\\Filip\\Pictures\\");
            FileFilter imageFilter = new FileNameExtensionFilter(
             "Image files", ImageIO.getReaderFileSuffixes());
            fileChooser.setFileFilter(imageFilter);
             if (fileChooser.showOpenDialog(null)==JFileChooser.APPROVE_OPTION)
             {
                 File plik = fileChooser.getSelectedFile();
                 path = plik.getPath();
                 System.out.print(path);
                try {
                    image = ImageIO.read(new File(path));
                } catch (IOException ex) {
                    Logger.getLogger(OknoInterfejsu.class.getName()).log(Level.SEVERE, null, ex);
                }

               picHeight = image.getHeight();
               picWidth = image.getWidth();
               picAspect = (double) picHeight / picWidth;
               //if(picAspect>1)realHeight = 400;
               //else realHeight = 800;
               realHeight = 400;
                scaledImage = image.getScaledInstance(realHeight, (int) (realHeight*picAspect),Image.SCALE_SMOOTH);

                picLabel = new JLabel(new ImageIcon(scaledImage));

                content.add(picLabel);
               content.revalidate();
               content.repaint();

             }

        } 
        }
          //--------------------------OBROT +------------  
         else if(bt==przyciski[1]){
            picLabel.setIcon(null);

            int temp1 = (int) (400*picAspect);

            picRotate(scaledImage, 400,temp1);

            picLabel = new JLabel(new ImageIcon(scaledImage));
               content.add(picLabel);
               content.revalidate();
               content.repaint();
        }   


   }
   }

    public OknoInterfejsu()
   {    
    super("Okno interfejsu");


    setSize(1000,700);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   //-------------------------------------------------------
    przyciski = new JButton[2];
    przyciski[0] = new JButton("Wczytaj Obraz");
    przyciski[0].addActionListener(new ObslugaPrzycisku(this));

    przyciski[1] = new JButton("Obrót +");
    przyciski[1].addActionListener(new ObslugaPrzycisku(this));

    JPanel panelPrzyciski   = new JPanel(new FlowLayout());
    panelPrzyciski.add(przyciski[0]);
    panelPrzyciski.add(przyciski[1]);

    //-------------------------------------------------------
    content  = getContentPane();
    content.setLayout(new BorderLayout());
    content.add(panelPrzyciski,BorderLayout.SOUTH);

    setVisible(true);
    }



     public static void main(String args[]){
     new OknoInterfejsu();
    }

    public void picRotate(Image image,int w,int h){

    BufferedImage temp=(BufferedImage)createImage(w,h);
    Graphics2D  g2d=(Graphics2D)temp.createGraphics(); 
    g2d.rotate((Math.PI/2)*22.5, w/2, h/2);

    g2d.drawImage(image,0,0,null); 
    this.scaledImage=temp; 
    g2d.dispose();  


    }
    }

共有2个答案

长孙瑞
2023-03-14

我看到您正在使用 picLabel 来存储图像并显示它:

     picRotate(scaledImage, 400,temp1);

        picLabel = new JLabel(new ImageIcon(scaledImage));
           content.add(picLabel);
           content.revalidate();
           content.repaint();

由于某种原因,标签大小是图像的高度和宽度,但标签不知道图像已旋转。解决此问题的方法可能是在将图像添加到标签之前设置标签的大小,并确保即使旋转,标签的大小也能容纳整个图像:

     picRotate(scaledImage, 400,temp1);

        picLabel = new JLabel();
           picLabel.setPreferredSize(new Dimension(800, 800));
           picLabel.add(new ImageIcon(scaledImage))
           content.add(picLabel);
           content.revalidate();
           content.repaint();

现在,首选大小的picLabel宽度和高度必须根据旋转图像所需的空间来计算。我认为一些三角函数可能对此有所帮助。我假设800x800有足够的空间来容纳图像

龙亮
2023-03-14

当您旋转图像时,它会改变大小,您需要创建一个新图像,其边界包含此新大小,例如

public Image rotateBy(Image image, double degrees) {

    // The size of the original image
    int w = source.getWidth();
    int h = source.getHeight();
    // The angel of the rotation in radians
    double rads = Math.toRadians(degrees);
    // Some nice math which demonstrates I have no idea what I'm talking about
    // Okay, this calculates the amount of space the image will need in
    // order not be clipped when it's rotated
    double sin = Math.abs(Math.sin(rads));
    double cos = Math.abs(Math.cos(rads));
    int newWidth = (int) Math.floor(w * cos + h * sin);
    int newHeight = (int) Math.floor(h * cos + w * sin);

    // A new image, into which the original can be painted
    BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = rotated.createGraphics();
    // The transformation which will be used to actually rotate the image
    // The translation, actually makes sure that the image is positioned onto
    // the viewable area of the image
    AffineTransform at = new AffineTransform();
    at.translate((newWidth - w) / 2, (newHeight - h) / 2);

    // And we rotate about the center of the image...
    int x = w / 2;
    int y = h / 2;
    at.rotate(rads, x, y);
    g2d.setTransform(at);
    // And we paint the original image onto the new image
    g2d.drawImage(image, 0, 0, null);
    g2d.dispose();

    return rotated;
}

然后你只需要调用它...

picLabel.setIcon(new ImageIcon(rotateBy(scaledImage, 22.5)));

因为< code>setIcon是一个绑定属性,所以它应该自动触发布局和绘制过程,否则,您可以简单地调用< code>revalidate和< code>repaint来手动触发它们

 类似资料:
  • 我试图在从图库中选择图像后使用intent来裁剪图像。以下是我的代码片段 在这里,我使用PICK_IMAGE_REQUEST意图句柄调用上面的代码段 由于我在裁剪后使用了相同的意图,即PICK_IMAGE_REQUEST,可能会出现什么问题

  • 问题是如何使用OpenCV旋转图像并保持原始尺寸。当前正在使用此功能: 此外,在warpAffine中使用了什么样的算法(Bicubic?)

  • 我将<code>背景 1.back_xml: 2.瓷砖.xml 现在,我将back.xml设置为< code >背景以< code>LinearLayout工作正常。 我需要有一个圆角,以及它的边框。但是我只有圆角的边框,而不是图像,我的代码中有什么问题吗? 这是我的照片:

  • 本节,我们将裁剪图像的一部分,然后把其结果绘制到画布上。 图3-2 裁剪图像 绘制步骤 按照以下步骤,裁剪图像的一部分,再把结果绘制到画布: 1. 定义画布上下文: window.onload  = function(){ var canvas  = document.getElementById("myCanvas"); var context  = canvas.getContext

  • 问题内容: 我正在尝试裁剪图像,然后将裁剪后的图像粘贴到另一个图像的中心。理想情况下,我希望裁切后的图像小于粘贴的图像,以便在粘贴的图像周围有一个边框,但我不知道这样是否可行。 这是我尝试过的方法(以及由此产生的错误消息): 我可以看到“区域”的大小已设为(0,0),但我不明白为什么。 任何对此的帮助将非常感谢 问题答案: 裁剪方法的PIL文档指出: 返回当前图像的矩形区域。该框是一个四元组,定义

  • 我有两个矩形,其中一个是另一个的剪裁。现在我想围绕剪切矩形的中心旋转较大的矩形并调整x / y值。 如何计算旋转后的新x/y值? 我只想绕着小盒子的中心旋转大盒子的x/y。因此,较大盒子的x/y点相对于较小盒子的顶部/左侧点。我有小盒子的宽度和高度,所以我可以计算大盒子相对于小盒子中心的x/y点。旋转的角度以度为单位。旋转可以是任何角度,例如10度。