Automattic / node-canvas

Node canvas is a Cairo backed Canvas implementation for NodeJS.
10.12k stars 1.17k forks source link

Can't load svg with base64 image inside #1607

Open thobn24h opened 4 years ago

thobn24h commented 4 years ago

Issue or Feature

When load svg ( with base64 image inside ) file using function loadImage I get exception: GdkPixbuf-CRITICAL **: 13:03:49.842: gdk_pixbuf_get_width: assertion 'GDK_IS_PIXBUF (pixbuf)' failed

Steps to Reproduce

  1. Run following code to load svg file:
const fs = require('fs');
const { createCanvas, loadImage } = require('canvas');

async function nodeCanvasTest() {
  console.log('starting...');
  const canvas = createCanvas(400, 200);
  const ctx = canvas.getContext('2d');

  image = await loadImage('./input.svg');

  ctx.drawImage(image, 0, 0);
  var stream = canvas.createPNGStream();
  stream.pipe(fs.createWriteStream('output.png'));
  console.log('completed');
}

nodeCanvasTest();

Here is svg file:

input.svg.zip

  1. In the terminal run command: node server.js

  2. Get Error: GdkPixbuf-CRITICAL **: 13:03:49.842: gdk_pixbuf_get_width: assertion 'GDK_IS_PIXBUF (pixbuf)' failed

error_load_svg_with_base64

Your Environment

OS: MacOS Catalina 10.15.5 Node: v10.16.0 NPM: 6.9.2 Canvas: canvas@2.6.1

Expected:

SVG file is loaded & rendered normally.

jjyoh commented 3 years ago

Any updates on this issue?

nickgraz commented 2 years ago

According to the docs this is how you're supposed to load an SVG:

const img = new Image()
img.onload = () => ctx.drawImage(img, 0, 0)
img.onerror = err => { throw err }
img.src = './example.svg'

Not sure if it will work for you or not but might be worth a try! 😅

LinusU commented 2 years ago

The example posted in the original post looks good, loadImage is the recommended way and it uses img.onload & img.src under the hood.

A pull request to fix this would be very welcome if anyone wants to work on this!

danieltroger commented 2 years ago

Suffering from a similar/the same issue. Trying to load an SVG that contains a base64 image and the SVG just renders without the image.

danieltroger commented 2 years ago

I found a workaround.

For me this made the image load:

  1. Use a <svg tag that has an id
  2. Use <svg tag that has xmlns:xlink="http://www.w3.org/1999/xlink"

So in summary the minimum working svg tag looks like this rn:

<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  viewBox="0 0 1000 1612"
  id="svg8">
  1. On the image tag, replace <image href="data: with <image xlink:href="
  2. This is the weirdest thing ever: add a newline every 76th character in the base64-url, don't ask me why
  3. Wrap the <image tag in a <g> (not sure if this actually helped but now it works and I also did that change)
Byteschmiede commented 1 year ago

Does anyone know how to fix that?

I've tried your workaroung but it didn't work here

gguy0406 commented 11 months ago

I have similar issue on Linux. It fails with no exception, the rendered image has everything in svg file without the image tag. On the other hand, it works perfectly on my Mac.