我有一个带有缓冲区的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)那样取决于我们需要找到的比例。
答案 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:
修改强>
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