Skip to content

WebP decoding support #1258

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

Open
josephrocca opened this issue Sep 27, 2018 · 26 comments
Open

WebP decoding support #1258

josephrocca opened this issue Sep 27, 2018 · 26 comments

Comments

@josephrocca
Copy link

Issue or Feature

I'd like to be able to draw webp images onto the canvas like I can in the browser. Note that I'm not talking about encoding (i.e. toDataURL("image/webp")), since that already has an open issue, and an extension.

Steps to Reproduce

Below is a minimal example that should work, but doesn't (It predictably throws Error: Unsupported image type). You can comment out the webp dataURL and uncomment the PNG url to test that it's working fine with PNGs (no surprise).

(async function() {
  
  console.log("starting");

  let Image = require("canvas").Image;
  let createCanvas = require("canvas").createCanvas;

  let img = await new Promise((resolve, reject) => {
    let img = new Image();
    img.onerror = reject;
    img.onload = resolve;
    img.src = "data:image/webp;base64,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";
    //img.src = "data:image/png;base64,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";
  });

  let canvas = imageToCanvas(img);

  console.log(canvas.toDataURL());

  console.log("finished");
  
  function imageToCanvas(img) {
    let canvas = createCanvas();
    canvas.width = img.width;
    canvas.height = img.height;
    let ctx = canvas.getContext("2d");
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, 0, 0, img.width, img.height);
    return canvas;
  }

})();

Your Environment

  • node-canvas v2.0.0-alpha.16
  • Node v10.9.0 on Ubuntu 16.04
@LinusU
Copy link
Collaborator

LinusU commented Sep 27, 2018

Would absolutely love to see a PR that adds this using a small WASM module 😍

https://medium.com/@kennethrohde/on-the-fly-webp-decoding-using-wasm-and-a-service-worker-33e519d8c21e

https://github.com/kenchris/wasm-webp

@josephrocca
Copy link
Author

Here's a working example using @kenchris's repo as a starting point:
https://gist.github.com/josephrocca/a2ec179ef24462c7c21bd494d98a8988

And here's one with the wasm file inlined: https://gist.github.com/josephrocca/3d26325f1b76b3b10cb5e7c402c6dfd8

I'm new to all this wasm stuff so it may not be the best code, but it's a start! 👍

@LinusU
Copy link
Collaborator

LinusU commented Sep 27, 2018

I might be wrong, but from what I can tell, that code uses the asm.js version instead of the WASM one.

It should probably be one binary webp.wasm file, together with some small code like this:

const fs = require('fs')
const path = require('path')

const code = fs.readFileSync(path.join(__dirname, 'webp.wasm'))
const module = new WebAssembly.Module(code)
const instance = new WebAssembly.Instance(module, {})

exports.decode = function (input) {
  // Allocate memory to hand over the input data to WASM
  const inputPointer = instance.exports.allocate(input.byteLength)
  const targetView = new Uint8Array(instance.exports.memory, inputPointer, input.byteLength)

  // Copy input data into WASM readable memory
  targetView.set(input)

  // Decode input data into
  const metadataPointer = instance.exports.decode(inputPointer, input.byteLength)

  // Free the input data in WASM land
  instance.exports.free(inputPointer)

  // Read returned metadata
  const metadata = new Uint32Array(instance.exports.memory, metadataPointer, 3)
  const [width, height, outputPointer] = metadata

  // Create an empty buffer for the resulting data
  const outputSize = (width * height * 4)
  const output = new Uint8Array(outputSize)

  // Copy decoded data from WASM memory to JS
  output.set(new Uint8Array(instance.exports.memory, outputPointer + 4, outputSize))

  // Free WASM copy of decoded data
  instance.exports.free(outputPointer)

  // Return decoded image as raw data
  return { width, height, data: output }
}

edit: added support for returning width & height

@kenchris
Copy link

kenchris commented Sep 27, 2018

@LinusU
Copy link
Collaborator

LinusU commented Sep 27, 2018

Yeah, I was referring to the Gist made by @josephrocca ☺️

I'm going to try and plug your compiled wasm into my glue code and see if I can get it working 🙌

@josephrocca
Copy link
Author

josephrocca commented Sep 27, 2018

The gists I posted are just rearranged versions of kenchris's code so it works in node. I don't know if the webp.c file would support the standalone stuff, but it might: https://github.com/kripken/emscripten/wiki/WebAssembly-Standalone

In any case, looking forward to testing out webp stuff with node-canvas!

@LinusU
Copy link
Collaborator

LinusU commented Sep 27, 2018

Hmm, the Emscripten shim is 30 KiB 😅 would be nice to not use that.

I didn't know that you had to provide your own malloc and free 🤔

Going to try and write some glue using wasmception and see how it goes 😄

edit: super much work in progress: https://github.com/LinusU/js-webp

@asturur
Copy link
Contributor

asturur commented Oct 3, 2018

but why not the official C lib? wouldn't be more straight forward?

@LinusU
Copy link
Collaborator

LinusU commented Oct 3, 2018

The advantage would be that we could add a small .wasm file which will work in all versions of Node.js on all platforms (x86, arm, etc) without the end user having to compile anything. Seeing how many installation problems we have now, I would love to see this for gif, jpeg, etc. as well, potentially even cairo & pango.

It is the official C lib that I'm compiling btw. ☺️ so it should support all webp files and behave exactly as the normal lib

@asturur
Copy link
Contributor

asturur commented Oct 3, 2018

can you share some compilation detail? i need the webp muxer and encoder!

@kenchris
Copy link

kenchris commented Oct 3, 2018

@zbjornson
Copy link
Collaborator

Once the WASM version is working, I'd love to benchmark it against the C version. I'm happy to make the binding for that.

@kenchris
Copy link

kenchris commented Oct 3, 2018

Remember, wasm will be faster with time. Also future versions will support SIMD and threads, which emscripten then need to build for

@asturur
Copy link
Contributor

asturur commented Oct 3, 2018

Also that would make node canvas browserifiable? i mean transitioning all C to wasm. ( cairo included )

@zbjornson
Copy link
Collaborator

@asturur I suppose, but it seems redundant given that node-canvas exists to emulate the Canvas API that's already in browsers.

@asturur
Copy link
Contributor

asturur commented Oct 3, 2018

well i would never do that. But for people really caring about the same output OR just because till now to people that asked me how to browserify canvas i said that it could not be done.

I was just exploring.

@LinusU
Copy link
Collaborator

LinusU commented Oct 12, 2018

Okay, a status update, I'm soooo close to getting it working. It can decode some webp files currently, but I'm running into problems with YUV-images. To be honest I'm not exactly sure where the problem lies, but I've filed a bug report on libwebp here:

https://bugs.chromium.org/p/webp/issues/detail?id=403

The current code can be found here:

https://github.com/LinusU/cwasm-webp

I have published the first version of it on npm 🎉

Currently, only Node.js is supported, but browser support should be easy to add. Just want to research how to best do the loading. Also, only decoding is supported, but it should be trivial to add encoding as well.

I would absolutely love some help in tracking down the memory out of bounds issue ❤️

@LinusU
Copy link
Collaborator

LinusU commented Nov 25, 2019

Update! During the weekend I wrote a Node.js compatible Image class with support for png, gif, bmp, jpeg & webp!

It uses WebAssembly to decode all the image formats 🎉

@canvas/image - https://github.com/node-gfx/image

Should be trivial to start using that Image class here, started trying it out but ran out of time, hope to look at it soon again :)

@chearon
Copy link
Collaborator

chearon commented Nov 25, 2019

Amazing work!! Looks like you were able to get different C libs compiled with the latest LLVM's WASM support?

I've actually been experimenting with this too. In an unrelated project, I'm working on a JS implementation of (parts of) Pango. It also relies on some WebAssembly-compiled C libraries. If we were to use it in node-canvas that would be another native dependency gone, plus it would get us perfect font matching.

It would be interesting to experiment with a fork that only uses Cairo/pixman. I'm going to bet though that performance will suffer enough that we might still need to maintain the native version somehow 😑

@LinusU
Copy link
Collaborator

LinusU commented Nov 26, 2019

Looks like you were able to get different C libs compiled with the latest LLVM's WASM support?

Yeah 🙌 the WASI SDK made it really easy to get going!

I was thinking of trying out to do the same with Cairo and see if I could get a nice @cwasm/cairo with a somewhat nice, but still low level, api

I don't know if there is a way to link a bunch of different wasm files together into one file, it might be expensive to go thru JavaScript every time the different part needs to talk to each other (on the other hand, maybe it doesn't matter that much, since it will probably only be when loading in new images 🤔)

It's going to be very interesting to see how the performance will be. Even if it's not stellar, it would be cool if we could have the natively compiled parts as an optionalDependency so that npm will try to install it, but if it fails everything will still work, just not as fast.

Also, potentially it's faster to call between JavaScript and WASM then JavaScript and the C++ functions. I don't have any data to back this up 😁, but I think that JS and WASM can be JIT compiled into the same VM, and then the calls are very cheap. This could potentially be a win when calling into Cairo which is mostly calling functions with a few integers and it does a lot of pixel manipulation internally. Anyhow, the only way to find out is to try 😄

@Jytesh
Copy link

Jytesh commented Nov 30, 2020

Is this issue fixed, how do I import remote webp images from urls to node canvas to use the ctx.drawImage(webp_image) function

@Xetera
Copy link

Xetera commented Apr 15, 2021

The @canvas/image package doesn't work for me as the libraries I'm using, namely face-api.js have their own image instanceof Image prototype checks that fail when passing in the custom Image class over the canvas image. It's very frustrating to have spent all this time converting images to webp only to find that I probably need to convert them back to jpg before I can do anything with them in node.

@LinusU
Copy link
Collaborator

LinusU commented Apr 15, 2021

@Xetera if they are doing instanceof Image than it probably wouldn't work with the Image from node-canvas either? 🤔 It seems like that library is intended to be run inside a browser?

@Xetera
Copy link

Xetera commented Apr 15, 2021

After playing around with it for a bit I realized face-api.js has a monkeyPatch function that allows me to pass a custom Image implementation but node-canvas still doesn't seem to like that very much. It fails with TypeError: Image or Canvas expected. I feel like this has something to do with the check in

if (Nan::New(Image::constructor)->HasInstance(obj)) { ... }

Where node-canvas internally relies on its own definition of Image. This behavior is reproducible with just node-canvas and no external libraries using

const imageResponse = await axios.get(image.rawUrl, {
  responseType: "arraybuffer",
});
const ca = canvas.createCanvas(500, 500);
const ctx = ca.getContext("2d");
const imageElem = await imageFromBuffer(imageResponse.data);
ctx.drawImage(imageElem, 0, 0, image.width, image.height);

I wanted to keep the conversation related to the solution here but I'm happy with moving over to the @canvas/image repo if you like

EDIT: I tried patching the node-canvas instance check to see if that's the issue but I didn't have much luck. I either get a black canvas output or runtime errors.

EDIT2: I was able to solve my issue by combining @canvas/image with @tensorflow/tfjs-node without canvas although I don't know how useful that solution might be for others. Check out the linked issue for more context if relevant.

@ringcrl
Copy link

ringcrl commented Jul 18, 2022

After playing around with it for a bit I realized face-api.js has a monkeyPatch function that allows me to pass a custom Image implementation but node-canvas still doesn't seem to like that very much. It fails with TypeError: Image or Canvas expected. I feel like this has something to do with the check in

if (Nan::New(Image::constructor)->HasInstance(obj)) { ... }

Where node-canvas internally relies on its own definition of Image. This behavior is reproducible with just node-canvas and no external libraries using

const imageResponse = await axios.get(image.rawUrl, {
  responseType: "arraybuffer",
});
const ca = canvas.createCanvas(500, 500);
const ctx = ca.getContext("2d");
const imageElem = await imageFromBuffer(imageResponse.data);
ctx.drawImage(imageElem, 0, 0, image.width, image.height);

I wanted to keep the conversation related to the solution here but I'm happy with moving over to the @canvas/image repo if you like

EDIT: I tried patching the node-canvas instance check to see if that's the issue but I didn't have much luck. I either get a black canvas output or runtime errors.

EDIT2: I was able to solve my issue by combining @canvas/image with @tensorflow/tfjs-node without canvas although I don't know how useful that solution might be for others. Check out the linked issue for more context if relevant.

The same issue, I can convert webp to png before I use it on node-canvas, It's an extraordinary and inefficient way...

@LegendaryEmoji
Copy link

For those who want to decode WebP images so they can use them in their canvas. Here you go:

const webp = require("@cwasm/webp");

const source = fs.readFileSync("./image.webp");

// Decoding the WebP file and putting it on the canvas.

const image = webp.decode(source);
const imageData = ctx.createImageData(image.width, image.height);
imageData.data.set(image.data);

ctx.putImageData(imageData, 0, 0);

// Converting the canvas to buffer and saving it.

writeFileSync("./result.png", canvas.toBuffer());

This is a synchronous solution (Bundlephobia: @cwasm/webp).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants