【问题标题】:Rebuild byte array image重建字节数组图像
【发布时间】:2011-05-09 12:12:56
【问题描述】:

我正在尝试接收以字节数组编码的图像。

如果图像不是太大,效果很好,但是当我必须多次读取输入流以获取所有图像字节时,行:

BufferedImage img = ImageIO.read(new ByteArrayInputStream(finalData));

返回null

这是我的代码:

byte[]imgSize = new byte[SIZE_OF_LENGTH_ARRAY];
bis.read(imgSize, 0, SIZE_OF_LENGTH_ARRAY);
ByteBuffer bb = ByteBuffer.wrap(imgSize);
int size = bb.getInt();

System.out.println("Client: size="+size);
byte[] tmpData = new byte[size];
System.out.println("tmpData length = "+tmpData.length);
int readen = bis.read(tmpData, 0, tmpData.length);
System.out.println("readen="+readen);

byte[]finalData = new byte[size]; 

if(readen == size){
    finalData = tmpData;
}
else{
    int totalRead = readen;
    int j=1;

    while(totalRead<size){
        System.out.println("-----------append number "+j+"----------");
        System.out.println("totalRead="+totalRead);

        for(int i=0;i<tmpData.length;i++){
            finalData[i]=tmpData[i];
        }

        tmpData = new byte[size-totalRead];
        int tmpRead = bis.read(tmpData, 0, size-totalRead);
        System.out.println("tmpRead="+tmpRead);

        for(int i=0;i<tmpData.length;i++){
            finalData[i+totalRead]=tmpData[i];
        }

        totalRead+=tmpRead;
        j++;
    }
    System.out.println("totalRead final="+totalRead);
}

BufferedImage img = ImageIO.read(new ByteArrayInputStream(finalData));

一个输出示例是:

---Client: sending mess number 1---
Client: size=31099
tmpData length = 31099
readen=31099
---Client: sending mess number 2---
Client: size=85921
tmpData length = 85921
readen=17520
-----------append number 1----------
totalRead=17520
tmpRead=17520
-----------append number 2----------
totalRead=35040
tmpRead=17520
-----------append number 3----------
totalRead=52560
tmpRead=31408
-----------append number 4----------
totalRead=83968
tmpRead=1953
totalRead final=85921
image null

虽然我很好地读取了 85921 个字节,但 ImageIO.Read 生成了一个空图像。

【问题讨论】:

    标签: java image io bytearray


    【解决方案1】:

    这一行可能会覆盖上一个 while 迭代的字节:

     while(totalRead<size){
            System.out.println("-----------append number "+j+"----------");
            System.out.println("totalRead="+totalRead);
            //I suspect this is unnecessary and one source of the error
            //this loop would overwrite data from the last iteration's tmpData
            for(int i=0;i<tmpData.length;i++){ 
                finalData[i]=tmpData[i];
            }
            tmpData = new byte[size-totalRead];
            int tmpRead = bis.read(tmpData, 0, size-totalRead);
            System.out.println("tmpRead="+tmpRead);
            for(int i=0;i<tmpData.length;i++){
                finalData[i+totalRead]=tmpData[i];  //append tmpData
            }
            totalRead+=tmpRead;
            j++;
        }
    

    假设您在每次迭代中读取 10 个字节。

    在第一次运行中,您会将最终数据的所有元素设置为 0,然后读取 10 个字节并设置最终数据的 0-9 元素。

    在第二次迭代中,您现在循环遍历 tmpData 的内容(即字节 0-9)并在读取字节 10-19 并附加它们之前覆盖字节 0-9。 (到目前为止一切顺利)

    在第三次迭代中,您将 tmpData 的内容(现在是第二次迭代的第 10-19 个字节)的内容覆盖掉,并覆盖 finalData 中的第 0-9 个字节。所以这里有一个错误。

    【讨论】:

    • 是的,就是这样……太着急了,我错过了。只需将此迭代放在一段时间之前,就可以像魅力一样工作。谢谢。
    • 这仍然不能回答为什么您将数据读入字节数组,然后创建一个 ByteArrayInputStream 作为 ImageIO.read 的参数。只需将原始流提供给 ImageIO.read。它会为你读取数据。
    【解决方案2】:

    我不知道 bis 是什么,但这行可能是错误的:

    bis.read(imgSize, 0, SIZE_OF_LENGTH_ARRAY);
    

    您应该始终检查读取的返回值。一次读取可以读取少于您指定的内容。

    编辑:

    这是您通常从流中读取所有数据的方式:

    byte[] buffer = new byte[1024 * 32];
    int len = 0;
    while ((len = in.read(buffer)) > -1) {
        out.write(buffer, 0, len);
    }
    

    编辑2:

    但是你为什么不做类似的事情:

    ImageIO.read(bis);
    

    【讨论】:

    • 对不起,我忘记了这一行:bis = new BufferedInputStream(socket.getInputStream());
    • 好吧,目前我的字节数组中只有我的图像,但接下来我将在同一个数组中包含其他信息。这就是我提取有关图像的字节的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    相关资源
    最近更新 更多