有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中图像的HTML画布字节数组

真实图像

Actual graph

生成图像

Generated graph

我在客户端有多个使用Javascript(SAP/Open-UI-5)生成的图(比如最多14个),我已经将这些图转换为字节数组,下面是相同的代码

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);
  }
}

现在我使用RESTAPI和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) 个答案

  1. # 1 楼答案

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

    必选: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

    解决方案:

    下面是我的图片,我将使用byte array重新创建它

    ACTUAL_IMAGE_IN_PNG_FORMAT

    注意颜色:-

    • 尺寸:50px*20px
    • 背景-白色
    • M-黑色
    • A-黄色
    • N-绿色
    • O-蓝色
    • 橘子

    这只是为了验证不同的颜色是否被正确保留

    代码

    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

    希望能有帮助

  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);
                }