1. 程式人生 > >Java簡易圖片翻轉以及任意角度旋轉

Java簡易圖片翻轉以及任意角度旋轉

 最近幾天在做一個專案,因為涉及到了圖片(絕大部分都不是整圖,是把一張張的大圖切成小圖,也就是Title)的翻轉以及90°旋轉,弄得焦頭爛額。在網上搜索好幾天,發現用到的方法都是比較公式化的,對於只是在繪圖的時候需要顯示翻轉而不需要另外生成圖片的情況,這些程式碼用起來非常的麻煩。最後仔細的研究了一下JDK文件,用Graphics2D很簡單的就實現了以下功能:
1、圖片的翻轉,包括水平翻轉以及垂直翻轉
2、圖片的任意角度旋轉。因為工程需要,程式碼裡面都直接寫成了+90,根據需要,可以對這個值進行改動,以符合需求。

3、可以使用組合操作,比如水平翻轉+旋轉,或者垂直+水平+旋轉,任意。


以下是程式碼:
package Demo628;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class ImageRote
{
    public static void main(String[] args)
    {
        JFrame frame = new TransformFrame();
        frame.setVisible(true);
    }
}

class TransformFrame extends JFrame implements ActionListener
{
    //新增幾個按鈕方便操作。
    JButton rote = new JButton("旋轉") ;
    JButton flipX= new JButton("水平翻轉");
    JButton flipY= new JButton("垂直翻轉");
    JButton zoomIn = new JButton("放大") ;
    JButton zoomOut = new JButton("縮小") ;
    public TransformFrame()
    {
        setTitle("TransformTest");
        setSize(400, 400);
        addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        });
        Container contentPane = getContentPane();
        canvas = new TransPanel();
        contentPane.add(canvas, "Center");
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(rote);
        rote.addActionListener(this);
        buttonPanel.add(flipX);
        flipX.addActionListener(this);
        buttonPanel.add(flipY);
        flipY.addActionListener(this);
        
        buttonPanel.add(zoomIn) ;
        zoomIn.addActionListener(this) ;
        buttonPanel.add(zoomOut) ;
        zoomOut.addActionListener(this) ;
        contentPane.add(buttonPanel, "North");
    }

    public void actionPerformed(ActionEvent event)
    {
        Object source = event.getSource();
        //對於source == ???這種方法,在特殊的情況下出現錯誤,所以,需要酌情使用event.getSource().equals()方法來替代==
        if (source == rote)
        {
            canvas.setRotate();
        } else
        if (source == flipX)
        {
            canvas.flipX();
        } else
        if (source == flipY)
        {
            canvas.flipY();
        } else
        if (source == zoomIn)
        {
            canvas.zoomIn();
        } else
        if (source == zoomOut)
        {
            canvas.zoomOut();
        }
    }
    private TransPanel canvas;
}

class TransPanel extends JPanel
{
    //水平翻轉比例的標誌。-1表示需要進行水平翻轉
    int m_nFlipXScale = 1 ;
    //垂直翻轉比例的標誌。-1表示需要進行垂直翻轉
    int m_nFlipYScale = 1 ;
    //旋轉的角度。因為工程需要,程式碼中直接寫成了90,可以根據具體需要動態修改,以符合實際情況
    int roteAngle = 0 ;    
    //縮放比例。預設的比例0表示沒有翻轉,具體的翻轉大小通過一個方法:getZoomSize()獲取
    int zoomLevel = 0 ;
    public TransPanel()
    {
        //首先載入一張圖片。
        img = new ImageIcon("D000.GIF").getImage();
    }
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.drawImage(img,0,0,this) ;
        
        drawTransImage(g,img.getWidth(this),img.getHeight(this),zoomLevel) ;
        
    }
    
    public void drawTransImage(Graphics g,int drawx,int drawy,int zoom)
    {
        int x = 0 ;
        int y = 0 ;
        int w = img.getWidth(this) ;
        int h = img.getHeight(this) ;
        int zoomw = getZoomSize(w,zoom) ;
        int zoomh = getZoomSize(h,zoom) ;
        int xPos = 0 ;
        int yPos = 0 ;
        if (m_nFlipXScale == -1)
              xPos = -zoomw ;
        if (m_nFlipYScale == -1)
              yPos = -zoomh ;
        Graphics2D g2 = (Graphics2D)g ;
        //轉換座標原點。這步不要也成,但是將當前位置轉換為座標原點後,可以節省好多計算步驟,非常好用。
         //不過記得用完了以後,一定要把原點轉換回來,要不然其他地方就亂了
        g2.translate(drawx,drawy);
        if (roteAngle != 0)
              g2.rotate(Math.toRadians(m_nFlipXScale * m_nFlipYScale * roteAngle),zoomw >> 1,zoomh >> 1);
              //上面的m_nFlipXScale * m_nFlipYScale需要特殊說明一下:因為實際使用中,可能遇到各種組合的情況,比如
                //先flipX或者flipY以後然後再旋轉,這時候,圖片的旋轉方向就會出現錯誤,加上這段程式碼可以保證無論使用哪種組合
                //操作方式,都保證在旋轉圖片的時候是按照順時針的方向進行旋轉。
        if (m_nFlipXScale == -1)
              g2.scale(-1,1);//第一個值表示水平,-1表示等寬水平翻轉,Math.abs(m_nFlipXScale)的值越大,出來的圖片就越寬
        if (m_nFlipYScale == -1)
              g2.scale(1,-1);//第二個值表示垂直,-1表示等高垂直翻轉,Math.abs(m_nFlipYScale)的值越大,出來的圖片就越高
        //顯示圖片
        g2.drawImage(img,xPos,yPos,xPos + zoomw,yPos + zoomh,x,y,w,h,null) ;
        g2.translate(-drawx,-drawy);        
    }
    public void setRotate()
    {
        roteAngle += 90 ;
        roteAngle %= 360 ;
        repaint();
    }
    public void flipX()
    {
        m_nFlipXScale = -m_nFlipXScale ;
        repaint();
    }
    
    public void flipY()
    {
        m_nFlipYScale = -m_nFlipYScale ;
        repaint();
    }    
    
    public void zoomIn()
    {
        zoomLevel++ ;
        repaint();
    }
    
    public void zoomOut()
    {
        zoomLevel-- ;
        repaint();
    }
    
    public static final int getZoomSize(int sourceSize,int zoomLevel)
    {
        if (zoomLevel == 0)
              return sourceSize ;
        else
        if (zoomLevel < 0)
            return sourceSize / (Math.abs(zoomLevel) + 1) ;
        else
            return sourceSize * (zoomLevel + 1) ;
      }    
    private Image img;
}