1

I have UInt8array, width, height of png image. I tried to save it like this

const screenshot = new TextDecoder('utf-8').decode(await frame.exportAsync()) // figma.com/plugin-docs/api/properties/nodes-exportasync 
// passing screenshot as string over network
const uint8array = new TextEncoder('utf-8').encode(screenshot);
const data = Buffer.from(uint8array);
fs.writeFileSync(`${fileName}.png`, data, 'binary');

but this code obviously does not consider width and height.

How can I save it as png in Node.js properly?

6
  • what is screenshot? Commented Nov 21, 2019 at 13:21
  • screenshot is new TextDecoder('utf-8').decode(await frame.exportAsync()) , where exportAsync is figma.com/plugin-docs/api/properties/nodes-exportasync Commented Nov 21, 2019 at 13:24
  • 1
    So what is frame.exportAsync()? Also I dont think using UTF8 strings to transfer binary data is always safe. Commented Nov 21, 2019 at 13:43
  • frame.exportAsync() returns UInt8array. Probably you right. But I also looking for a way to save png in node from UInt8array anyway. Commented Nov 21, 2019 at 13:49
  • 1
    Never use utf-8 to transfer binary. I don't even know how you'd get that to work. utf-8 is a text encoding, not meant for binary. Use base64 if you need an ascii representation of binary data. Commented Nov 21, 2019 at 14:20

1 Answer 1

1

As @Lux mentioned using UTF8 strings to transfer binary data is not safe, so I used conversion to base64

this works

var base64 = btoa(new Uint8Array(await frame.exportAsync()).reduce((data, byte) => data + String.fromCharCode(byte), ''),
);

// passing screenshot as string over network
function urlBase64ToUint8Array(base64String: string) {
    var padding = '='.repeat((4 - (base64String.length % 4)) % 4);
    var base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');

    var rawData = atob(base64);
    var outputArray = new Uint8Array(rawData.length);

    for (var i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}

const uint8array = urlBase64ToUint8Array(screenshot);
const data = Buffer.from(uint8array);
fs.writeFileSync(`${fileName}.png`, data, 'binary');

no need for width and height also as it is encoded in buffer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.