-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature request] support for web workers #13
Comments
There are 2 ways to handle this without any changes to the library:
Otherwise, the best way to implement this into the library in my opinion would be to allow |
Okay, so it took me a minute to figure out what you meant -- I was stuck thinking about what all this meant about updating the library itself. But what you are actually saying is that I can myself use So in my case (since it's an Electron app and I know exactly what browser will be used), I added this to my app (for anyone else looking for this): const { readPsd, initializeCanvas } = require('ag-psd');
const base64 = require('base64-js');
const createCanvas = function (width, height) {
console.log('MY CREATE CANVAS');
const canvas = new OffscreenCanvas(width, height);
canvas.width = width;
canvas.height = height;
return canvas;
};
const createCanvasFromData = function (data) {
console.log('MY CREATE CANVAS FROM DATA');
const image = new Image();
image.src = 'data:image/jpeg;base64,' + base64.fromByteArray(data);
const canvas = new OffscreenCanvas(image.width, image.height);
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(image, 0, 0);
return canvas;
}; Then I can use it like this: // in Web Worker
const psd = readPsd(myInput, {
skipLayerImageData: true
}));
const canvas = psd.canvas;
// OffscreenCanvas doesn't have the same image export methods,
// but you can get a buffer, which is frankly the best one
const blob = await canvas.convertToBlob({ type: 'image/jpeg', quality: 0.92 });
const arrayBuffer = await blob.arrayBuffer();
// ArrayBuffer is a transferable!! Send that to the main thread
postMessage({ data: arrayBuffer, width: canvas.width, height: canvas.height }, [arrayBuffer]); // in the main thread (Electron with node integration)
const buffer = Buffer.from(message.data); // in the main thread (in a browser)
const canvas = document.createElement('canvas');
canvas.width = message.width;
canvas.height = message.height;
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(message.width, message.height);
for (let i = 0; i < message.data.length; i++) {
imageData.data[i] = data[i];
}
ctx.putImageData(imageData, 0, 0);
// now you have a canvas with the image in it, do whatever you wanted to do before
const dataUrl = canvas.toDataURL('image/jpeg', 0.92); So it turns out my use case is actually covered already. For browsers that do not have For writing, I am checking out what is being used, and it seems like only |
it's btw I think you can just send offscreen canvas to and from the worker and then draw it directly to regular one when you have it back |
Looks like I made a few mistakes in that code above (that's what I get for not running it first). I'll fix it up once I clean up my implementation a bit, in case anyone wants to use it in the future. Also, unfortunately, you cannot send an OffscreenCanvas. It is not a serializable object, so you get this error:
And in case you interpret that message as just needing to transfer it, it is also not a transferable:
|
Did you mark it when sending over, you should be able to do it according to this: https://developers.google.com/web/updates/2018/08/offscreen-canvas#unblock_main_thread That feature might not be in electron yet though, they just added it to chrome |
Ooh, interesting. I hadn't read this post, I was just going off of what MDN said. It looks like there are a few caveats to using it this way though. I will look into it now. |
@Agamnentzar add test/example of using ag-psd in a webworker |
Closed in 25ee647 |
Rendering PSD files can be quite slow and the current implementation in this module is synchronous and blocking. I'd like to hand off this work to a web worker, but that is currently not possible due to the use of canvas in the module.
I currently have 2 ideas for this:
OffscreenCanvas
where available. Unfortunately, "where available" is only Chromium browsers, so that's certainly not ideal.ImageData
, and then exposed as the public API result so that it can be exported by the user usingtoDataURL()
,toBlob()
, ortoBuffer()
in node. However,ImageData
is just a wrapper aroundUint8ClampedArray
, which can be used throughout the code instead ofImageData
. The API could then be updated to specify whether to provide a canvas or to provide thisUint8ClampedArray
along with the width and height directly. This array can be transferred across the worker and rendered on the other side (either by copying it into a newImageData
object or through various other means likejimp
orsharp
-- this is all up to the user, of course) doing only a small trivial portion in the main thread. I think this is the preferred option, but obviously quite a bit more work.I am happy to help with all this, but I am hoping to get your input before starting.
The text was updated successfully, but these errors were encountered: