Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Encode an ArrayBuffer as a base64 string

View gist:958841
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
// Converts an ArrayBuffer directly to base64, without any intermediate 'convert to string then
// use window.btoa' step. According to my tests, this appears to be a faster approach:
// http://jsperf.com/encoding-xhr-image-data/5
 
function base64ArrayBuffer(arrayBuffer) {
var base64 = ''
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
 
var bytes = new Uint8Array(arrayBuffer)
var byteLength = bytes.byteLength
var byteRemainder = byteLength % 3
var mainLength = byteLength - byteRemainder
 
var a, b, c, d
var chunk
 
// Main loop deals with bytes in chunks of 3
for (var i = 0; i < mainLength; i = i + 3) {
// Combine the three bytes into a single integer
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
 
// Use bitmasks to extract 6-bit segments from the triplet
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
d = chunk & 63 // 63 = 2^6 - 1
 
// Convert the raw binary segments to the appropriate ASCII encoding
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
}
 
// Deal with the remaining bytes and padding
if (byteRemainder == 1) {
chunk = bytes[mainLength]
 
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
 
// Set the 4 least significant bits to zero
b = (chunk & 3) << 4 // 3 = 2^2 - 1
 
base64 += encodings[a] + encodings[b] + '=='
} else if (byteRemainder == 2) {
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
 
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
 
// Set the 2 least significant bits to zero
c = (chunk & 15) << 2 // 15 = 2^4 - 1
 
base64 += encodings[a] + encodings[b] + encodings[c] + '='
}
return base64
}

I kind of need the reverse. A base64 encoded utf8 string to an ArrayBuffer. How can I do that?

Owner

I guess you would need to write this function sort of in reverse. So iterate over each 4 characters, converting them to three bytes which you append to the ArrayBuffer, and then with special handling for the padding at the end. I don't have code for that though :)

As you just saved my life, I just wanted to say THANK YOU

kinda late, but here is the reverse

And CryptoJS has a method to transform to a WordArray as well: CryptoJS.enc.Base64.parse

@joscha, the "reverse" (see comment https://gist.github.com/jonleighton/958841/#comment-733469) seems to be 3x slower than atob in my tests.

This is a pretty nifty method! Is there any chance you might add a license to it? I would really like to include it in a project of mine but am not allowed to do so without a proper license ;-)

It's amazing, I'm working on >10 000 000 arrays (audio files) and performance was serious bottleneck, thanks

This function is flaw. Everything turns out as "AAAAAAAAA" for small number like [0.000354254885, -0.521365849254, 0.002453687924].

gfranko commented

Thank you very much, works like a charm! Would you mind adding a license to this?

Thank you for this useful script. Which license is this? GPL? BSD?

You made my day.

You are my hero!

Boom, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.