AffineTransform 截断图像 [英] AffineTransform truncates image

查看:27
本文介绍了AffineTransform 截断图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张图片,我必须将它旋转 45、90、135、180 度.我在做什么:

试试{BufferedImage src = ImageIO.read(new File("src.png"));双 ang = Math.toRadians(90);仿射变换 t = 新的仿射变换();t.setToRotation(ang, src.getWidth()/2, src.getHeight()/2);AffineTransformOp op = new AffineTransformOp(t, null);BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());op.filter(src, dst);ImageIO.write(dst, "png", new File("output.png"));} 捕捉(异常前) { ex.printStackTrace();}

问题是图像改变了它的位置并超出了目标图像的范围:

我用谷歌搜索并在这个问题中找到了解决方案:

如何解决这个问题?目标图像不应有任何额外的(对角旋转所需的除外)空白或截断区域.角度问题(0 == 180 还是顺时针)并不重要.

感谢您的帮助.

解决方案

现在它适用于一般情况.

围绕中心进行旋转,中心在目标图像中的位置与在源图像中的位置相同(正确的行为).

我已修改您的代码以转换源图像矩形,以便我们可以轻松获得新的尺寸/图像偏移量.这用于构造正确尺寸的目标 BufferedImage,并将翻译附加到您的 AffineTransform 以便图像中心位于目标图像的中心.

 BufferedImage src = ImageIO.read(new File(INPUT));int w = src.getWidth();int h = src.getHeight();仿射变换 t = 新的仿射变换();双 ang = Math.toRadians(35);t.setToRotation(ang, w/2d, h/2d);//源图像矩形点 [] 点 = {新点(0, 0),新点(w,0),新点(w,h),新点(0, h)};//转换为目标矩形t.transform(点, 0, 点, 0, 4);//获取目标矩形边界框点 m​​in = new Point(points[0]);最大点 = 新点(点 [0]);for (int i = 1, n = points.length; i < n; i ++) {点 p = 点[i];双 pX = p.getX(), pY = p.getY();//更新最小/最大 xif (pX  max.getX()) max.setLocation(pX, max.getY());//更新最小/最大 yif (pY  max.getY()) max.setLocation(max.getX(), pY);}//确定新的宽度、高度w = (int) (max.getX() - min.getX());h = (int) (max.getY() - min.getY());//确定需要的翻​​译双 tx = min.getX();双 ty = min.getY();//附加所需的翻译AffineTransform 翻译 = 新的 AffineTransform();翻译.translate(-tx, -ty);t.preConcatenate(翻译);AffineTransformOp op = new AffineTransformOp(t, null);BufferedImage dst = new BufferedImage(w, h, src.getType());op.filter(src, dst);ImageIO.write(dst,png",新文件(输出));

I have an image and I have to rotate it by 45, 90, 135, 180 degrees. What I am doing:

try {
    BufferedImage src = ImageIO.read(new File("src.png"));
    double ang = Math.toRadians(90);

    AffineTransform t = new AffineTransform();
    t.setToRotation(ang, src.getWidth() / 2, src.getHeight() / 2);

    AffineTransformOp op = new AffineTransformOp(t, null);
    BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
    op.filter(src, dst);

    ImageIO.write(dst, "png", new File("output.png"));
} catch(Exception ex) { ex.printStackTrace();
}

The problem is that image changes its position and gets out of bounds of destination image:

I've googled this and found the solution in this question: AffineTransform truncates image, what do I wrong? But I quite don't understand it and it works only for quadrants. I've tried to multiply twice width and height of destination, but it failed:

How to fix this? The destination image shouldn't have any extra (except required for diagonal rotation) whitespace or truncated area. Angle problems (0 == 180 or is it clockwise) aren't important.

Thanks for any help.

解决方案

Edit: Now it works for the general case.

The rotation is performed around the center, and the center is placed at the same position in the destination image as it was in the source image (correct behavior).

I've modified your code to transform the source image rectangle so we can easily get the new dimensions/image offset. This is used to construct a destination BufferedImage of the correct dimensions, and to append a translation to your AffineTransform so the image center is placed at the center of the destination image.

        BufferedImage src = ImageIO.read(new File(INPUT));
        int w = src.getWidth();
        int h = src.getHeight();

        AffineTransform t = new AffineTransform();
        double ang = Math.toRadians(35);
        t.setToRotation(ang, w / 2d, h / 2d);

        // source image rectangle
        Point[] points = {
            new Point(0, 0),
            new Point(w, 0),
            new Point(w, h),
            new Point(0, h)
        };

        // transform to destination rectangle
        t.transform(points, 0, points, 0, 4);

        // get destination rectangle bounding box
        Point min = new Point(points[0]);
        Point max = new Point(points[0]);
        for (int i = 1, n = points.length; i < n; i ++) {
            Point p = points[i];
            double pX = p.getX(), pY = p.getY();

            // update min/max x
            if (pX < min.getX()) min.setLocation(pX, min.getY());
            if (pX > max.getX()) max.setLocation(pX, max.getY());

            // update min/max y
            if (pY < min.getY()) min.setLocation(min.getX(), pY);
            if (pY > max.getY()) max.setLocation(max.getX(), pY);
        }

        // determine new width, height
        w = (int) (max.getX() - min.getX());
        h = (int) (max.getY() - min.getY());

        // determine required translation
        double tx = min.getX();
        double ty = min.getY();

        // append required translation
        AffineTransform translation = new AffineTransform();
        translation.translate(-tx, -ty);
        t.preConcatenate(translation);

        AffineTransformOp op = new AffineTransformOp(t, null);
        BufferedImage dst = new BufferedImage(w, h, src.getType());
        op.filter(src, dst);

        ImageIO.write(dst, "png", new File(OUTPUT));

这篇关于AffineTransform 截断图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆