5

Since browsers know how to handle JPG files, is there a way to give them the actual binary data of a JPG file dynamically and allowing them to decode it?

I can't supply the file as a normal image.src="path.jpg" because the data is originally a part of another file which is parsed in JS.

In addition, I have weird JPG files that store alpha, and so libraries like https://github.com/notmasteryet/jpgjs can't handle them.

user2503048
  • 1,021
  • 1
  • 10
  • 22
  • There's no way to make the browser read binary code, closest you'll get is probably base64, which modern browsers will read. – adeneo Apr 26 '14 at 11:07
  • To get the base64 string I'll need to decode the JPG first, which goes back to the start. – user2503048 Apr 26 '14 at 11:11
  • What does "weird JPG files that store alpha" mean? Is this really 2 image files: jpg + greyscale image representing the alpha channel? If yes, then (1) separate the 2 images, (2) decode them with a library like your jpgjs, (3) create 2 javascript Image objects from the decoded jpgs, (4) create 2 canvases and drawImage both images to canvas, (5) use context.getImageData to combine the rgb channels from the color .jpg with the alpha mask from the grayscale .jpg, (6) use context.putImageData to write the combined pixel data to canvas, (7) use canvas.toDataURL to create base64 image data. – markE Apr 26 '14 at 11:56
  • I edited the above jpgjs a little, and it seems like the colors are simply stored as BGRA instead of YCbCr. If I avoid the later check (that sees the format has 4 components, which it doesn't like), I can get the values just fine. I'd still prefer the browser to do the decoding, since it's better at it, but whatever. Thanks for the comments. – user2503048 Apr 26 '14 at 12:06

1 Answers1

12

You can use Blobs to create objects from binary data that you later pass as an url for image decoding. Assuming you have the binary data stored as typed array you could do something like this:

var blob = new Blob([myTypedArray], {type: 'application/octet-binary'});
var url = URL.createObjectURL(blob);

Now you can pass that url as a source for image:

var img = new Image;
img.onload = function() {
    URL.revokeObjectURL(url);
    ...
};
img.src = url;

Note that you still have make sure that the data you pass in is valid image format that the browser can handle.

  • That looks brilliant, but sadly it drops the alpha channel (all of it becomes opaque) :( – user2503048 Apr 26 '14 at 14:32
  • The pixels where the alpha wasn't opaque are changed, so I assume the browser pre-multiplies the alpha channel and then removes it. Too bad, because this is brilliant and fast (and quite smaller than a 30KB+ decoder). – user2503048 Apr 26 '14 at 15:27
  • 1
    @user2503048 It seems JPG spec doesn't officially support alpha, right? Therefore I wouldn't be surprised that this answer doesn't work with alpha channels. PNG files with alpha channels would work using this technique though, because PNG supports alpha. – trusktr May 05 '20 at 18:55
  • JPEG doesn't support the alpha channel. – Neetigya Chahar Jan 08 '21 at 17:41