2013-05-27 61 views
2

我有一個graphics.drawImage與我想繪製的中心縮放的緩衝區和一個帶座標和縮放比例的矩形我希望緩衝區被繪製爲。Affinetransform中心比例座標

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

+0

了'Buffer'如何定位在座標網格數學?如果它的左上角位於原點上,那麼我認爲應該切換你的兩個'translate'調用以使其回到那個位置。 – Arend

+0

這個問題一旦被縮小了角落的變化。 – adrix89

+0

你能提供一個例子嗎?即爲Buffer'和Rect'提供一組簡單的座標(使用變量的大寫名稱是令人困惑的!),然後指出哪些點應該映射到這個變換。 – MvG

回答

2

兩點:

  • 在(0,0)一BufferedImage開始的左上角,這簡化了操作。
  • 當您將操作添加到AffineTransform時,它會將其放入隊列的前面。 (我知道沒有真正的隊列,請參閱下面的內容。)如果您添加翻譯,然後添加比例,然後過濾數據,您的數據看起來好像經過了過濾,然後翻譯了

如果你想在矩陣,它應該是這樣的:

AffineTransform at = new AffineTransform(); 

你現在有一個空的單位矩陣(無操作):

[A0] = [I]

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

output.png:

output

編輯:

  • 重讀的問題,我知道我錯了什麼你試圖做:您正在繪製到Graphics2D,而不是另一個BufferedImage。抱歉。最簡單的解決方案就是使用Graphics2D.drawImage並指定目標矩形。請務必先登錄setRenderingHint
  • 只要合適的翻譯是在詞後完成的,縮放東西的原點在哪裏並不重要。如果你懷疑它們是相同的,切記AffineTransform僅有6個double值列表,並嘗試這個

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

考慮這兩個相當於功能

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]] 
+0

是的,但問題是它並沒有集中規模,這是我想要的,爲什麼這是一個問題開始,否則我可以使用drawimage規模。 – adrix89

+0

您的解決方案激發我尋找真正的解決方案。 – adrix89

+0

你意識到縮放向中心和縮放後翻譯沒有區別,對吧?這兩個是相同的。 – maybeWeCouldStealAVan

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