【问题标题】:AffineTransform truncates imageAffineTransform 截断图像
【发布时间】:2012-05-03 07:23:09
【问题描述】:

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

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

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

我用谷歌搜索了这个并在这个问题中找到了解决方案:AffineTransform truncates image, what do I wrong? 但我完全不理解它,它只适用于象限。我尝试将目的地的宽度和高度乘以两倍,但失败了:

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

感谢您的帮助。

【问题讨论】:

  • 沿对角线 45 和 135 处的额外空间怎么样?它应该是透明的吗? 180 等于 0 吗?请编辑您的问题以包含一个 sscce 来展示您描述的问题。 FauxImage 可能是一个方便的附加词。
  • 我有一个例子和图片来说明这个问题。代码已准备好运行。

标签: java image-processing rotation image-rotation affinetransform


【解决方案1】:

编辑:现在它适用于一般情况。

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

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

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

【讨论】:

【解决方案2】:

我建议更换

AffineTransformOp op = new AffineTransformOp(t, null);

AffineTransformOp op = new AffineTransformOp(t,  AffineTransformOp.TYPE_BILINEAR);

它将大大提高输出质量。

【讨论】:

  • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。 - From Review
  • @MuhammedRefaat 这怎么不试图提供答案?这可能是完全错误的,but that doesn't mean we should abuse the review queues to delete it.
  • @Undo 我一直认为建议将作为 cmets 放置,如果每个建议都写成答案,那么这个问题实际上会有 10 个答案,但逻辑上只有 2 个,我只是想遵守社区规则。
  • @MuhammedRefaat 请阅读上面评论中的链接。社区规则是我们不会从评论中删除试图回答的内容。当然,欢迎您花费您的反对票,并在您达到 20k 时删除投票,如您所愿。只是不要使用审查来删除这些。
  • @Undo 好吧,谢谢你的建议,也许你是对的。
猜你喜欢
  • 2012-02-01
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-15
  • 1970-01-01
  • 2017-10-10
  • 1970-01-01
相关资源
最近更新 更多