2010-02-13 25 views
10

我在使用AffineTransform類的Java中旋轉圖像時遇到了一些問題。旋轉BufferedImage的問題

我有用於創建圖像的旋轉(90度)複製下面的方法:

private BufferedImage createRotatedCopy(BufferedImage img, Rotation rotation) { 
    int w = img.getWidth(); 
    int h = img.getHeight(); 

    BufferedImage rot = new BufferedImage(h, w, BufferedImage.TYPE_INT_RGB); 

    double theta; 
    switch (rotation) { 
     case CLOCKWISE: 
      theta = Math.PI/2; 
      break; 
     case COUNTERCLOCKWISE: 
      theta = -Math.PI/2; 
      break; 
     default: 
      throw new AssertionError(); 
    } 

    AffineTransform xform = AffineTransform.getRotateInstance(theta, w/2, h/2); 
    Graphics2D g = (Graphics2D) rot.createGraphics(); 
    g.drawImage(img, xform, null); 
    g.dispose(); 

    return rot; 
} 

旋轉是一個簡單枚舉與該值NONE,順時針方向和逆時針方向。

我的問題的症狀是在這裏顯示:

http://perp.se/so/rotate_problems.html

所以,旋轉工程確定,但由此產生的圖像不固定在正確的座標(或如何應該把它)。因爲我並不真正知道自己在做什麼(我的線性代數很弱),所以我不知道如何自己解決這個問題。

我試過一些隨機擺弄AffineTransform實例,但它並沒有幫助我(當然)。我嘗試過使用Google搜索(並搜索),但我所見過的所有示例基本上都使用與我一樣的方法...這對我不起作用。

感謝您的建議。

+1

等效問題:http://stackoverflow.com/questions/2225363/c-rotate-bitmap-90-degrees – finnw 2010-02-13 10:46:30

回答

16

如果你要表達的轉化爲一個單一的旋轉,定位點取決於旋轉方向:要麼(w/2, w/2)(h/2, h/2)

但它可能更簡單地表示爲translate; rotate; translate,例如,

AffineTransform xform = new AffineTransform(); 
xform.translate(0.5*h, 0.5*w); 
xform.rotate(theta); 
xform.translate(-0.5*w, -0.5*h); 

還要考慮使用的getQuadrantRotateInstance代替getRotateInstance

+0

我明白你的意思了,我也試過了。但問題依然存在。它們仍然被拉到目標區域的「外面」,儘管在水平方向上是「另一邊」,可以這麼說。我可以提供更多的截圖,如果它不清楚我在做什麼。 – perp 2010-02-13 12:35:36

+0

@perp,你是對的,修好了。我已經測試了新版本,它的工作原理。 – finnw 2010-02-13 16:19:20

+0

工程就像一個魅力!我想我現在也對現在的情況有了更好的瞭解。謝謝! – perp 2010-02-13 16:43:10

0

我不知道這可能是你的問題。

AffineTransform xform = AffineTransform.getRotateInstance(theta, w/2, h/2); 

爲什麼不試試?

AffineTransform xform = AffineTransform.getRotateInstance(theta); 

OR

g.transform(AffineTransform.getRotateInstance(theta)); 
g.drawImage(img, 0, 0, w/2, h/2, null, null); 
+0

我已經嘗試過了。 :-) – perp 2010-02-13 12:31:28

1

你可以嘗試一個替代的應用程序,並從圖像創建一個圖標,然後使用Rotated Icon

或者你可以嘗試這個舊的代碼我在陽光論壇上發現:

import java.awt.*; 
import java.awt.geom.*; 
import java.awt.image.*; 
import java.io.*; 
import java.net.*; 
import javax.imageio.*; 
import javax.swing.*; 

public class RotateImage { 
    public static void main(String[] args) throws IOException { 
     URL url = new URL("https://blogs.oracle.com/jag/resource/JagHeadshot-small.jpg"); 
     BufferedImage original = ImageIO.read(url); 
     GraphicsConfiguration gc = getDefaultConfiguration(); 
     BufferedImage rotated1 = tilt(original, -Math.PI/2, gc); 
     BufferedImage rotated2 = tilt(original, +Math.PI/4, gc); 
     BufferedImage rotated3 = tilt(original, Math.PI, gc); 
     display(original, rotated1, rotated2, rotated3); 
    } 

    public static BufferedImage tilt(BufferedImage image, double angle, GraphicsConfiguration gc) { 
     double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle)); 
     int w = image.getWidth(), h = image.getHeight(); 
     int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin); 
     int transparency = image.getColorModel().getTransparency(); 
     BufferedImage result = gc.createCompatibleImage(neww, newh, transparency); 
     Graphics2D g = result.createGraphics(); 
     g.translate((neww-w)/2, (newh-h)/2); 
     g.rotate(angle, w/2, h/2); 
     g.drawRenderedImage(image, null); 
     return result; 
    } 

    public static GraphicsConfiguration getDefaultConfiguration() { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice gd = ge.getDefaultScreenDevice(); 
     return gd.getDefaultConfiguration(); 
    } 

    public static void display(BufferedImage im1, BufferedImage im2, BufferedImage im3, BufferedImage im4) { 
     JPanel cp = new JPanel(new GridLayout(2,2)); 
     addImage(cp, im1, "original"); 
     addImage(cp, im2, "rotate -PI/2"); 
     addImage(cp, im3, "rotate +PI/4"); 
     addImage(cp, im4, "rotate PI"); 

     JFrame f = new JFrame("RotateImage"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setContentPane(cp); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    static void addImage(Container cp, BufferedImage im, String title) { 
     JLabel lbl = new JLabel(new ImageIcon(im)); 
     lbl.setBorder(BorderFactory.createTitledBorder(title)); 
     cp.add(lbl); 
    } 
} 
3

既然你只需要90度旋轉,你可以儘量避免使用的AffineTransform東西:

public BufferedImage rotate90DX(BufferedImage bi) { 
    int width = bi.getWidth(); 
    int height = bi.getHeight(); 
    BufferedImage biFlip = new BufferedImage(height, width, bi.getType()); 
    for(int i=0; i<width; i++) 
     for(int j=0; j<height; j++) 
      biFlip.setRGB(height-1-j, width-1-i, bi.getRGB(i, j)); 
    return biFlip; 
} 

這也避免了切斷矩形圖像的邊緣。

來源:爲.NET http://snippets.dzone.com/posts/show/2936

+3

只是一個人頭,強迫直接訪問RGB像素值將圖像從Java2D中的加速管道中取出。這種方法可能會給你想要的結果,但速度要慢得多。 – 2011-08-03 01:46:30

+0

啊哈。不知道。謝謝 – 2011-08-03 08:08:57

+0

我測試了這段代碼,它不是簡單地旋轉圖像,它也左右變化(就像在鏡子中一樣) – Radon8472 2015-08-11 15:56:57