Байт-массив HTML Canvas в изображение в java

Фактическое изображение

Байт-массив HTML Canvas в изображение в java

Созданное изображение

Байт-массив HTML Canvas в изображение в java

У меня есть несколько графиков (скажем, 14 макс.), Которые создаются с использованием Javascript (SAP / Open-UI-5) на стороне клиента. Я преобразовал эти графики в массив байтов. Ниже приведен код для того же

Код JavaScript

var arrCanvas = document.getElementsByTagName("canvas");
var arrImageByte = [];
for(var i=0; i<arrCanvas.length; i++){
  var canvas = arrCanvas[i];
  if (canvas.width!=0 && (typeof imageNames[i] != 'undefined')){
    var imageDetail = {};
    var uint8Array = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
    imageDetail.byteData = [].slice.call(uint8Array);
    imageDetail.name = imageNames[i];
    imageDetail.height = canvas.height;
    imageDetail.width = canvas.width;
    arrImageByte.push(imageDetail);
  }
}

Теперь я отправляю эти байты на сервер, используя REST API и вызов AJAX. и создание изображений на стороне сервера ниже - это код, в котором я воссоздаю изображения

Код Java

int width = imageDetail.getWidth();
int height = imageDetail.getHeight();
byte[] data = imageDetail.getByteData();
String name = imageDetail.getName();
BufferedImage bufferedImage =new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    // calculate array offset
    final int o = (x * 3) + (y * width * 3);
    // set the pixel color here we will need to convert the byte
    // data to an unsigned
    // value using &0xFF before passing it to the Color
    // constructor
    bufferedImage.setRGB(x, y, new Color(data[o + 1] & 0xFF, data[o + 2] & 0xFF, data[o + 3] & 0xFF).getRGB());
  }
}

boolean result = ImageIO.write(bufferedImage, "jpg", new File(baseReportFolderLocation+name+".jpg"));
logger.info("Name "+name+" status :: "+result);

Но цвет моего изображения не такой, как ожидалось. Как я могу воссоздать изображение с точно таким же цветом, каким оно было при создании на стороне клиента?

Я также пробовал приведенный ниже код

byte[] data = imageDetail.getByteData();
        String name = imageDetail.getName();        
        BufferedImage bImageFromConvert = ImageIO.read(new ByteArrayInputStream(data));
        ImageIO.write(bImageFromConvert, "jpg", new File(baseReportFolderLocation+"New_"+name+".jpg"));

последняя строка вызывает исключение

java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
at javax.imageio.ImageIO.getWriter(ImageIO.java:1592)

Почему вы устанавливаете bufferedImage.setRGB() вручную, поскольку вы сказали, что изображение уже создано на клиенте, и его байты отправляются в Java-код. ??

miiiii 06.09.2018 17:05

@MadMan, потому что массив байтов на стороне клиента несовместим с ImageTO. Запись вызывает ошибку преобразования [B в [I. Вы знаете, как мне получить желаемый результат?

Angular Bird 06.09.2018 17:16

@MadMan У меня такая же проблема. Ребята, вы нашли какое-нибудь решение?

Hades 06.09.2018 17:19

Какое полное название пакета ImageIO ??

miiiii 06.09.2018 17:30

@MadMan пакет javax.imageio

Angular Bird 06.09.2018 17:38

niharika и @Hades У меня есть решение .. не могли бы вы, ребята, просто предоставить свой ответ байтового массива .. ?? Или просто скажите мне, массив байтов закодирован по базе 64 или нет ??

miiiii 06.09.2018 19:17

@Nope, по крайней мере, в моем случае, поскольку, когда я сделал canvas.getContext ("2d"). GetImageData, он вернул байт uint8array, который копируется в новый массив со знаком из 0-255

Angular Bird 06.09.2018 19:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
7
850
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я следил за кодом, который вы описали (спасибо, поскольку он помогает мне анализировать проблему, с которой я столкнулся, и я следовал аналогичному подходу), после внесения следующих изменений в код Java я сделал изображение точно таким же, как исходное изображение

int width = imageDetail.getWidth();
            int height = imageDetail.getHeight();
            byte[] data = imageDetail.getByteData();
            String name = imageDetail.getName();
            BufferedImage bufferedImage =new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int o = (x * 4) + (y * width * 4);
                    bufferedImage.setRGB(x, y, new Color(data[o] & 0xFF, data[o + 1] & 0xFF, data[o + 2] & 0xFF).getRGB());
                }
            }   
            try {
                ImageIO.write(bufferedImage, "jpg", new File(PDFReportingUtil.baseReportFolderLocation+name+".jpg"));
            } catch (IOException e) {
                PDFReportingUtil.logger.error("Error while executing the thread "+Thread.currentThread().getName()+" ",e);
            }

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

miiiii 07.09.2018 11:57

@Hades Это работает отлично ... не знал, что такая небольшая проблема вызывает огромные проблемы, Спасибо.

Angular Bird 07.09.2018 16:19

Вот простое решение, позволяющее избежать петель и всей ручной работы. !!

Необходимые :org.apache.commons.codec.binary.Base64 класс. Так что добавьте это в свой путь к классам.

Если вы используете Maven, добавьте ниже зависимость к вашему pom.xml

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
</dependency>

Если для зависимостей используется jar, добавьте следующий файл jar в свой lib или путь к классам.

Файл Jar-файла кодека Apache Commons

Решение:

Ниже приведено мое изображение, которое я собираюсь воссоздать с помощью byte array.

ACTUAL_IMAGE_IN_PNG_FORMAT

Обратите внимание на цвет: -

  • Размер: 50 пикселей * 20 пикселей
  • Фон - белый
  • M - черный
  • A - желтый
  • N - зеленый
  • O - синий
  • J - Апельсин

Это просто для того, чтобы убедиться, что разные цвета сохраняются должным образом.

Код

public static void main(String args[]) throws Exception {

    String abs = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAUCAIAAABAqPnNAAAAAXNSR0IArs4c6QAAAARnQU1BAACx\n" +
            "jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIBSURBVEhL7ZW9SgNREIXzBD5EGt8hjdhZSAqf\n" +
            "QVIkkC5gZ5VSWAg2IbUQtrJZSBGDIEQhXVAIN1FCcBtZCwstx/m7u3d/VAQ1Ch4uZGZuYD/OmU1K\n" +
            "8Cv1j/UZ/SEs41VKqIpndCAKajQt1QLtv1YPPTjchOOedAVYSpUBUKjvooLzPcI6v5MujxVTuQQW\n" +
            "6tuoMsphJVQxAo8qFZrraA73DZhuwBUf0+EhKzwqn+6WJ3530qTitNkK9Qa1HIft+mRrh099caFj\n" +
            "m6B/pm0eS6hqNXJHGATK85IJPHeIZtoA01CyiOcAwwmi0KmOBGu3PPJv+WrZvxag/bot+i98YxO8\n" +
            "0Q6VwVKqQFmMhTKcYlGC99sO1mWLUI6GT9ypc5dUr8J9cihc8g2MFw7WHRxvwuEB16o0lqWyNAF9\n" +
            "2NahmkM00ENRNnTMHNXZSrrbGRkmIYpV7TFfZNpcgqgUVvJ0qUhJp1SG7XGPGfCFJNjsilWw6o7Y\n" +
            "OapfTmil4mVKt7kEUS6W83SL5TRcRrxM0Zy+jsonaDcJnvzqGwmKVe8kiHKw0p54uPYB/566c8P2\n" +
            "yLJPxbaPE1QsOtdaxEtWlCAqweKnZ3/ZUSnaiN9BOtv6Gn6cIGnZX8Rk7f6jMqGKEkSlV/6nVZwg\n" +
            "an1YNz3w2apcgqh1YYlP+N9cYBVqvSG+qV+JBfAKOyszW/bU2FMAAAAASUVORK5CYII = ";

    byte [] sam = abs.getBytes(); // your bytes data goes here.. no need to create string and bytes from it. I did it for demo.
    byte [] data = org.apache.commons.codec.binary.Base64.decodeBase64(sam);
    FileOutputStream imageOutFile = new FileOutputStream(
            "i-love-sample.jpg");
    imageOutFile.write(data);
    imageOutFile.close();
    System.out.println("Image Successfully Manipulated!");

}

На выходе будет точно такое же изображение, но я преобразовал его в jpg (см. Код), поэтому теперь изображение является jpg. Вы можете указать любой желаемый формат.

Выходное изображение:

OUTPUT_IMAGE_IN_JPG_FORMAT

Смотрите цвета, они же воссоздаются без потерь.

Теперь, как я понимаю, вы получаете массив byte от клиента, поэтому следуйте комментарию в приведенном выше коде. Вы сделали. Не нужно использовать даже javax.imageio.ImageIO.

Надеюсь, это помогло ... !!

Спасибо @Mad Man за ответ, но я хочу, чтобы преобразование байтов происходило на стороне клиента, поскольку несколько таких декодированных строк base64 (почти 15) занимают огромное количество времени на преобразование (хотя я реализовал поток в этом преобразовании) подход, который я я использую очень быстро (разница почти в 15-20 секунд) на изображение.

Angular Bird 08.09.2018 20:24

Хотя у меня недостаточно репутации, чтобы проголосовать за ваш ответ, и я могу принять только один в качестве ответа, работающего для меня.

Angular Bird 08.09.2018 20:25

да, я пробовал кодировщик base 64, на преобразование одного изображения ушло почти 40 секунд. Есть ли у декодера apache другой более быстрый способ преобразования строки в байты?

Hades 08.09.2018 20:56

Причина проблемы с производительностью заключается в том, что в соответствии со спецификацией Java, Тип данных char - это один 16-битный символ Unicode. & Тип данных byte - это 8-битовое целое число с дополнением до двух со знаком., поэтому для каждого символа должен быть вызов функции, в противном случае сразу выбросить первые 8 бит char, но затем может произойти потеря данных, поскольку некоторые из символов не работают. t помещается в 8-битное пространство.

miiiii 09.09.2018 09:17

Другие вопросы по теме