processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.12k stars 3.22k forks source link

Bridges between modern JavaScript image manipulation and p5.Image (createImageFromBitmap) #5641

Open juliendorra opened 2 years ago

juliendorra commented 2 years ago

Increasing Access

unsure

Most appropriate sub-area of p5.js?

Feature request details

The ImageBitmap interface (https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap) is a more modern way to use images on canvas than manipulating DOM images. It is also usable in web workers.

The implementation is still quite unequal in browsers, with some browsers not supporting some options (chrome support everything) https://caniuse.com/createimagebitmap and https://developer.mozilla.org/en-US/docs/Web/API/createImageBitmap#browser_compatibility

But this newer interface makes it very easy to turn a downloaded blob or a canvas into a ImageBitmap, and it's also easy to draw them on a canvas.

There's no way that I could find in the current p5.js library to turn a ImageBitmap (or a blob for that matter) into ap5.Image object.

For a generative template that load and prepares images from a web source for generative artist to then use and remix, I needed to fetch the remote images and store them as ImageBitmap (so it can be natively used without p5 by an artist).

But I also needed to store them as p5.Image in the case p5 library was loaded by the generative artist using the template.

Of course I wanted to avoid fetching images twice, once with Fetch => Blob => ImageBitmap , and once with LoadImage which includes a Fetch. I also wanted to avoid having to have two completely different path for fetching from the web, depending on the library used by artists.

I stripped down loadImage() code to a simple function that just set the p5.Image, so I can pass it an ImageBitmap and get a p5.Image in return.

function createImageFromBitmap(bitmap) {

    const pImg = new p5.Image(1, 1, this);

    pImg.width = pImg.canvas.width = bitmap.width;
    pImg.height = pImg.canvas.height = bitmap.height;

    // Draw the image into the backing canvas of the p5.Image
    pImg.drawingContext.drawImage(bitmap, 0, 0);
    pImg.modified = true;

    return pImg;
}

Using this small function, I can have one single fetch path, retrieving the images, and then chose to store them as ImageBitmaps or p5.Images or both.

(It's missing the standard argument verification and error handling of p5 functions. of course.)

I think it would be interesting for p5.js to have better bridges with this relatively recent image manipulation interface in JavaScript, with ways to convert to and from p5.image objects.

welcome[bot] commented 2 years ago

Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.

limzykenneth commented 2 years ago

From what I can see on MDN, Safari doesn't fully support createImageBitmap() yet?

sandstrom commented 2 years ago

For reference, here is an open issues in the Webkit (Safari) bug tracker:

Also unclear if the options argument is supported by Webkit.