把Swing的Icon轉換到SWT的Image

環境:Windows七、Eclipse 3.五、JRE1.6
最近在研究SWT的TreeView控件,想要寫一個相似於Windows資源管理器的目錄樹,弄了半天,目錄樹是出來了,可是圖標搞不出來,何解?FileSystemView.getFileSystemView().getSystemIcon(File f)這個函數返回的是個Icon對象,是用在Swing上的,而個人目錄樹採用的是SWT/JFace TreeViewer控件,其ILabelProvider的getImage()接口返回的是SWT的Image對象。這兩個玩意兒得轉換一下才能使用。
在網上找了半天的資料,發現沒有現成的API能夠一句話就完成轉換,都是須要寫一段代碼來完成。有幾個方案,基本思路都是將Icon對象內所包含的Icon數據轉換成數據流,而後根據這個數據流從新生成Image,其代碼以下:
@Override
public Image getImage(Object element)
{
    // 獲得文件圖標
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.getHeight( null );
    // 建立用於繪製 Icon 的緩衝區
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
    // 繪製 Icon 到緩衝區
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(p_w_picpath, 0, 0, null );
    g2d.dispose();
    // 讀取緩衝區圖片數據到一個數組
    int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
    // 根據數組數據生成 ImageData 對象
    ImageData p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 對象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    return swtImage;
}
Icon的確是轉換到Image了,看下面的效果圖:
001
雖然Icon轉換到了Image,但是圖片周圍全都是黑色,這是由於Icon在轉換的時候,原來的圖片裏面是透明色的像素點,轉換過來系統自動變成了黑色,所以代碼還須要額外的處理一下,修改後的代碼以下:
@Override
public Image getImage(Object element)
{
    // 獲得文件圖標
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.getHeight( null );
    // 建立用於繪製 Icon 的緩衝區
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
    // 繪製 Icon 到緩衝區
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(p_w_picpath, 0, 0, null );
    g2d.dispose();
    // 讀取緩衝區圖片數據到一個數組
    int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
    // 將沒有顏色的點設置爲白色
    for ( int i = 0; i < data. length ; i++)
    {
    if (data[i] == 0)
        data[i] = 0xFFFFFF;
    }
    // 根據數組數據生成 ImageData 對象
    ImageData p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 對象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    return swtImage;
}
和上面的代碼相比,新增長了一個循環,將緩衝區內爲0的數據修改成0xFFFFFF,也就是將相應的像素設置爲白色,效果圖以下:
002
看起來效果好多了,但是若是目光敏銳一點的話,仍是可以看出破綻來,截取一個圖標,放大後仔細看一看:
2
和正常的圖標對比一下,能夠發現邊邊角角的顏色都不對,廣泛偏深,但是網上找到的資料到這裏就爲止了,沒有人提出來如何解決這個問題,固然,這也可能跟個人系統有關係。通過跟蹤和調試,發現其實調用 systemIcon.getImage() 獲得的對象就已是一個BufferedImage對象了,沒有必要再去從新new一個,而事實證實,就是這個new操做,致使轉換後的圖片出現上述問題。
根據 systemIcon.getImage()獲得BufferedImage對象後,由於該對象內部數據實際上就已是文件圖標數據了,因此調用 Graphics2D繪製Icon的操做也不必了,最後修改後的代碼以下:
@Override
public Image getImage(Object element)
{
    // 獲得文件圖標
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.getHeight( null );
    // 獲得 Icon 的數據緩衝區
    BufferedImage bufferedImage = (BufferedImage) systemIcon.getImage();
    // 讀取緩衝區圖片數據到一個數組
    int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
    // 將沒有顏色的點設置爲白色
    for ( int i = 0; i < data. length ; i++)
    {
    if (data[i] == 0)
        data[i] = 0xFFFFFF;
    }
    // 根據數組數據生成 ImageData 對象
    ImageData p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 對象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    return swtImage;
}
這回效果圖以下:
003
看起來好看多了,基本上跟Windows資源管理器的效果差很少了。不過若是目光依舊敏銳的話,再繼續打開某一驅動器,看文件夾圖標,仍是有一點小小的瑕疵,有些Icon在轉換過來的時候,會莫名其妙的在原來沒有顏色的像素點上增長一點淡淡的顏色,不過影響已經不大了,就姑且這樣吧。期待有高手可以進一步將其搞定。
好消息,這個問題我本身搞定了,參見《把Swing的Icon轉換到SWT的Image(續)》這篇文檔。
相關文章
相關標籤/搜索