Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Trying to get canvas image data via toDataURL #246

Open
j9a12c20k opened this issue Feb 25, 2023 · 1 comment
Open

Trying to get canvas image data via toDataURL #246

j9a12c20k opened this issue Feb 25, 2023 · 1 comment

Comments

@j9a12c20k
Copy link

j9a12c20k commented Feb 25, 2023

Hello,

I am trying to get canvas image data in JSDOM. I wrapped headless-gl functions to jsdom to add web gl functionality, however headless-gl does not seem to have canvas.toDataURL() option. Is there a way to add this functionality?

Thanks

import gl from 'gl';

import jsdom from "jsdom";

const JSDOM = jsdom.JSDOM;
const dom = new JSDOM(`<html><head></head><body></body></html>`, {
  url: "https://example.com",
  beforeParse(window) {
    window = beforeParse(window);
  }
});

dom.window.eval(`

const webgl = window.document.createElement('canvas');

// window.WebGLRenderingContext.prototype.getParameter.name
// window.WebGLRenderingContext.prototype.getParameter
const g = webgl.getContext("webgl")
console.log(g.canvas.toDataURL());
//^ need to get the canvas to get the image data (returns undefined)
`)


function beforeParse() {
  const orig_getContext = window.HTMLCanvasElement.prototype.getContext
  window.HTMLCanvasElement.prototype.getContext = function () {
    if (arguments[0] === 'webgl') {
        const ctx = gl.create(1, 1, arguments[1])
        ctx.resize = ctx.getExtension('STACKGL_resize_drawingbuffer').resize
        return ctx
    } else {
        return orig_getContext.apply(this, arguments)
    }
}
}
@dhritzkiv
Copy link
Member

headless-gl itself does not provide a canvas element or image output functionality.

However, if you have a way to add toDataURL a method to HTMLCanvasElement, you can implement it yourself with something like:

// `width` and `height` are the dimensions of your canvas
const pixels = new Uint8Array(4 * width * height);

// `gl` is the gl context of this context.
// we pass the `pixels` array as the last argument 
// RGBA format is used 
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

// get the data buffer from the pixels array
const buffer = Buffer.from(pixels.buffer);

// pass this bitmap data to a method that can encode it as a PNG / JPEG. I use `sharp`, but there are others, such as `jpeg-js`, `pngjs3`, etc.
// ...

When creating your gl context, make sure to pass preserveDrawingBuffer: true to the constructor options. You may also want, antialias: true and alpha: true

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants