簡體   English   中英

java.awt.image.BufferedImage使用自定義ColorSpace進行24位RGB到8位灰度轉換

[英]java.awt.image.BufferedImage 24-bit RGB to 8-bit Grayscale conversion using custom ColorSpace

我想使用java.awt.image.BufferedImage為灰度轉換做一個簡單的顏色。 我是圖像處理領域的初學者,所以如果我感到困惑,請原諒。

我的輸入圖像是一個RGB 24位圖像(沒有alpha),我想在輸出上獲得一個8位灰度級BufferedImage ,這意味着我有一個這樣的類(為清晰起見省略了詳細信息):

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,這對我來說效果不佳,到目前為止正如我所知,但我不確定,我只是假設使用了這些值。 第二種方法效果較慢,但效果非常好。

有沒有一種方法可以將這兩者結合起來,例如: 使用自定義索引ColorSpace for ColorConvertOp 如果有,你能舉個例子嗎?

提前致謝。

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;
}

這里有一個例子它與你的第一個例子在一個小方面不同, ColorConvertOp的參數。 嘗試這個:

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

嘗試修改第二種方法。 不是處理單個像素,而是檢索argb int值的數組,將其轉換並重新設置。

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

這是一個在某些情況下對我有用的解決方案。

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

請記住,這種方法可能不會與標准亮度方法具有相同的質量水平,但如果您正在尋找速度和質量之間的折衷,並且不想處理昂貴的浮點運算,它可能會為你工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM