簡體   English   中英

嘗試用Java繪制24位圖像

[英]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的字節PackedRasterPackedRaster圖像(四位以上為24位)

如果我正確理解了這個問題,則您正在嘗試將字節樣本數據流轉換為BufferedImage

為了澄清一些事情,一個4字節/像素的圖像是一個32位/像素的圖像(因為4 * 8為32),但是實際的顏色分量可能僅跨越24位(3字節)作為一個8位分量。留給Alpha(透明度)。 考慮到這一事實,擁有一個24位圖像,每個顏色通道具有8位並且沒有alpha通道是完全正常的(此時該圖像將是3字節/像素圖像)。

出現不兼容異常的原因是您使用了錯誤的方法來創建WritableRaster。

假設您的輸入數據為字節數組形式,並且您嘗試創建一個圖像,其中每個字節存儲的不是整個像素而是一個像素的樣本,createPackedRaster()方法立即被視為不合適,因為該方法會處理每個數據元素(即每個字節)作為自己的像素,這絕對不是您要在此處完成的工作。

要確定您需要使用哪種“創建”方法,您需要確定傳入數據的格式。

樣本編碼的三種主要類型如下所示:

圖像樣本編碼演示

圖片來源amor.cms.hu-berlin.de

它們是波段順序格式(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.

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