Java 仿射变换中心标度坐标
我有一个graphics.drawImage,其中有一个缓冲区,我想画一个中心缩放的矩形,还有一个坐标和缩放的矩形,我想画一个缓冲区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,
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),这取决于我们需要找到的缩放比例。两点:
的左上角从(0,0)开始,这简化了事情buffereImage
- 将操作添加到仿射变换时,它会将其放在队列的前面。(我知道实际上没有队列,请参见下文。)如果您添加翻译,然后添加比例,然后过滤数据,您的数据将看起来像是经过过滤,然后进行翻译
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缩放。你的解决方案启发我找到了真正的解决方案。你知道向中心缩放和缩放后平移没有区别,对吗?这两个是等价的。从我所看到的来看,它们不是。它们自己变换坐标。我知道了,我以为它是用偏移量缩放的。