From b1e3ee4eec7b7180aa3dea50eecef78c4801e201 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 11 Jun 2019 14:14:31 +0100 Subject: [PATCH] Added base64 to ArrayBuffer and ArrayBuffer to base64 --- CHANGELOG.md | 2 + src/utils/base64/ArrayBufferToBase64.js | 52 +++++++++++++++++++ src/utils/base64/Base64ToArrayBuffer.js | 69 +++++++++++++++++++++++++ src/utils/base64/index.js | 16 ++++++ src/utils/index.js | 1 + 5 files changed, 140 insertions(+) create mode 100644 src/utils/base64/ArrayBufferToBase64.js create mode 100644 src/utils/base64/Base64ToArrayBuffer.js create mode 100644 src/utils/base64/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a350ea01..f8da2c645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,8 @@ The following changes took place in the Pointer class: * You can now create a desynchronized 2D or WebGL canvas by setting the Game Config property `desynchronized` to `true` (the default is `false`). For more details about what this means see https://developers.google.com/web/updates/2019/05/desynchronized. * The CanvasRenderer can now use the `transparent` Game Config property in order to tell the browser an opaque background is in use, leading to faster rendering in a 2D context. * `GameObject.scale` is a new property, that exists as part of the Transform component, that allows you to set the horizontal and vertical scale of a Game Object via a setter, rather than using the `setScale` method. This is handy for uniformly scaling objects via tweens, for example. +* `Base64ToArrayBuffer` is a new utility function that will convert a base64 string into an ArrayBuffer. It works with plain base64 strings, or those with data uri headers attached to them. The resulting ArrayBuffer can be fed to any suitable function that may need it, such as audio decoding. +* `ArrayBufferToBase64` is a new utility function that converts an ArrayBuffer into a base64 string. You can also optionally included a media type, such as `image/jpeg` which will result in a data uri being returned instead of a plain base64 string. ### Updates diff --git a/src/utils/base64/ArrayBufferToBase64.js b/src/utils/base64/ArrayBufferToBase64.js new file mode 100644 index 000000000..8fc3e3466 --- /dev/null +++ b/src/utils/base64/ArrayBufferToBase64.js @@ -0,0 +1,52 @@ +/** + * @author Niklas von Hertzen (https://github.com/niklasvh/base64-arraybuffer) + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +/** + * Converts an ArrayBuffer into a base64 string. + * + * The resulting string can optionally be a data uri if the `mediaType` argument is provided. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs for more details. + * + * @function Phaser.Utils.Base64.ArrayBufferToBase64 + * @since 3.18.0 + * + * @param {ArrayBuffer} arrayBuffer - The Array Buffer to encode. + * @param {string} [mediaType] - An optional media type, i.e. `audio/ogg` or `image/jpeg`. If included the resulting string will be a data URI. + * + * @return {string} The base64 encoded Array Buffer. + */ +var ArrayBufferToBase64 = function (arrayBuffer, mediaType) +{ + var bytes = new Uint8Array(arrayBuffer); + var len = bytes.length; + + var base64 = (mediaType) ? 'data:' + mediaType + ';base64,' : ''; + + for (var i = 0; i < len; i += 3) + { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + + if ((len % 3) === 2) + { + base64 = base64.substring(0, base64.length - 1) + '='; + } + else if (len % 3 === 1) + { + base64 = base64.substring(0, base64.length - 2) + '=='; + } + + return base64; +}; + +module.exports = ArrayBufferToBase64; diff --git a/src/utils/base64/Base64ToArrayBuffer.js b/src/utils/base64/Base64ToArrayBuffer.js new file mode 100644 index 000000000..85ade9635 --- /dev/null +++ b/src/utils/base64/Base64ToArrayBuffer.js @@ -0,0 +1,69 @@ +/** + * @author Niklas von Hertzen (https://github.com/niklasvh/base64-arraybuffer) + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +// Use a lookup table to find the index. +var lookup = new Uint8Array(256); + +for (var i = 0; i < chars.length; i++) +{ + lookup[chars.charCodeAt(i)] = i; +} + +/** + * Converts a base64 string, either with or without a data uri, into an Array Buffer. + * + * @function Phaser.Utils.Base64.Base64ToArrayBuffer + * @since 3.18.0 + * + * @param {string} base64 - The base64 string to be decoded. Can optionally contain a data URI header, which will be stripped out prior to decoding. + * + * @return {ArrayBuffer} An ArrayBuffer decoded from the base64 data. + */ +var Base64ToArrayBuffer = function (base64) +{ + // Is it a data uri? if so, strip the header away + base64 = base64.substr(base64.indexOf(',') + 1); + + var len = base64.length; + var bufferLength = len * 0.75; + var p = 0; + var encoded1; + var encoded2; + var encoded3; + var encoded4; + + if (base64[len - 1] === '=') + { + bufferLength--; + + if (base64[len - 2] === '=') + { + bufferLength--; + } + } + + var arrayBuffer = new ArrayBuffer(bufferLength); + var bytes = new Uint8Array(arrayBuffer); + + for (var i = 0; i < len; i += 4) + { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + + return arrayBuffer; +}; + +module.exports = Base64ToArrayBuffer; diff --git a/src/utils/base64/index.js b/src/utils/base64/index.js new file mode 100644 index 000000000..51edeed07 --- /dev/null +++ b/src/utils/base64/index.js @@ -0,0 +1,16 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.Base64 + */ + +module.exports = { + + ArrayBufferToBase64: require('./ArrayBufferToBase64'), + Base64ToArrayBuffer: require('./Base64ToArrayBuffer') + +}; diff --git a/src/utils/index.js b/src/utils/index.js index 3af3db371..cda9f7c27 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -11,6 +11,7 @@ module.exports = { Array: require('./array/'), + Base64: require('./base64/'), Objects: require('./object/'), String: require('./string/')