0

I'm working in an Javascript application that receives a base64 array. This array encodes a 16 bits per pixel raw image.

Thus, I would like to do some calculations in it. For this, I need to unpack this Base64 string in a Uint16Array, so I can iterate over pixels and perform the required calculations.

What are my options for doing that?

Fernando
  • 1,477
  • 2
  • 14
  • 33

2 Answers2

1

After some hours looking for a solution, I found a way for doing this:

function getData()
{
    fetch("test_data/img_base64.txt")
    .then(res => res.text())
    .then((out) => {
        rawString = window.atob(out);
        uint8Array = new Uint8Array(rawString.length);
        for(var i = 0; i < rawString.length; i++)
        {
            uint8Array[i] = rawString.charCodeAt(i);
        }
        uint16Array = new Uint16Array(uint8Array.buffer);
        console.log(uint16Array);
    })
    .catch(err => { throw err });
}

First I fetch my base64 string from a file. Then using window.atob it is converted to a JavaScript string. After this, I need to fill a Uint8Array with every byte loaded from the string. Finally, I had to convert this Uint8Array, into the final Uint16Array.

That was tough to achieve exactly what I was looking. But I have found it.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Fernando
  • 1,477
  • 2
  • 14
  • 33
  • Thank you. I spent litteraly days on it. You saved my week-end ! My scenario was converting image into webp on client, converting it into base64, compressing it, transmitting it over network, decompress it then reading it on a Cloudflare Worker width res.text(), and after that I had to read width and height of the webp in a Uint16 fashion. It was a nightmare but thanks to your code that converts Uint8 to Uint16, It works :) – Denis TRUFFAUT Nov 07 '20 at 12:02
0

You can use this function that converts a base64 string into a binary Uint16 Array

var BASE64_MARKER = ';base64,';

function convertDataURIToBinary(dataURI) {
  var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
  var base64 = dataURI.substring(base64Index);
  var raw = window.atob(base64);
  var rawLength = raw.length;
  var array = new Uint16Array(new ArrayBuffer(rawLength));

  for(i = 0; i < rawLength; i++) {
    array[i] = raw.charCodeAt(i);
  }
  return array;
}

If you're targeting Firefox and feeling adventurous you can shorten the function down to this:

var BASE64_MARKER = ';base64,';

function convertDataURIToBinaryFF(dataURI) {
  var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
  var raw = window.atob(dataURI.substring(base64Index));
  return Uint8Array.from(Array.prototype.map.call(raw, function(x) {
    return x.charCodeAt(0);
  }));
};
Alexandre Elshobokshy
  • 10,720
  • 6
  • 27
  • 57