Since ImageFill takes a data: URI with base-64 encoded data, and what’s gotten from the web with a fetch is usually binary data, it’d be great if Xd provided utilities to convert binary to and from base-64.
Thanks for the request. For now, please use a utility function. Example: https://github.com/AdobeXD/plugin-samples/blob/master/how-to-make-network-requests/main.js
Thought I’d let you know (a bit later!) that using the npm module base64-arraybuffer works great.
The code
import base64 from 'base64-arraybuffer'
const binary = await fetchBinary(uri)
const imgBase64 = base64.encode(binary)
const imgFill = new ImageFill('data:image/png;base64,' + imgBase64)
seems to work great (using the fetchBinary utility from the plugin-samples). Not bad! 3 lines of code to fetch an image and turn it into an ImageFill.
But here’s a strong vote for a built-in fast (C++) base64 implementation that handles both string and arraybuffer encoding/decoding.
(You probably already have much of that built-in, handling the “data:” URIs, so you could expose it to JS.)
Hey crypland. That way of importing the base64-arraybuffer did not work for me. Can you give a little more detail on how you did it? Thanks
I’m using the ES6 style import, but
const base64 = require('base64-arraybuffer')
or maybe
const base64 = require('base64-arraybuffer').default
should work as an alternative.
Ok thank you I will try! Can you post the imgBase64 output?
Not sure what you mean.
Found this on Git:
It is working without any outer plugins.
These alternatives don’t work for me. I still need synchronous image data to base 64 method.
const bitmapData = sceneNode.toBitmapData();
const base64 = bitmapData.encode("png");
console.log(base64); // "data:image/png;base64,..."
function strToUTF8Base64(str) {
function decodeSurrogatePair(hi, lo) {
var resultChar = 0x010000;
resultChar += lo - 0xdc00;
resultChar += (hi - 0xd800) << 10;
return resultChar;
}
var bytes = [0, 0, 0];
var byteIndex = 0;
var result = [];
function output(s) {
result.push(s);
}
function emitBase64() {
var digits =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789+/";
function toDigit(value) {
return digits[value];
}
// --Byte 0-- --Byte 1-- --Byte 2--
// 1111 1122 2222 3333 3344 4444
var d1 = toDigit(bytes[0] >> 2);
var d2 = toDigit(((bytes[0] & 0x03) << 4) | (bytes[1] >> 4));
var d3 = toDigit(((bytes[1] & 0x0f) << 2) | (bytes[2] >> 6));
var d4 = toDigit(bytes[2] & 0x3f);
if (byteIndex === 1) {
output(d1 + d2 + "==");
} else if (byteIndex === 2) {
output(d1 + d2 + d3 + "=");
} else {
output(d1 + d2 + d3 + d4);
}
}
function emit(chr) {
bytes[byteIndex++] = chr;
if (byteIndex == 3) {
emitBase64();
bytes[0] = 0;
bytes[1] = 0;
bytes[2] = 0;
byteIndex = 0;
}
}
function emitLast() {
if (byteIndex > 0) {
emitBase64();
}
}
// Converts the string to UTF8:
var i, chr;
var hi, lo;
for (i = 0; i < str.length; i++) {
chr = str.charCodeAt(i);
// Test and decode surrogate pairs in the string
if (chr >= 0xd800 && chr <= 0xdbff) {
hi = chr;
lo = str.charCodeAt(i + 1);
if (lo >= 0xdc00 && lo <= 0xdfff) {
chr = decodeSurrogatePair(hi, lo);
i++;
}
}
// Encode the character as UTF-8.
if (chr < 0x80) {
emit(chr);
} else if (chr < 0x0800) {
emit((chr >> 6) | 0xc0);
emit(((chr >> 0) & 0x3f) | 0x80);
} else if (chr < 0x10000) {
emit((chr >> 12) | 0xe0);
emit(((chr >> 6) & 0x3f) | 0x80);
emit(((chr >> 0) & 0x3f) | 0x80);
} else if (chr < 0x110000) {
emit((chr >> 18) | 0xf0);
emit(((chr >> 12) & 0x3f) | 0x80);
emit(((chr >> 6) & 0x3f) | 0x80);
emit(((chr >> 0) & 0x3f) | 0x80);
}
}
emitLast();
return result.join("");
}
Taken from this site https://stackoverflow.com/questions/246801/how-can-you-encode-a-string-to-base64-in-javascript
There’s also this: