[英]Trying to Draw a 24bit image in Java
我有一個圖像,其中每個像素為4字節,即紅色蒙版為0xFF0000,綠色為0xFF00,藍色為0xFF。 我讀入圖像並將其傳遞給函數function(byte imgBuff,int w,int h)然后我有了
void fun(byte imgBuff,int w,int h)
{
Graphics g;
BufferedImage img;
DataBuffer dBuffer = new DataBufferByte(imgBuff, w * h);
WritableRaster wr = Raster.createPackedRaster(dBuffer,w,h,24,null);
DirectColorModel dcm = new DirectColorModel(24,0xFF0000,0xFF00,0xFF);
img = new BufferedImage(dcm,wr,false,null);
g = getGraphics();
g.drawImage(img,x,y,w,h,null);
}
但是當我跑步時我得到
線程“ Thread-23”中的異常java.lang.IllegalArgumentException:光柵sun.awt.image.SunWritableRaster@1d82ed7與ColorModel DirectColorModel不兼容:rmask = ff0000 gmask = ff00 bmask = ff amask = 0
我如何從PackedRaster的字節PackedRaster
到PackedRaster
圖像(四位以上為24位)
如果我正確理解了這個問題,則您正在嘗試將字節樣本數據流轉換為BufferedImage
。
為了澄清一些事情,一個4字節/像素的圖像是一個32位/像素的圖像(因為4 * 8為32),但是實際的顏色分量可能僅跨越24位(3字節)作為一個8位分量。留給Alpha(透明度)。 考慮到這一事實,擁有一個24位圖像,每個顏色通道具有8位並且沒有alpha通道是完全正常的(此時該圖像將是3字節/像素圖像)。
出現不兼容異常的原因是您使用了錯誤的方法來創建WritableRaster。
假設您的輸入數據為字節數組形式,並且您嘗試創建一個圖像,其中每個字節存儲的不是整個像素而是一個像素的樣本,則createPackedRaster()
方法立即被視為不合適,因為該方法會處理每個數據元素(即每個字節)作為自己的像素,這絕對不是您要在此處完成的工作。
要確定您需要使用哪種“創建”方法,您需要確定傳入數據的格式。
樣本編碼的三種主要類型如下所示:
它們是波段順序格式(bsq),按像素格式交織的波段(bip)和按行格式交織的波段(bil)。 該圖像演示了如何對3 x 3樣本圖像進行編碼。 為簡單起見,我們僅考慮后兩個(BIP和BIL),因為BSQ很少使用( 據我所知 )。
如果通過的圖像數據是BIP格式(也稱為像素交錯),則需要使用createInterleavedRaster()
方法讀取輸入數據。 如文檔所述:
基於具有指定數據類型的PixelInterleavedSampleModel創建一個Raster。
我們需要確定的另一個因素是,如果通過的字節數據包含alpha,則本質上圖像數據是否像這樣(假設BIP):
RGBRGB ....
要么
RGBARGBA ....
由於有許多采用不同參數的重載方法,我們將使用一種采用dataType,寬度,高度,波段和位置的方法。
對於dataType,我們將使用常量DataBuffer.TYPE_BYTE
因為我們正在輸入字節數組。
寬度和高度由我們的方法參數提供,這里沒有什么時髦。
這些頻帶對應於有多少個不同的數據頻帶。 如果您的輸入流不包含Alpha,您將具有三個不同的波段(紅色,綠色和藍色)。 如果輸入數據包含Alpha,則圖像將具有四個波段(紅色,綠色,藍色和Alpha)。
該語句將如下所示:
//Replace '4' with '3' if your image doesn't have alpha
WritableRaster wr = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null);
接下來要擔心的是ColorModel。 由於我們不再使用createPackedRaster()
方法,因此我們需要將ColorModel的類型也更改為ComponentColorModel
。 由於時間太長,我只向您展示我所做的事情(不過請您自己閱讀文檔 )。
如下:
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
//Change the first 'true' to 'false' if you don't have alpha.
ComponentColorModel ccm = new ComponentColorModel(sRGB, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
現在,將它們組裝在一起:
void fun(byte[] imgBuff,int w,int h) throws IOException{
WritableRaster wr = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null);
wr.setDataElements(0, 0, w, h, imgBuff);
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ComponentColorModel ccm = new ComponentColorModel(sRGB, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage img = new BufferedImage(ccm, wr, false, null);
}
您會注意到我添加了一行wr.setDataElements(0, 0, w, h, imgBuff)
。 該行直接使用字節數組有效地將實際數據填充到WritableRaster中(無需創建DataBufferByte對象)。
我之前提到過,我將同時討論BIP和BIL。 將上述方法從BIP更改為BIL就像將createInterleavedRaster()
方法交換為createBandedRaster()
一樣簡單,並且它(在這里我可能錯了) 應該是一樣的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.