2014-05-15 52 views
0

我需要打開/關閉圖像的RGB通道,但是我卡住了,我的代碼有問題。在RGB通道之間切換

你能幫我弄清楚如何以正確的方式做到這一點嗎?這是我的代碼:

功能頻道時1 3的複選框已更改其狀態被調用,並提供它們true == selected

public void channels(boolean red, boolean green, boolean blue) { 
    if (this.img != null) {// checks if the image is set 
     char r = 0xFF, g = 0xFF, b = 0xFF; 
     if (red == false) { 
      r = 0x00; 
     } 
     if (green == false) { 
      g = 0x00; 
     } 
     if (blue == false) { 
      b = 0x00; 
     } 
     BufferedImage tmp = new BufferedImage(
       img.getWidth(), 
       img.getHeight(), 
       BufferedImage.TYPE_INT_RGB); 
     for (int i = 0; i < img.getWidth(); i++) { 
      for (int j = 0; j < img.getHeight(); j++) { 
       int rgb = img.getRGB(i, j); 
       int red = (rgb >> 16) & r; 
       int green = (rgb >> 8) & g; 
       int blue = (rgb >> 0) & b; 
       int gbr = (red << 16) | (green << 8) | blue;// EDITED 
       tmp.setRGB(i, j, gbr); 
      } 
     } 
     img = tmp; 
     repaint(); 
    } else { 
     //show error 
    } 
} 

謝謝你的幫助的參數!

+0

第一眼看起來不錯,現在當您關閉一個頻道時會發生什麼? – Octopus

+2

看起來你正在錯位。不應該是:'int gbr =(red << 16)| (綠色「8」)藍色;'?你基本上想要按照與你前進的方式相同的順序轉回來......對吧?讓我知道這個是否奏效。如果是這樣,我會把它變成一個答案,所以你可以接受! :) – rayryeng

+0

當我關閉一個頻道是好的,但是當我嘗試打開/關閉其他頻道時,它變得非常混亂。例如,我不能關閉,然後在一個頻道上,並獲得相同的圖像 – Mark

回答

1

看起來你正在錯位。它不應該是:int gbr = (red << 16) | (green << 8) | blue;?你基本上想要按照和你前進的方式相同的順序轉回去。

此外,一旦你清除了相應的顏色,你就沒有辦法讓它恢復原狀。您需要在某處存儲原始圖像的副本。當需要重新打開頻道時,只需將原始圖像中的原始像素複製回來即可。

假設你有地方存儲爲origImg原始圖像,我會修改你的for循環,這樣,如果該通道處於啓用狀態,從原始圖像複製。

for (int i = 0; i < img.getWidth(); i++) { 
    for (int j = 0; j < img.getHeight(); j++) { 
     int rgb = img.getRGB(i, j); 
     int origRGB = origImg.getRGB(i, j);    
     int redPixel = red ? (origRGB >> 16) & r : (rgb >> 16) & r; 
     int greenPixel = green ? (origRGB >> 8) & g : (rgb >> 8) & g; 
     int bluePixel = blue ? origRGB & b : rgb & b; 
     int gbr = (redPixel << 16) | (greenPixel << 8) | bluePixel; 
     tmp.setRGB(i, j, gbr); 
    } 
} 
2

這個優化版本怎麼樣,移位少得多?

public void channels(boolean showRed, boolean showGreen, boolean showBlue) { 
    if (this.origImg!= null) {// checks if the image is set 
     int channelMask = 0xff << 24 | (showRed ? 0xff : 0) << 16 | (showGreen ? 0xff : 0) << 8 | (showBlue ? 0xff : 0); 

     BufferedImage tmp = new BufferedImage(origImg.getWidth(), origImg.getHeight(), BufferedImage.TYPE_INT_RGB); 

     for (int i = 0; i < origImg.getWidth(); i++) { 
      for (int j = 0; j < origImg.getHeight(); j++) { 
       int rgb = origImg.getRGB(i, j); 
       tmp.setRGB(i, j, rgb & channelMask); 
      } 
     } 

     img = tmp; 
     repaint(); 
    } else { 
     //show error 
    } 
} 

更快的方法還,很可能是使用一個引導Raster,或至少一個Raster配置,允許帶子採樣(見Raster.createChild(...)方法,尤其是最後的參數)。

LookupOp,正如@trashgod提到的也是一個好主意,並且可能比getRGB()/setRGB()方法更快。

+0

+1比我建議的要好。去看看我有多少Java經驗:) – rayryeng