2

我有一个 graphics.drawImage 和一个缓冲区,我想绘制中心缩放和一个 Rectangle,其坐标和比例我希望缓冲区被绘制为。

tr2.translate(buffer.getWidth()/2, buffer.getHeight()/2);
tr2.scale((double)rect.width/buffer.getWidth(),(double) rect.height/buffer.getHeight());
tr2.translate(-buffer.getWidth()/2, -buffer.getHeight()/2);

问题是我需要做什么才能使其与矩形坐标对齐?

缓冲区坐标应映射到矩形位置。

因此,如果矩形的左上角为 (30,80),我们希望缩放后的缓冲区左上角也为 (30,80)

问题是如果在比例之前左上角是 (0,0) 现在它类似于 (-15,10) 取决于我们需要找到的比例。

4

2 回答 2

2

两点:

  • a 的左上角BufferedImage从 (0,0) 开始,这简化了事情。
  • 当您向 中添加操作时AffineTransform,它会将其放在队列的前面。(我知道实际上没有队列,见下文。)如果您添加翻译,然后添加比例,然后过滤您的数据,您的数据看起来好像是经过过滤然后翻译的。

如果你在矩阵中思考,它看起来像这样:

AffineTransform at = new AffineTransform();

您现在有一个空的单位矩阵(无操作):

[A0] = [我]

at.translate(x, y);

现在您已经添加了翻译:

[A1] = [I][tr] = [tr]

at.scale(x, y);

然后是一个规模:

[A2] = [A0][sc] = [tr][sc]

因此,当您过滤数据(点在列中)时,您会得到:

[新] = [A2][旧] = [tr][sc][旧] = [tr][scaledVersion]

这是一个例子:

static String backgroundFilename = "green.png";
static String foregroundFilename = "red.png";

public static void drawImageInRectangle(BufferedImage src, BufferedImage dst, Rectangle rect) {
    if (dst == src) {
        src = new BufferedImage(src.getColorModel(), src.copyData(null), src.getColorModel().isAlphaPremultiplied(), null);
    }
    AffineTransform at = new AffineTransform();
    // AffineTransform applies transformations in the OPPOSITE ORDER to how they were added
    at.translate(rect.x, rect.y);
    at.scale((double)rect.width/src.getWidth(), (double)rect.height/src.getHeight());
    AffineTransformOp op = new AffineTransformOp(at, new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC));
    op.filter(src, dst);
}

static Rectangle getCenterRectangle(BufferedImage image) {
    int w = image.getWidth();
    int h = image.getHeight();
    return new Rectangle(w/4, h/4, w/2, h/2);
}

public static void main(String[] args) throws Exception {
    BufferedImage background = ImageIO.read(new File(backgroundFilename));
    BufferedImage foreground = ImageIO.read(new File(foregroundFilename));
    drawImageInRectangle(foreground, background, getCenterRectangle(background));
    ImageIO.write(background, "png", new File("output.png"));
}

输出.png:

输出

编辑:

  • 重读这个问题,我发现我对你试图做的事情弄错了:你正在画一个Graphics2D,而不是另一个BufferedImage。对不起。那么最简单的解决方案就是使用Graphics2D.drawImage并指定目标矩形。一定setRenderingHint要先。
  • 缩放某物时原点在哪里并不重要,只要在之后进行适当的翻译即可。

考虑这两个等效函数:

public static AffineTransform longWay(BufferedImage buffer, Rectangle rect){
    AffineTransform tr= new AffineTransform();
    AffineTransform tr2= new AffineTransform();
    tr.translate(
            rect.x+(rect.width-buffer.getWidth())/2,
            rect.y+(rect.height-buffer.getHeight())/2); 
    tr2.translate(buffer.getWidth()/2, buffer.getHeight()/2);
    tr2.scale(
            (double)rect.width/buffer.getWidth(),
            (double)rect.height/buffer.getHeight() );
    tr2.translate(-buffer.getWidth()/2,-buffer.getHeight()/2);
    tr.concatenate(tr2);
    return tr;
}

public static AffineTransform shortWay(BufferedImage buffer, Rectangle rect){
    AffineTransform tr = new AffineTransform();
    tr.translate(rect.x, rect.y);
    tr.scale((double)rect.width/buffer.getWidth(), (double)rect.height/buffer.getHeight());
    return tr;
}

如果您怀疑它们是否相同,请记住 anAffineTransform只是 6 个double值的列表,然后试试这个:

System.out.println(longWay(buff,rect));
System.out.println(shortWay(buff,rect));

输出:

AffineTransform[[0.5, 0.0, 32.0], [0.0, 0.5, 24.0]]
AffineTransform[[0.5, 0.0, 32.0], [0.0, 0.5, 24.0]]
于 2013-05-28T18:27:20.467 回答
0

解决方案是使用 2 个转换。

AffineTransform tr= new AffineTransform();
AffineTransform tr2= new AffineTransform();

一个处理翻译和对齐。

tr.translate(rect.x+(rect.width-buffer.getWidth())/2,
rect.y+(rect.height-buffer.getHeight())/2); 

另一个处理中心缩放。

tr2.translate(buffer.getWidth()/2, buffer.getHeight()/2);
tr2.scale((double)rect.width/buffer.getWidth(),
(double)rect.height/buffer.getHeight() );
tr2.translate(-buffer.getWidth()/2,-buffer.getHeight()/2);

然后我们像这样连接它。

tr.concatenate(tr2);

并使用 tr 进行绘图。

gfx.drawImage(buffer, tr, null);

连接似乎保持AffineTransform分开,以免相互影响。

如果您修改数学,您可能可以使缩放锚点任意tr.translate

于 2013-05-31T07:19:45.930 回答