当前位置: 首页 > 知识库问答 >
问题:

尝试用Java绘制24位图像

仲孙鸿飞
2023-03-14

我有一个图像,其中每个像素是4字节,即红色掩码是0xFF0000绿色是0xFF00和蓝色0xFF。我读取图像,并将其传递给函数作为函数(字节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:光栅太阳。awt。形象SunWritableRaster@1d82ed7与ColorModel DirectColorModel不兼容:rmask=ff0000 gmask=ff00 bmask=ff amask=0

我如何从字节缓冲通过PackedRaster到缓冲图像24位超过四个字节

共有1个答案

聂季同
2023-03-14

如果我理解正确,您正在尝试将字节样本数据流转换为buffereImage

为了澄清一些事情,一个4字节/像素图像是一个32位/像素图像(因为4*8是32),但是实际的颜色分量可能只跨越24位(3字节),因为一个8位分量留给了阿尔法(透明度)。鉴于这一事实,它是完全正常的,有一个24位的图像,每个颜色通道8位,没有alpha通道(其中图像将是一个3字节/像素图像)。

获得不兼容异常的原因是您使用了错误的方法来创建WritableRaster。

考虑到您的输入数据是字节数组的形式,并且您试图创建一个图像,其中每个字节存储的不是整个像素,而是一个像素样本,因此方法createPackedRaster()立即被视为不合适,因为该方法将每个数据元素(即每个字节)视为其自己的像素,而这肯定不是什么你正在努力完成这项任务。

要确定需要使用哪些“创建”方法,需要确定传入数据的格式。

下面显示三种主要类型的示例编码:

图像源amor。cms。胡伯林。判定元件

它们是带顺序格式(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......

由于有许多重载方法采用不同的参数,我们将使用采用dataType、宽度、高度、带和位置的方法。

对于数据类型,我们将使用常量DataBuffer。输入字节,因为我们正在输入字节数组。

宽度和高度由我们的方法参数提供,这里没有什么奇怪的地方。

波段对应于有多少不同的数据波段。如果您的输入流不包含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()一样简单,它应该(我可能在这里错了)工作。

 类似资料:
  • 我正在尝试使用pdfbox将图像添加到pdf的中心。下面是我的代码,但我无法在pdf中获得图像的正确位置。我在PDFBox中遵循了以下链接,如何更改PDRectangle对象的原点(0,0)?要获得正确的位置,但静止图像偏离中点位置?

  • 我现在正在做一个游戏,遇到了一些我想不出来的事情。我有一系列的ImageButton,我正在迭代,并在每个按钮上绘制位图。位图本身绘制得很好,但是我也想在这些位图上绘制矩形。 相关代码(如果这还不够,我可以发布更多): 位图本身出现在按钮上,但是我想要绘制的矩形没有被绘制。

  • 问题内容: 我目前有一个迷宫游戏,它绘制一个5 x 5的正方形(占用屏幕的宽度并将其均匀分割)。然后,对于每个使用x和y坐标的框,我使用drawRect绘制彩色背景。 我遇到的问题是我现在需要在同一位置绘制图像,因此需要替换当前的纯背景色填充。 这是我当前用于drawRect的代码(一些示例): 然后,我还需要为画布中的所有其他正方形实现背景图像。该背景将在其顶部绘制简单的1px黑色线条,当前代码

  • 我看了java文档和其他文章没有找到答案,这是我的最后一招:/ 提前致谢

  • 这是我的线程的最终输出,它获取屏幕截图并将其存储在一个矢量中。 用于获取屏幕截图,这些截图基本上是屏幕的光栅,不包含光标位置。作为一种解决办法,我使用类获取,然后获取一个。然后在该点绘制图像。 如果将记录区域设置为全屏分辨率,则一切都很酷。但是,如果我改变了记录区域,光标会被绘制在错误的位置。 这个黑色光标应该在Eclipse IDE的Play按钮的顶部。然而,它处于错误的位置。 如果光标超出记录

  • 很抱歉问了那个愚蠢的问题,但我是个安静的傻瓜。我不知道如何在Libgdx中绘制位图字体。我用过HIERO v2。0工具生成位图字体文件。然后我用代码初始化它: 但当我尝试在屏幕上绘制它时: 我得到这个结果:http://imageshack.us/photo/my-images/696/bitmapfont.png/有人知道我做错了什么吗?