java - Java中HTML Canvas 字节数组到图像

标签 java arrays image bufferedimage javax.imageio

实际图像

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)

最佳答案

这是一个简单的解决方案,避免循环和所有手动工作。!!

必需: org.apache.commons.codec.binary.Base64 类。因此,将其添加到您的类路径中。

如果使用 Maven,请将以下依赖项添加到您的 pom.xml

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

如果使用 jar 作为依赖项,请在您的 lib 或类路径中添加以下 jar 文件。

Apache Commons Codec Jar File

解决方案:

以下是我的图像,我将使用字节数组重新创建它。

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

希望它有帮助......!!

关于java - Java中HTML Canvas 字节数组到图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52207023/

相关文章:

java - 将鼠标监听器添加到 Canvas 上,并在其上显示 lwjgl

Java:公开 protected 方法的简单方法

javascript - 如何在 JS 中选择具有特定值的数组中的对象

jquery - 在 div 中按比例调整图像 - 图像永远不应该被剪裁

image - 如何在 webroot View 中显示图像

java - 使用特定年份过去的天数获取一年中的月份和星期几

java - 使用 JAXB 解码

arrays - 将最小可能的正整数插入唯一整数数组

php - 计算特定值在数组中出现的频率

javascript - 在页面加载完成之前显示图像