Decode JPEG2000 bitarray image with Javascript

user1211709 picture user1211709 · Feb 15, 2012 · Viewed 10.7k times · Source

I'm using HTML5 technology with the FileApi.

My problem is very simple, but i'm searching since 2 days ago and I have not find anything on the web

I have a DicomFile. I use the FileApi from HTML5 to break it down, and get all the information. Finally I get the image data in a byte array. The problem is that I can not decode a JPEG2000 Image and show it in the browser (Chrome, FireFox, any). For example, if the image data is coded in JPEG format, I have no problem at all to show the image in the browser, but the problem is with JPEG2000 or JPEG-LS. I know that those Image formats aren't able to show in the web browers, but It must exist a library in Javascript to decode the image data that is in JPEG2000 or JPEG-LS. It's very important and I am a bit desesperate.

If I can not find any way to do this, I'll have to change all my work.

Thank you very much in advance

Answer

Mark Rhodes picture Mark Rhodes · Mar 14, 2012

Since JPEG 2000 images don't render natively in browsers, you'll probably have to convert them to something that browsers can render before using them on a web-page. The easiest way to do this would be to just convert the images server side to some web-safe format then serve the converted images to the browser. However, if you're determined to do it client side then, then there is an example of using JavaScript to decode JPEG 2000 images here: https://github.com/kripken/j2k.js/blob/master/examples/simple.html.

This works using a JavaScript compilation of the OpenJPEG library, available here. This this is an automatic conversion it's not the nicest to use, but they supply the following function makes it's use a bit easier:

// Wrapper around OpenJPEG..
//Converts the given j2k image array to RGB values that
//can be put into a Canvas..
function j2k_to_image(data) {
    run();
    _STDIO.prepare('image.j2k', data);
    callMain(['-i', 'image.j2k', '-o', 'image.raw']);
    return _STDIO.streams[_STDIO.filenames['image.raw']].data;
}

Here data is expected to be JavaScript array of bytes (well JavaScript numbers with values between 0 and 255 inclusive) as in the example file. You could get this by converting the images to this form server side, or Ajaxing them in and treating the response as binary data (see MDN's using XHR's on how to do this for Firefox at least, other browsers probably need different methods). The output of this function is then put into a Canvas element like so:

  output = j2k_to_image([255, 0, 123, ...]); //pass in the JPEG 2000 image as an array

  var canvas = document.getElementById('canvas'); //get the canvas element (use whatever you actually need here!)
  canvas.width = imageWidth;
  canvas.height = imageHeight;

  var ctx = canvas.getContext('2d');
  var image = ctx.getImageData(0, 0, canvas.width, canvas.height);

  var componentSize = canvas.width*canvas.height;
  for (var y = 0; y < canvas.height; y++) {
    for (var x = 0; x < canvas.width; x++) {
      var value = output[y*canvas.width + x];
      var base = (y*canvas.width + x)*4;
      image.data[base + 0] = output[0*componentSize + y*canvas.width + x];
      image.data[base + 1] = output[1*componentSize + y*canvas.width + x];
      image.data[base + 2] = output[2*componentSize + y*canvas.width + x];
      image.data[base + 3] = 255; //the alpha part..
    }
  }
  ctx.putImageData(image, 0, 0);

Since this uses the Canvas element means this won't work in IE8, but for that it might be possible to do something else. For example, you could try getting the converted image data in the right format for a bitmap or some other simple IE compatible format, base64 encoding it then sticking it in as the source of an image element, see http://css-tricks.com/data-uris/ for examples of how to use data urls like this.