Перестроить изображение массива байтов

#java #image #io #bytearray

#java #изображение #io #массивы

Вопрос:

Я пытаюсь получить изображение, закодированное в массиве байтов.

Это хорошо работает, если изображение не слишком большое, но когда мне приходится много раз читать входной поток, чтобы получить все байты изображения, строка:

 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 получается нулевое изображение.

Ответ №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 байт в каждой итерации while.

В первом запуске вы бы установили все элементы конечных данных равными 0, затем прочитали 10 байт и установили элементы 0-9 FinalData.

На второй итерации теперь вы перебираете содержимое tmpData (которое составляет байты 0-9) и перезаписываете байты 0-9, прежде чем читать байты 10-19 и добавлять их. (пока все хорошо)

На третьей итерации вы перемещаете содержимое tmpData (которое теперь составляет 10-19 байт со второй итерации) и перезаписываете байты 0-9 в FinalData. Итак, вот одна ошибка.

Комментарии:

1. да, это именно так… Слишком поспешно, я это пропустил. Просто поместите эту итерацию перед while, и все сработает как по маслу. Спасибо.

2. Это по-прежнему не отвечает на вопрос, почему вы считываете данные в массив байтов, а затем создаете 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);
  

Комментарии:

1. извините, я забыл эту строку: bis = новый BufferedInputStream (socket.getInputStream());

2. ну, в настоящее время у меня есть только мое изображение в моем bytearray, но в следующий раз у меня будет другая информация в этом же массиве. Вот почему я извлекаю байты, относящиеся к изображению.