Affinetransform中心比例坐标

时间:2013-05-27 16:13:26

标签: java math scale affinetransform

我有一个带有缓冲区的graphics.drawImage,我想绘制中心缩放,一个带坐标和缩放的矩形,我希望将缓冲区绘制为。

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

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

缓冲区坐标应映射到rect loaction。

因此,如果rect的左上角是(30,80),我们想要缩放后左上角的缓冲区(30,80)

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

2 个答案:

答案 0 :(得分:2)

两点:

  • BufferedImage的左上角从(0,0)开始,这简化了事情。
  • AffineTransform添加操作时,会将其置于队列的中。 (我知道没有真正的队列,请参阅下文。)如果您添加翻译,然后添加比例,然后过滤数据,您的数据看起来就像过滤了然后翻译

如果您在矩阵中思考,它将如下所示:

AffineTransform at = new AffineTransform();

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

[A0] = [I]

at.translate(x, y);

现在你添加了一个翻译:

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

at.scale(x, y);

然后是一个比例:

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

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

[new] = [A2] [old] = [tr] [sc] [old] = [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"));
}

output.png:

output

修改

  • 重读这个问题,我发现我误解了你要做的事情:你正在吸引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;
}

如果您怀疑它们是相同的,请记住AffineTransform只是一个包含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]]

答案 1 :(得分: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);

Concatenate似乎将AffineTransform分开,以免互相影响。

如果您在tr.translate

修改数学,则可以使缩放锚任意