尝试用Java绘制24位图像
我有一个图像,其中每个像素是4字节,即红色掩码是0xFF0000,绿色是0xFF00,蓝色是0xFF。我读入图像并将其作为函数传递给函数(字节imgBuff,intw,inth) 那么我有尝试用Java绘制24位图像,java,bufferedimage,illegalargumentexception,Java,Bufferedimage,Illegalargumentexception,我有一个图像,其中每个像素是4字节,即红色掩码是0xFF0000,绿色是0xFF00,蓝色是0xFF。我读入图像并将其作为函数传递给函数(字节imgBuff,intw,inth) 那么我有 void fun(byte imgBuff,int w,int h) { Graphics g; BufferedImage img; DataBuffer dBuffer = new DataBufferByte(imgBuff, w * h); Wr
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转换为四字节24位的缓冲图像如果我正确理解了这个问题,您正在尝试将字节样本数据流转换为缓冲图像
为了澄清一些事情,4字节/像素图像是32位/像素图像(因为4*8是32),但是实际的颜色分量可能只跨越24位(3字节),因为一个8位分量留给Alpha(透明度)。考虑到这一事实,具有每个颜色通道8位且没有alpha通道的24位图像(其中图像将是3字节/像素图像)是完全正常的
出现不兼容异常的原因是您使用了错误的方法来创建可写光栅
考虑到您的输入数据是字节数组的形式,并且您试图创建一个图像,其中每个字节存储的不是整个像素,而是一个像素样本,因此方法createPackedRaster()
立即被视为不合适,因为该方法处理每个数据元素(即每个字节)作为它自己的像素,这绝对不是你想要实现的
要确定需要使用哪些“创建”方法,需要确定传入数据的格式
下面显示了三种主要的样本编码类型:
图像源
它们是波段顺序格式(bsq)、按像素格式交织的波段(bip)和按行格式交织的波段(bil)。该图像演示了如何对3×3样本图像进行编码。为了简单起见,我们只考虑后两个(BIP和BIL),因为BSQ很少使用(据我所知)。
如果通过的图像数据是BIP格式,也称为像素交错,则需要使用createInterleavedRaster()
方法读取输入数据。如文件所述:
基于具有指定数据类型的像素InterleavedSampleModel创建光栅
我们需要确定的另一个因素是,如果通过的字节数据包含alpha,那么实际上图像数据是否是这样的(假设BIP):
R G B R G B
或
R G B A R G B A
由于有许多重载方法采用不同的参数,我们将使用一种采用数据类型、宽度、高度、频带和位置的方法
对于数据类型,我们将使用常量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()
方法替换为CreateBandedMaster()
,它应该(这里可能是错误的)工作原理相同。如果我正确理解了这个问题,您正在尝试将字节样本数据流转换为缓冲区图像
为了澄清一些事情,4字节/像素图像是32位/像素图像(因为4*8是32),但是实际的颜色分量可能只跨越24位(3字节),因为一个8位分量留给Alpha(透明度)。考虑到这一事实,具有每个颜色通道8位且没有alpha通道的24位图像(其中图像将是3字节/像素图像)是完全正常的
出现不兼容异常的原因是您使用了错误的方法来创建可写光栅
考虑到您的输入数据是字节数组的形式,并且您试图创建一个图像,其中每个字节存储的不是整个像素,而是一个像素样本,因此方法createPackedRaster()
立即被视为不合适,因为该方法处理每个数据元素(即每个字节)作为它自己的像素,这绝对不是你想要实现的
要确定需要使用哪些“创建”方法,需要确定传入数据的格式
下面显示了三种主要的样本编码类型:
图像源
它们是波段顺序格式(bsq)、按像素格式交织的波段(bip)和按行格式交织的波段(bil)。该图像演示了如何对3×3样本图像进行编码。为了简单起见,我们只考虑后两个(BIP和BIL),因为BSQ很少使用(据我所知)。
如果图像是dat