首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AffineTransform截断图像,我错了什么?

AffineTransform截断图像,我错了什么?
EN

Stack Overflow用户
提问于 2012-01-03 22:21:07
回答 3查看 4.3K关注 0票数 2

这里有一个大小为2156x1728的黑白png文件,我想用AffineTransform旋转90度。结果的图像没有正确的比例。这里有一些示例代码(假设我已经成功地将png文件加载到BufferedImage中):

代码语言:javascript
复制
public BufferedImage transform(BufferedImage image){

    System.out.println("Input width: "+ image.getWidth());
    System.out.println("Input height: "+ image.getHeight());

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(1, image.getWidth() / 2, image.getHeight() / 2);

    AffineTransformOp opRotated = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
    BufferedImage transformedImage = opRotated.createCompatibleDestImage(image, image.getColorModel());
    System.out.println("Resulting width: "+ transformedImage.getWidth());
    System.out.println("Resulting height: "+ transformedImage.getHeight());

    transformedImage = opRotated.filter(image, transformedImage);
    return transformedImage;
}

因此,产出如下:

输入宽度: 2156 输入高度: 1728 结果宽度:1942年 最终高度:1942年

为什么旋转会返回如此完全不相关的维度?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-03 23:28:11

我不是这方面的专家,但为什么不直接创建一个大小正确的BufferedImage呢?还要注意,你的革命中心是不正确的。您需要在w/2、w/2或h/2,h/2的中心上旋转,这取决于您要旋转到的象限、1或3,以及图像的相对高度和宽度。例如:

代码语言:javascript
复制
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class RotateImage {
   public static final String IMAGE_PATH = "http://duke.kenai.com/"
         + "models/Duke3DprogressionSmall.jpg";

   public static void main(String[] args) {
      try {
         URL imageUrl = new URL(IMAGE_PATH);
         BufferedImage img0 = ImageIO.read(imageUrl);
         ImageIcon icon0 = new ImageIcon(img0);

         int numquadrants = 1;
         BufferedImage img1 = transform(img0, numquadrants );
         ImageIcon icon1 = new ImageIcon(img1);

         JOptionPane.showMessageDialog(null, new JLabel(icon0));
         JOptionPane.showMessageDialog(null, new JLabel(icon1));

      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   public static BufferedImage transform(BufferedImage image, int numquadrants) {
      int w0 = image.getWidth();
      int h0 = image.getHeight();
      int w1 = w0;
      int h1 = h0;

      int centerX = w0 / 2;
      int centerY = h0 / 2;

      if (numquadrants % 2 == 1) {
         w1 = h0;
         h1 = w0;
      }

      if (numquadrants % 4 == 1) {
         if (w0 > h0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         } else if (h0 > w0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         }
         // if h0 == w0, then use default
      } else if (numquadrants % 4 == 3) {
         if (w0 > h0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         } else if (h0 > w0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         }
         // if h0 == w0, then use default
      }

      AffineTransform affineTransform = new AffineTransform();
      affineTransform.setToQuadrantRotation(numquadrants, centerX, centerY);

      AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);

      BufferedImage transformedImage = new BufferedImage(w1, h1,
            image.getType());

      transformedImage = opRotated.filter(image, transformedImage);
      return transformedImage;
   }
}

编辑1

你问:

你能解释一下为什么必须是w/2,w/2或h/2,h/2吗?

要最好地解释这一点,最好是可视化并实际操作一个矩形:

剪出一张长方形的纸,放在一张纸上,这样它的左上角就在纸的左上角--这就是你在屏幕上的图像。现在检查一下你需要在哪里旋转那个矩形1或3象限,这样它的左上角就在纸的左上角上,你就会明白为什么你需要使用w/2,w/2或h/2,h/2。

票数 6
EN

Stack Overflow用户

发布于 2012-09-07 11:53:26

上面的解决方案与图像的维数和高度有关,下面的代码与w>h\x\h>w无关。

代码语言:javascript
复制
public static BufferedImage rotateImage(BufferedImage image, int quadrants) {

    int w0 = image.getWidth();
    int h0 = image.getHeight();
    int w1 = w0;
    int h1 = h0;
    int centerX = w0 / 2;
    int centerY = h0 / 2;

    if (quadrants % 2 == 1) {
        w1 = h0;
        h1 = w0;
    }

    if (quadrants % 4 == 1) {
        centerX = h0 / 2;
        centerY = h0 / 2;
    } else if (quadrants % 4 == 3) {
        centerX = w0 / 2;
        centerY = w0 / 2;
    }

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(quadrants, centerX, centerY);
    AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);
    BufferedImage transformedImage = new BufferedImage(w1, h1,
            image.getType());
    transformedImage = opRotated.filter(image, transformedImage);

    return transformedImage;

}
票数 5
EN

Stack Overflow用户

发布于 2017-06-23 13:58:06

小毛孩的答案很好,对我帮助很大。但也不是那么完美。如果图像是矩形的,则产生的旋转图像可能在一侧包含一些额外的黑色像素。

我试了一张Marty的照片,原版和结果可以在以下链接中查看:Marty Feldman轮调试验

在黑色背景上很难看到,但是在任何图像编辑软件上,都很容易看到在结果图像的右侧和底部的小黑边框。对于某些人来说,这可能不是问题,但如果对您来说,这是固定的代码(为了便于比较,我保留了原始代码作为注释):

代码语言:javascript
复制
public BufferedImage rotateImage(BufferedImage image, int quadrants) {

    int w0 = image.getWidth();
    int h0 = image.getHeight();
    /* These are not necessary anymore
    * int w1 = w0;
    * int h1 = h0;
    */
    int centerX = w0 / 2;
    int centerY = h0 / 2;

    /* This is not necessary anymore
    * if (quadrants % 2 == 1) {
    *     w1 = h0;
    *     h1 = w0;
    * }
    */

    //System.out.println("Original dimensions: "+w0+", "+h0);
    //System.out.println("Rotated dimensions: "+w1+", "+h1);

    if (quadrants % 4 == 1) {
        centerX = h0 / 2;
        centerY = h0 / 2;
    } else if (quadrants % 4 == 3) {
        centerX = w0 / 2;
        centerY = w0 / 2;
    }

    //System.out.println("CenterX: "+centerX);
    //System.out.println("CenterY: "+centerY);

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(quadrants, centerX, centerY);
    AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);

    /*Old code for comparison
    //BufferedImage transformedImage = new BufferedImage(w1, h1,image.getType());
    //transformedImage = opRotated.filter(image, transformedImage);
    */
    BufferedImage transformedImage = opRotated.filter(image, null);
    return transformedImage;

}

警告:前面的意见。我不知道为什么会发生这种情况,但我有一个猜测。如果你能解释得更好,请编辑。

我相信这个“小故障”的原因是因为奇怪的维度。例如,当计算新BufferedImage的尺寸时,当正确的值为136.5时,高度为273将生成136个centerY。这可能导致旋转发生在一个稍微偏离中心的地方。但是,通过将null发送到filter作为目标映像,“用源ColorModel创建BufferedImage”似乎效果最好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8719473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档