我有一个图像,其中每个像素是4个字节,即红色掩码是0xFF0000绿色是0xFF00和蓝色0xFF。我在图像中读取并将其作为函数传递给函数(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
从bytebuffer到4位字节的24位缓冲图像
答案 0 :(得分:4)
如果我正确理解了这个问题,那么您正尝试将字节样本数据流转换为BufferedImage
。
为了澄清一些事情,4字节/像素图像是32位/像素图像(4 * 8是32),但实际颜色分量可能仅跨越24位(3个字节),因为一个8位组件留给Alpha(透明度)。鉴于这一事实,拥有一个24位图像,每个颜色通道8位,没有alpha通道(图像将是一个3字节/像素的图像)是完全正常的。
您获得不兼容性异常的原因是您使用了错误的方法来创建WritableRaster。
鉴于您的输入数据是字节数组的形式,并且您正在尝试创建一个图像,其中每个字节不存储整个像素,而是像素的样本方法{{ 1}}被立即认为是不合适的,因为该方法将每个数据元素(即每个字节)视为自己的像素,这绝对不是你想要在这里完成的。
要确定您需要使用哪种“创建”方法,您需要确定传入数据的格式。
下面显示了三种主要的样本编码类型:
它们是波段顺序格式(bsq),通过像素格式(bip)交错的波段和通过线格式(bil)交织的波段。该图像演示了如何编码3乘3的样本图像。为简单起见,我们只考虑后两者(BIP和BIL),因为很少使用BSQ(据我所知, )。
如果通过的图像数据采用BIP格式,也简单地称为像素交错,则需要使用createPackedRaster()
方法读取输入数据。正如文档所述:
基于具有指定数据类型的PixelInterleavedSampleModel创建Raster。
我们需要确定的另一个因素是,如果通过的字节数据包含alpha,实质上是否图像数据是这样的(假设是BIP):
R G B R G B ....
或
R G B A R G B A ....
由于有许多重载方法采用不同的参数,我们将使用带有dataType,宽度,高度,波段和位置的方法。
对于dataType,我们将使用常量createInterleavedRaster()
,因为我们正在输入一个字节数组。
宽度和高度由我们的方法参数提供,这里没什么好用的。
这些频段对应于有多少不同的数据带。如果输入流不包含alpha,则会有三个不同的波段(红色,绿色和蓝色)。如果输入数据包含alpha,则图像将具有四个波段(红色,绿色,蓝色和alpha)。
该陈述如下所示:
DataBuffer.TYPE_BYTE
担心的下一部分是ColorModel。由于我们不再使用//Replace '4' with '3' if your image doesn't have alpha
WritableRaster wr = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null);
方法,因此我们需要将ColorModel的类型更改为createPackedRaster()
。由于这有点长,我只会告诉你我做了什么(请尽快阅读documentation)。
如下:
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);
}
。该行有效地使用字节数组直接将实际数据填充到WritableRaster中(无需创建DataBufferByte对象)。
我之前提到过,我会谈论BIP和BIL。将上述方法从BIP更改为BIL应该就像将wr.setDataElements(0, 0, w, h, imgBuff)
方法交换到createInterleavedRaster()
一样简单,而应该(我可能在这里错了)也可以正常工作。