Search code examples
htmlnode.jsimagenodesgraphviz

NodeJS Graphviz - trying to add image as label throws Error code 1


I am attempting to use an image as a node in Graphviz. I am using the npm grapghviz project to do this. However, despite numerous tutorials stating that you can do it via the menthods I have outlined below, the .output function just throws an error, with simply the number 1 and no message.

I have attempted the following:

  const imagePath = path.join(__dirname, "myImage.png");
  g.addNode(node.Name, {
    shape: "record",
    label: `<f0> | <img src="${myImage}" width="100" height="100"/> | <f1>`, // Image in the record node
    style: "filled",
    fillcolor: "#FF5733", // Background color
    color: "#C70039",     // Border color
    penwidth: 2           // Border width
})

Using html like label with a table

  g.addNode(node.Name, {
    label: `<TABLE CELLSPACING="2" CELLPADDING="2" BORDER="0"><TR><TD><IMG SRC="${imagePath}"/></TD></TR></TABLE>>`,
    shape: "plaintext",
  });

This works, but looks wonky without a table. Long text makes the node HUGE and the image small.

  g.addNode(node.Name, {
    label: "A Service",
    shape: "square",
    image: imagePath
  });

Essentially, i'm trying to make nodes that look something like this.. but can't do it as it always throws Error 1 when outputting to either png or svg.

Graphviz Node Examples


Solution

    • According to that answer, record do not handle images.

    • HTML-Like label definitely works with cli graphviz app.
      Example script in file.dot:

      graph G {
        "img" [label=<<TABLE><TR><TD><IMG SRC="image.png"/></TD></TR></TABLE>>]
      }
      

      Command: dot -Tpng file.dot > file.png
      Result:
      show image in node, made with Graphviz
      But doesn't work with graphviz@0.0.9 NPM package, even using parsing of the working file above with

      const util = require('util');
      const graphviz = require('graphviz');
      graphviz.parse("file.dot", function(graph){ graph.output("png","file.png") }, ...
      

      so I'm guessing it's a bug in the package.
      P.S. There is an Issue about this and proposed solution there is to use such code with ! sign:

      const n1 = g.addNode('APIGW', {
        label: '!<B>API</B> <i>Gateway</i>',
      });
      
    • It only remains to work with the image attribute...

    So, in order to position the picture on the left side, as in your example, we will need to change the shape of the node to a rectangle and align the picture to the left side.

    To align the image we need the following node attributes:

    And there will be problems with imagepos, because when using this attribute in the code, the package will produce an error:

    DEBUG: Warning : Invalid attribut `imagepos' for a node
    D:\yourproject\node_modules\graphviz\lib\deps\attributs.js:192
      return(quotedTypes.indexOf(attrs[data].type) !== -1);
                                             ^
    
    TypeError: Cannot read property 'type' of undefined
        at mustBeQuoted (D:\yourproject\node_modules\graphviz\lib\deps\attributs.js:192:42)
        ...
    

    It does not understand this attribute (as mentioned in Issues on the package repo on GitHub).

    Fortunately, you can easily fixing this bug!
    To do this, edit the file \node_modules\graphviz\lib\deps\attributs.js by adding the following line:

    var attrs = {
      ...
      "imagepath" : { "usage" : "G", "type" : "string" },
      "imagepos" :  { "usage" : "N", "type" : "string" }, //👈 add this line
    

    Now imagepos is recognized correctly.

    Script:

    const graphviz = require('graphviz');
    
    // Create digraph G
    var graph = graphviz.digraph("G");
    
    graph.addNode( "node name", {
      label: "A Service",
      shape: "box",
      image: "image.png",
      imagepos: "ml",
      imagescale: true,
      fixedsize: true,
      width: 3,
      height: 1,
    });
    
    // Generate a PNG output
    graph.output( "png", "file.png" );
    

    Result:
    Align image in node in Graphviz