HTML-байтовый массив холста для изображения в Java - PullRequest
0 голосов
/ 06 сентября 2018

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

Actual graph

Сгенерированное изображение

Generated graph

У меня есть несколько графиков (скажем, не более 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)

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

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

Требуется: org.apache.commons.codec.binary.Base64 класс. Так что добавьте это к вашему classpath.

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

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

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

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

Решение:

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

ACTUAL_IMAGE_IN_PNG_FORMAT

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

  • Размер: 50px * 20px
  • Фон - Белый
  • М - черный
  • А - Желтый
  • 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.

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

0 голосов
/ 07 сентября 2018

Я следовал коду, который вы описали (спасибо, что он помогает мне проанализировать проблему, с которой я столкнулся, и я придерживался аналогичного подхода), после внесения приведенных ниже изменений в коде 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);
            }
...