【问题标题】:How to convert array of bytes into Image in Java SE如何在 Java SE 中将字节数组转换为图像
【发布时间】:2010-11-11 17:06:42
【问题描述】:

在 Java SE 中将原始字节数组转换为 Image 的正确方法是什么。 数组由字节组成,每三个字节代表一个像素,每个字节对应对应的RGB分量。

谁能推荐一个代码示例?

谢谢, 迈克

【问题讨论】:

  • 最终我没有找到更好的东西: for(int y=0; y
  • 字节数组的维度是多少?是一维数组,二维数组,还是3维数组?

标签: java image graphics


【解决方案1】:

假设您的原始数据是一维数组,例如:

byte[] imageBytes = new byte[1024];
// transform to bufferImage
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
// if you want to do some operations to the image, like resize, 
// use the lib (net.coobird.thumbnailator)
BufferedImage image = Thumbnails.of(bufferedImage).forceSize(WIDTH, HEIGHT)
                                .outputFormat("bmp").asBufferedImage();

【讨论】:

    【解决方案2】:

    您可以使用 Raster 类来做到这一点。它更好,因为它不需要迭代和复制字节数组。

     byte[] raw = new byte[width*height*3]; // raw bytes of our image
     DataBuffer buffer = new DataBufferByte(raw, raw.length);
    
     //The most difficult part of awt api for me to learn
     SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width*3, new int[]{2,1,0});
    
     Raster raster = Raster.createRaster(sampleModel, buffer, null);
    
     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
     image.setData(raster);
    

    【讨论】:

    • 感谢发布。它真的派上用场了!
    【解决方案3】:

    如果您的 RGB 值按 B、G、R 顺序排列,folkyatina 的方法有效,但如果它们按 R、G、B 顺序排列,我发现以下代码可以工作:

        DataBuffer rgbData = new DataBufferByte(rgbs, rgbs.length);
    
        WritableRaster raster = Raster.createInterleavedRaster(
            rgbData, width, height,
            width * 3, // scanlineStride
            3, // pixelStride
            new int[]{0, 1, 2}, // bandOffsets
            null);
    
        ColorModel colorModel = new ComponentColorModel(
            ColorSpace.getInstance(ColorSpace.CS_sRGB),
            new int[]{8, 8, 8}, // bits
            false, // hasAlpha
            false, // isPreMultiplied
            ComponentColorModel.OPAQUE,
            DataBuffer.TYPE_BYTE);
    
        return new BufferedImage(colorModel, raster, false, null);
    

    【讨论】:

      【解决方案4】:

      有一个 setRGB 变体,它接受一个 RGBA 值的 int 数组:

      BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      int[] raw = new int[data.length * 4 / 3];
      for (int i = 0; i < data.length / 3; i++) {
          raw[i] = 0xFF000000 | 
              ((data[3 * i + 0] & 0xFF) << 16) |
              ((data[3 * i + 1] & 0xFF) << 8) |
              ((data[3 * i + 2] & 0xFF));
      }
      img.setRGB(0, 0, width, height, raw, 0, width);
      

      性能特点类似于CoderTao的方案。

      【讨论】:

        【解决方案5】:

        假设您知道图像的高度和宽度。

        BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for(int r=0; r<height; r++)
        for(int c=0; c<width; c++)
        {
          int index=r*width+c;
          int red=colors[index] & 0xFF;
          int green=colors[index+1] & 0xFF;
          int blue=colors[index+2] & 0xFF;
          int rgb = (red << 16) | (green << 8) | blue;
          img.setRGB(c, r, rgb);
        }
        

        大概。这假设像素数据被编码为一组行;并且颜色的长度是 3 * width * height (应该是有效的)。

        【讨论】:

        • 所以迭代数组是我最好的选择吗?感觉必须有某种方法可以接受数组作为参数并一次性填充/重新创建图像。也许与 Raster 类有关?
        • 据我所知,尽管 Raster 对我来说并不熟悉。如果这遵循标准图像格式,您可以使用 ImageIO 类,但这是我知识的限制。
        • 你也可以这样做:int rgb = ((int)colors[in] &lt;&lt; 24) + ((int)colors[in+1] &lt;&lt; 8) + (int)colors[in]
        • 这样你就可以解决sign/unsign问题:frameImg.setRGB(x, y, ((data[i0]&0xFF) | ((data[i0+1]&0xFF)
        • 尽管被接受,但这个答案似乎并不正确。如果 colors 是一个 RGB 数组(其中 R、G 和 B 是单独的字节),index 是否应该在每个循环中增加超过 1?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-17
        • 2011-06-01
        • 2023-03-09
        相关资源
        最近更新 更多