5

我正在使用 JNA。我正在从我的 c++ 方法中获取原始数据的字节数组。现在我被困在如何使用这个原始数据字节数组在 java 中获取缓冲图像。我尝试了几件事来将其作为 tiff 图像,但我没有成功。这是我到目前为止尝试的代码。这里我的字节数组包含 16 位灰度图像的数据。我从 x-sensor 设备中获取这些数据。现在我需要从这个字节数组中获取图像。

第一次尝试

byte[] byteArray = myVar1.getByteArray(0, 3318000);//array of raw data

          ImageInputStream stream1=ImageIO.createImageInputStream(newByteArrayInputStream(byteArray));
            ByteArraySeekableStream stream=new ByteArraySeekableStream(byteArray,0,3318000);
                 BufferedImage bi = ImageIO.read(stream);

第二次尝试

        SeekableStream stream = new ByteArraySeekableStream(byteArray);
         String[] names = ImageCodec.getDecoderNames(stream);


          ImageDecoder dec = ImageCodec.createImageDecoder(names[0], stream, null);
//at this line get the error ArrayIndexOutOfBoundsException: 0 
            RenderedImage im = dec.decodeAsRenderedImage();

我想我在这里失踪了。由于我的数组包含原始数据,因此它不包含 tiff 图像的标头。我对吗?如果是,那么如何在字节数组中提供此标头。最终如何从这个字节数组中获取图像?

为了测试我是否从我的本机方法中获得了正确的字节数组,我将此字节数组存储为 .raw 文件,并在 ImageJ 软件中打开此原始文件后,它会播下正确的图像,因此我的原始数据是正确的。我唯一需要的是如何将我的原始字节数组转换为图像字节数组?

4

2 回答 2

9

这是我用来将原始像素数据转换为BufferedImage. 我的像素是 16 位签名的:

public static BufferedImage short2Buffered(short[] pixels, int width, int height) throws IllegalArgumentException {
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);
    short[] imgData = ((DataBufferShort)image.getRaster().getDataBuffer()).getData();
    System.arraycopy(pixels, 0, imgData, 0, pixels.length);     
    return image;
}

然后我使用 JAI 对生成的图像进行编码。告诉我你是否也需要代码。

编辑:感谢@Brent Nash对类似问题的回答,我大大提高了速度。

编辑:为了完整起见,这里是无符号 8 位的代码:

public static BufferedImage byte2Buffered(byte[] pixels, int width, int height) throws IllegalArgumentException {
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
    byte[] imgData = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
    System.arraycopy(pixels, 0, imgData, 0, pixels.length);     
    return image;
}
于 2012-06-19T16:11:28.187 回答
4

字节数组是否只包含像素数据或结构化图像文件(如 TIFF 等)实际上取决于您从哪里获得它。从提供的信息中无法回答这个问题。

但是,如果它确实包含结构化图像文件,那么您通常可以:

  • 在它周围包裹一个 ByteArrayInputStream
  • 将该流传递给 ImageIO.read()

如果您只有字面上的原始像素数据,那么您有几个主要选择:

  • “手动”获取该像素数据,使其位于一个 int 数组中,每个像素一个 int,采用 ARGB 格式(ByteBuffer 和 IntBuffer 类可以帮助您处理字节)
  • 创建一个空白的 BufferedImage,然后调用它的 setRGB() 方法从你之前准备的 int 数组中设置实际的像素内容

如果你知道你在用比特和字节做什么,我认为上面是最简单的。但是,原则上,您应该能够执行以下操作:

  • 找到一个合适的 WritableRaster.create... 方法方法,该方法将创建一个包裹在数据周围的 WritableRaster 对象
  • 将该 WritableRaster 传递给相关的 BufferedImage 构造函数以创建图像。
于 2012-05-23T12:52:56.487 回答