6

I am building a .dot file to represent a directed acyclic graph.

I need to generate an image from this graph.dot file (using C#) so that I can show the image in a Picture Box in my application. What library should I use?

Using GraphViz's command in the command prompt:

dot -Tpng graph.dot -o graph.png 

I am able to generate the image fine, so I know that the formatting of my .dot file is correct.

Thank you.

Rachel
  • 1,722
  • 8
  • 29
  • 34

4 Answers4

5

Thank you @marapet for pointing me to David Brown's project.

I have downloaded the sample at: David Brown's Implicit Operator

The sample works well.

I copied the required code to my project. I had to change my .NET Target Framework from 4.0 to 3.5, but that isn't a problem.

So far, the code has never crashed. (Even though other people have reported issues.)

UPDATE

David Brown's website seems to be down so I have updated this answer with the code I'd taken from the website.

//Code for this Class downloaded from http://implicitoperator.com/blog/2010/4/11/graphviz-c-sample.html

public class GraphViz
{

    public const string LIB_GVC = "gvc.dll";
    public const string LIB_GRAPH = "graph.dll";
    public const int SUCCESS = 0;

    /// <summary> 
    /// Creates a new Graphviz context. 
    /// </summary> 
    [DllImport(LIB_GVC)]
    public static extern IntPtr gvContext();

    /// <summary> 
    /// Reads a graph from a string. 
    /// </summary> 
    [DllImport(LIB_GRAPH)]
    public static extern IntPtr agmemread(string data);

    /// <summary> 
    /// Renders a graph in memory. 
    /// </summary> 
    [DllImport(LIB_GVC)]
    public static extern int gvRenderData(IntPtr gvc, IntPtr g,
        string format, out IntPtr result, out int length);

    /// <summary> 
    /// Applies a layout to a graph using the given engine. 
    /// </summary> 
    [DllImport(LIB_GVC)]
    public static extern int gvLayout(IntPtr gvc, IntPtr g, string engine);

    /// <summary> 
    /// Releases the resources used by a layout. 
    /// </summary> 
    [DllImport(LIB_GVC)]
    public static extern int gvFreeLayout(IntPtr gvc, IntPtr g);

    /// <summary> 
    /// Releases a context's resources. 
    /// </summary> 
    [DllImport(LIB_GVC)]
    public static extern int gvFreeContext(IntPtr gvc);

    /// <summary> 
    /// Releases the resources used by a graph. 
    /// </summary> 
    [DllImport(LIB_GRAPH)]
    public static extern void agclose(IntPtr g);

    public static Image RenderImage(string source, string layout, string format)
    {
        // Create a Graphviz context 
        IntPtr gvc = gvContext();
        if (gvc == IntPtr.Zero)
            throw new Exception("Failed to create Graphviz context.");

        // Load the DOT data into a graph 
        IntPtr g = agmemread(source);
        if (g == IntPtr.Zero)
            throw new Exception("Failed to create graph from source. Check for syntax errors.");

        // Apply a layout 
        if (gvLayout(gvc, g, layout) != SUCCESS)
            throw new Exception("Layout failed.");

        IntPtr result;
        int length;

        // Render the graph 
        if (gvRenderData(gvc, g, format, out result, out length) != SUCCESS)
            throw new Exception("Render failed.");

        // Create an array to hold the rendered graph
        byte[] bytes = new byte[length];

        // Copy the image from the IntPtr 
        Marshal.Copy(result, bytes, 0, length);

        // Free up the resources 
        gvFreeLayout(gvc, g);
        agclose(g);
        gvFreeContext(gvc);

        using (MemoryStream stream = new MemoryStream(bytes))
        {
            return Image.FromStream(stream);
        }
    }
}
Rachel
  • 1,722
  • 8
  • 29
  • 34
  • 1
    That's great! Would you mind sharing what OS and graphviz version you're using? – marapet Dec 28 '11 at 18:47
  • 1
    @marapet I am using Windows 7 Professional 64-bit with SP1. GraphViz version is 2.28.0, as downloaded from http://www.graphviz.org/Download_windows.php. The code still hasn't crashed :) – Rachel Dec 28 '11 at 18:51
  • Hey, do you still have the sample? The website is down and I need to look at that code. – pmichna May 15 '13 at 19:43
  • 1
    For version 2.38 (Windows), I had to change 3 things: (1) graph.dll -> cgraph.dll, (2) agclose returns int, (3) for all DllImports: I had to add CallingConvention = CallingConvention.Cdecl. ((3) fixed imbalanced stack which was only observed by the VS Managed Debugging Assistant or by StackOverflowException when called multiple times) – eikuh Feb 15 '20 at 20:15
2

You could use Process to start dot.exe

 ProcessStartInfo startInfo = new ProcessStartInfo("dot.exe");
 startInfo.Arguments = "-Tpng graph.dot -o graph.png";

 Process.Start(startInfo);
PMC
  • 4,698
  • 3
  • 37
  • 57
  • 1
    Thank you for your input. That does work, but it's not what I'm looking for. I would prefer if I could use some library which has a method that takes the .dot file as a parameter (or the String found in the file) and returns the image. – Rachel Dec 13 '11 at 21:06
  • @Rachel no problem, bit of a fudge but all I could think of. – PMC Dec 13 '11 at 21:14
  • +1 Yes, it's a hack. But sometimes a hack like this can get you out of a bind. – user Sep 07 '13 at 09:25
2

This is a hard one, I found a .NET wrapper for GraphViz called GrapVizNet which maybe makes it possible.

A more interesting one is creating a wrapper your self with PInvoke. I believe this is exactly what you need. Not the most elegant solution but maybe the only you got.

Martijn B
  • 4,065
  • 2
  • 29
  • 41
  • 2
    The project of David Brown does actually exactly what's asked in the question. The only problem is that there seems to be a bug in recent versions - see also David Brown's question on SO: http://stackoverflow.com/a/4876966/63733 – marapet Dec 14 '11 at 10:24
  • @marapet +1 for seeing that one. A quick search doesn't give me any info whether this bug has been fixed. You will have to try it out to find out. – Martijn B Dec 14 '11 at 10:37
  • It hasn't - at least not according to the status of the bug reports ([1870](http://www.graphviz.org/bugs/b1870.html) and [1775](http://www.graphviz.org/bugs/b1775.html)) filed by @David Brown . Someone suggest building graphviz itself on windows with the same compiler - don't know whether that helps. – marapet Dec 14 '11 at 12:38
  • @marapet OK. Strange I would expect the dot tool to use the same underlying libs. – Martijn B Dec 14 '11 at 12:46
0

This other library called Graphviz.NetWrapper allows you to build graphs in C# code, compute a layout using the graphviz library, and read the layout information (like positions etc) back out using C#, or generate and image file directly.

This way you have the choice whether you want to embed a raw image, or draw the image yourself based on the layout information that is given to you.

chtenb
  • 14,924
  • 14
  • 78
  • 116