Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 仿射变换中心标度坐标_Java_Math_Scale_Affinetransform - Fatal编程技术网

Java 仿射变换中心标度坐标

Java 仿射变换中心标度坐标,java,math,scale,affinetransform,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,

我有一个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),这取决于我们需要找到的缩放比例。

两点:

  • buffereImage
    的左上角从(0,0)开始,这简化了事情
  • 将操作添加到仿射变换时,它会将其放在队列的前面。(我知道实际上没有队列,请参见下文。)如果您添加翻译,然后添加比例,然后过滤数据,您的数据将看起来像是经过过滤,然后进行翻译
如果你在矩阵中思考,它会是这样的:

AffineTransform at = new AffineTransform();
您现在有一个空的身份矩阵(无操作):

[A0]=[I]

at.translate(x, y);
现在您添加了一个翻译:

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

at.scale(x, y);
然后是天平:

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

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

[新]=[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:

编辑:

  • 重读这个问题,我发现我误解了您试图做的事情:您正在绘制一个
    图形2d
    ,而不是另一个
    缓冲图像
    。很抱歉最简单的解决方案就是使用
    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]]

解决方案是使用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);
“串联”似乎将
仿射变换
分开,以免相互影响


如果您在
tr.translate

处修改数学,则可能会使缩放锚定任意。
缓冲区如何定位在坐标网格上?如果它的左上角在原点上,那么我认为应该切换两个
translate
调用以使其返回到该位置。问题是一旦缩放后,角会发生变化。您能提供一个示例吗?例如,为
缓冲区
Rect
提供一组简单的坐标(变量使用大写名称很容易混淆!),然后说明通过此转换应映射到哪个点。@andrix89是的,因此我假设您的第一次平移是要使
缓冲区
位于原点的中心,然后缩放,然后往后退。我原以为你翻译的方向不对,但我现在意识到是
图形
在移动,而不是
缓冲区
。缩放不意味着后退(第二次
平移
)应该是缩放距离吗?在任何情况下,@MvG建议的示例坐标都有助于理解您试图实现的目标。是的,但问题是它不能集中缩放,这正是我想要的,也是为什么这是一个问题的开始,否则我可以使用drawimage缩放。你的解决方案启发我找到了真正的解决方案。你知道向中心缩放和缩放后平移没有区别,对吗?这两个是等价的。从我所看到的来看,它们不是。它们自己变换坐标。我知道了,我以为它是用偏移量缩放的。