【问题标题】:Create Image From .dot file in C#在 C# 中从 .dot 文件创建图像
【发布时间】:2012-01-19 17:16:51
【问题描述】:

我正在构建一个 .dot 文件来表示一个有向无环图。

我需要从这个 graph.dot 文件(使用 C#)生成一个图像,以便我可以在我的应用程序的图片框中显示图像。我应该使用什么库?

在命令提示符下使用 GraphViz 的命令:

dot -Tpng graph.dot -o graph.png 

我能够很好地生成图像,所以我知道我的 .dot 文件的格式是正确的。

谢谢。

【问题讨论】:

  • 所以我假设您不想只从 C# 应用程序中运行 dot 实用程序?

标签: c# graphviz


【解决方案1】:

感谢 @marapet 向我介绍 David Brown 的项目。

我已经下载了示例:David Brown's Implicit Operator

该示例运行良好。

我将所需的代码复制到我的项目中。我不得不将我的 .NET Target Framework 从 4.0 更改为 3.5,但这不是问题。

到目前为止,代码从未崩溃过。 (即使其他人报告了问题。)

更新

David Brown 的网站似乎已关闭,因此我使用从该网站获取的代码更新了此答案。

//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);
        }
    }
}

【讨论】:

  • 太好了!您介意分享您使用的操作系统和 graphviz 版本吗?
  • @marapet 我正在使用带有 SP1 的 Windows 7 Professional 64 位。 GraphViz 版本为 2.28.0,从 graphviz.org/Download_windows.php 下载。代码仍然没有崩溃:)
  • 嘿,样品还在吗?该网站已关闭,我需要查看该代码。
  • 对于 2.38 版 (Windows),我必须更改 3 件事:(1) graph.dll -> cgraph.dll,(2) agclose 返回 int,(3) 对于所有 DllImports:我有添加 CallingConvention = CallingConvention.Cdecl。 ((3) 修复了堆栈不平衡问题,只有 VS Managed Debugging Assistant 或 StackOverflowException 在多次调用时才会观察到)
【解决方案2】:

你可以使用 Process 来启动 dot.exe

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

 Process.Start(startInfo);

【讨论】:

  • 感谢您的意见。这确实有效,但这不是我想要的。如果我可以使用一些库,该库具有将 .dot 文件作为参数(或文件中找到的字符串)并返回图像的方法,我会更喜欢。
  • @Rachel 没问题,有点软糖,但我能想到的。
  • +1 是的,这是一个 hack。但有时像这样的 hack 可以让你摆脱困境。
【解决方案3】:

这很难,我为 GraphViz 找到了一个名为 GrapVizNet 的 .NET 包装器,这可能使它成为可能。

一个更有趣的方法是使用PInvoke 为您自己创建一个包装器。我相信this 正是您所需要的。不是最优雅的解决方案,但也许是您唯一的解决方案。

【讨论】:

  • 大卫布朗的项目实际上完全符合问题中的要求。唯一的问题是最近的版本中似乎存在错误 - 另请参阅 David Brown 关于 SO 的问题:stackoverflow.com/a/4876966/63733
  • @marapet +1 看到那个。快速搜索并没有给我任何信息是否已修复此错误。您必须尝试一下才能找到答案。
  • 它没有——至少根据@David Brown 提交的错误报告(18701775)的状态没有。有人建议使用相同的编译器在 Windows 上构建 graphviz 本身 - 不知道这是否有帮助。
  • @marapet 好的。奇怪的是,我希望 dot 工具使用相同的底层库。
【解决方案4】:

This other library called Graphviz.NetWrapper 允许您在 C# 代码中构建图形,使用 graphviz 库计算布局,并使用 C# 读取布局信息(如位置等),或直接生成图像文件。

这样,您可以选择是嵌入原始图像,还是根据提供给您的布局信息自行绘制图像。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多