Преобразование файла .bmp в двоичный файл и обратно в двоичный файл .bmp в Java

#java #bitmap #binary

#java #растровое изображение #двоичный

Вопрос:

Я пытаюсь преобразовать изображение (.bmp) в двоичный код, затем обработать его и преобразовать обратно. Давайте оставим часть обработки и просто сосредоточимся на преобразовании.

Что мне удалось сделать для преобразования изображения в двоичный файл сейчас:

     // Image to byte[]
    File file = new File("image.bmp");
    BufferedImage bufferedImage = ImageIO.read(file);
    WritableRaster raster = bufferedImage.getRaster();
    DataBufferByte data = (DataBufferByte) raster.getDataBuffer();

   // byte[] to binary String
   String string = "";
    for (byte b : data.getData()) {
        String substring = Integer.toBinaryString((b amp; 0xFF)   0x100).substring(1);
        string = string.concat(substring);
    }

  // Binary string to binary LinkedList<Ingeger> - this part is optional
  LinkedList<Integer> vector = new LinkedList<>();
    for (char c : stringVector.toCharArray()) {
        if (c == '0' || c == '1') {
            vector.add((int) c - 48);

        } else {
            System.out.println("Incorrect value.");
            break;
        }
    }
 

На данный момент я конвертирую файл (.bmp) в двоичный вектор. Я не уверен, правильно ли это.

Другая проблема заключается в преобразовании его обратно в файл .bmp. Мне нужно было бы преобразовать мой двоичный вектор (или строку) в byte[] и обратно в File или изображение.

Я считаю, что последний шаг будет выглядеть так:

         FileOutputStream fileOutputStream = new FileOutputStream("output.bmp");
        fileOutputStream.write(byteArrayFromBinary.getBytes());
 

Может кто-нибудь помочь мне разобраться? Потому что я не уверен, что именно в этом не так. Был бы благодарен за любые советы.

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

1. Файл BMP — это не только все данные изображения, которые вы получаете из растра; у него также есть, по крайней мере, заголовок. Таким образом, результат output.bmp не будет файлом BMP. Помимо этого, то, что вы делаете, крайне сбивает с толку. Я не могу себе представить, почему вы хотели бы работать с данными изображения как LinkedList<Integer> со всеми битами в растре. Я сильно подозреваю, что это проблема x-y, и вам было бы лучше объяснить, что вы на самом деле пытаетесь сделать.

2. LinkedList<Intgeger> часть, о которой я упоминал, является необязательной. Мне просто проще с ним работать (кодировать его, передавать по каналу, декодировать). Я буду делать то же самое с изображением, вот почему оно мне нужно как двоичное, и вот почему мне нужно преобразовать его обратно из двоичного файла в .bmp (после обработки). Но в этой теме я просто сосредоточен на преобразовании из .bmp в двоичный файл и обратно, и я немного застрял.

3. С какой стати вы конвертируете это в строку, из всех вещей? И использование алгоритма Schlemiel the Painter тоже? И, гм, на случай, если вы не заметили… bmp является двоичным, и, учитывая, что он несжат, он вообще не «закодирован». Чего вы на самом деле пытаетесь достичь всем этим?

4. @Nyerguds так что да, я делал это неправильно, теперь я опубликовал решение, которое отлично сработало для меня. Может быть, это не самое лучшее, но для меня это сработало. Я потратил на это некоторое время, пожалуйста, будьте добры, просмотрите его 🙂

Ответ №1:

Итак, после долгих исследований наконец-то появилось решение.

Чтобы преобразовать BufferedImage в формате .bmp в двоичный:

 public String imageToVector(BufferedImage image) throws Exception {
        String vectorInString = "";
        for (int x = 0; x < image.getWidth(); x  ) {
            for (int y = 0; y < image.getHeight(); y  ) {
                Color color = new Color(image.getRGB(x, y), false);
            vectorInString = vectorInString.concat(decimalToBinary(color.getRed()));
            vectorInString = vectorInString.concat(decimalToBinary(color.getGreen())); 
            vectorInString = vectorInString.concat(decimalToBinary(color.getBlue())); 
            }
        }
        return vectorInString;
}
 

Чтобы преобразовать обратно из двоичного вектора в BufferedImage в формате .bmp:

  String[] splittedString = vectorInString.split("(?<=\G.{8})");

    int i = 0;
    for (int x = 0; x < image.getWidth(); x  ) {
        for (int y = 0; y < image.getHeight(); y  ) {
            int red = Integer.parseInt(splittedString[i], 2); 
            i  ;
            int green = Integer.parseInt(splittedString[i], 2); 
            i  ;
            int blue = Integer.parseInt(splittedString[i], 2); 
            i  ;

            Color color = new Color(red, green, blue);

            image.setRGB(x, y, color.getRGB());
        }
    }
 

Если у вас есть какие-либо дополнительные вопросы, пожалуйста, задавайте, я могу объяснить, зачем мне понадобилось это решение.

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

1. Вы все еще используете алгоритм Schlemiel the Painter . Для создания длинных строк вы должны использовать StringBuilder, чтобы избежать значительных замедлений и дополнительного использования памяти. Кроме того, вы разбиваете на 8, но обрабатываете только RGB, без A, поэтому строка строится только на 3 байта. Разве это не должно быть 6, а не 8?

2. @Nyerguds Спасибо, учту ваши советы и улучшу свой алгоритм! Что касается количества байтов, да, вы правы, я разделил на 8 из-за другого варианта использования, но определенно это должно быть 6, потому что я не использую альфа-значения. Предоставленная вами ссылка была полезной, спасибо.