Search code examples
javaarraysimagebufferedimagejavax.imageio

HTML canvas byte array to Image in java


Actual image

Actual graph

Generated Image

Generated graph

I have multiple Graphs (say 14 max) which are generated using Javascript(SAP/Open-UI-5) at client side I have converted these graphs into bytes array below is the code for the same

JavaScript code

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

Now I am sending these bytes to server side using REST API and AJAX call and creating the images on the server side below is the code where I am recreating the images

Java code

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

But the color of my Image is not the same as expected. How can I recreate the image with exact same color as it was when it was created on the client side?

I have also tried the below code

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

the last line throws the exception

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

Solution

  • I have followed the code that you have described (Thank you as it helps me analyzing the problem I was facing and I have followed the similar approach ), after doing the below changes in java code I made the image exactly as that of the original image

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