2010-10-13 114 views
4

我想用java.awt.image.BufferedImage做一個簡單的灰度轉換顏色。我是圖像處理領域的初學者,所以請原諒,如果我困惑的東西。我想在輸出上獲得一個8位灰度BufferedImage,這意味着我有一個這樣的類(爲了清楚起見,細節被省略):我的輸入圖像是RGB 24位圖像(無alpha),我想在輸出上獲得8位灰度BufferedImagejava.awt.image.BufferedImage使用自定義ColorSpace的24位RGB到8位灰度轉換

public class GrayscaleFilter { 
    private BufferedImage colorFrame; 
    private BufferedImage grayFrame = 
     new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); 

我已經成功地嘗試了2種轉換的方法到現在爲止,第一個是:

private BufferedImageOp grayscaleConv = 
     new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null); 

    protected void filter() { 
     grayscaleConv.filter(colorFrame, grayFrame); 
    } 

,第二個是:

protected void filter() {  
     WritableRaster raster = grayFrame.getRaster(); 

     for(int x = 0; x < raster.getWidth(); x++) { 
      for(int y = 0; y < raster.getHeight(); y++){ 
       int argb = colorFrame.getRGB(x,y); 
       int r = (argb >> 16) & 0xff; 
       int g = (argb >> 8) & 0xff; 
       int b = (argb  ) & 0xff; 

       int l = (int) (.299 * r + .587 * g + .114 * b); 
       raster.setSample(x, y, 0, l); 
      } 
     } 
    } 

第一種方法運行速度快得多,但生成的圖像非常暗,這意味着我失去了不可接受的帶寬(灰度和sRGB ColorModel之間使用了一些顏色轉換映射,名爲tosRGB8LUT,這對我來說效果不佳,據我所知,但我不確定,我只是假設使用這些值)。第二種方法工作較慢,但效果非常好。

有沒有一種方法來結合這兩個,例如。使用自定義索引ColorSpaceColorConvertOp?如果是,請給我舉個例子嗎?

在此先感謝。

回答

2

嘗試修改你的第二種方法。而不是在一個像素上工作,檢索一個argb int值的數組,將其轉換並設置回來。

5

有一個示例here,它與第一個示例在一個小方面不同,參數爲ColorConvertOp。嘗試:

protected void filter() { 
    BufferedImageOp grayscaleConv = 
     new ColorConvertOp(colorFrame.getColorModel().getColorSpace(), 
         grayFrame.getColorModel().getColorSpace(), null); 
    grayscaleConv.filter(colorFrame, grayFrame); 
} 
+2

該建議的方法也產生較暗的圖像。我想知道是否有人解決了這個問題。 – ecem 2013-06-06 23:13:03

+0

@ecem也許是同樣的原因在這個問題:http://stackoverflow.com/questions/15399653/image-conversion-to-grayscale-using-imagemagick-is-very-dark – 2014-02-05 04:24:45

5
public BufferedImage getGrayScale(BufferedImage inputImage){ 
    BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY); 
    Graphics g = img.getGraphics(); 
    g.drawImage(inputImage, 0, 0, null); 
    g.dispose(); 
    return img; 
} 
0

第二種方法是基於像素的亮度,因此其獲得更有利的視覺效果。當使用查找數組或哈希表計算l時,可以通過優化昂貴的浮點算術運算來加快速度。

0

這是一種在某些情況下適用於我的解決方案。

獲取圖像高度y,圖像寬度x,圖像顏色深度m和整數位大小n。僅在(2^m)/(x * y * 2^n)> = 1時起作用。 在處理初始灰度值時,爲每個顏色通道保留一個n位整數。將每個通道的平均值avr [通道]的總和除以(x * y)。將每個通道的每個像素添加(192-avr [通道])。

請記住,這種做法可能不會有質量爲標準亮度的方法相同的水平,但如果你正在尋找速度和質量之間的妥協,而不想對付昂貴的浮點操作,它可能適合你。