Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中从.dot文件创建图像#_C#_Graphviz - Fatal编程技术网

C# 在C中从.dot文件创建图像#

C# 在C中从.dot文件创建图像#,c#,graphviz,C#,Graphviz,我正在构建一个.dot文件来表示有向无环图 我需要从这个graph.dot文件生成一个图像(使用C#),这样我就可以在应用程序的图片框中显示图像。我应该使用什么图书馆 在命令提示符下使用GraphViz的命令: dot -Tpng graph.dot -o graph.png 我能够很好地生成图像,因此我知道.dot文件的格式是正确的 谢谢。您可以使用进程启动dot.exe ProcessStartInfo startInfo = new ProcessStartInfo("dot.exe

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

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

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

dot -Tpng graph.dot -o graph.png 
我能够很好地生成图像,因此我知道.dot文件的格式是正确的


谢谢。

您可以使用进程启动dot.exe

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

 Process.Start(startInfo);

这是一个困难的问题,我为GraphViz找到了一个名为.NET的包装器,这可能使它成为可能


一个更有趣的方法是用你自己创建一个包装器。我相信这正是你需要的。这不是最优雅的解决方案,但可能是您唯一的解决方案。

谢谢@marapet为我介绍大卫·布朗的项目

我已在以下网址下载了示例:

这个样品很好用

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

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

更新

大卫·布朗的网站似乎关闭了,所以我用从网站上获取的代码更新了这个答案

//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);
        }
    }
}
//此类的代码已从下载http://implicitoperator.com/blog/2010/4/11/graphviz-c-sample.html
公共类GraphViz
{
public const string LIB_GVC=“GVC.dll”;
public const string LIB_GRAPH=“GRAPH.dll”;
公共const int SUCCESS=0;
///  
///创建新的Graphviz上下文。
///  
[DllImport(LIB_GVC)]
公共静态外部IntPtr gvContext();
///  
///从字符串读取图形。
///  
[DllImport(LIB_图)]
公共静态外部IntPtr agmemread(字符串数据);
///  
///在内存中呈现图形。
///  
[DllImport(LIB_GVC)]
公共静态外部int gvRenderData(IntPtr gvc、IntPtr g、,
字符串格式,输出IntPtr结果,输出int长度);
///  
///使用给定引擎将布局应用于图形。
///  
[DllImport(LIB_GVC)]
公共静态外部int gvLayout(IntPtr gvc、IntPtr g、字符串引擎);
///  
///释放布局使用的资源。
///  
[DllImport(LIB_GVC)]
公共静态外部int gvFreeLayout(IntPtr gvc、IntPtr g);
///  
///释放上下文的资源。
///  
[DllImport(LIB_GVC)]
公共静态外部int gvFreeContext(IntPtr gvc);
///  
///释放图形使用的资源。
///  
[DllImport(LIB_图)]
公共静态外部无效(IntPtr g);
公共静态图像渲染(字符串源、字符串布局、字符串格式)
{
//创建Graphviz上下文
IntPtr gvc=gvContext();
如果(gvc==IntPtr.Zero)
抛出新异常(“未能创建Graphviz上下文”);
//将点数据加载到图形中
IntPtr g=agmemread(源);
如果(g==IntPtr.Zero)
抛出新异常(“未能从源创建图形。请检查语法错误”);
//应用布局
if(gvLayout(gvc、g、layout)!=成功)
抛出新异常(“布局失败”);
IntPtr结果;
整数长度;
//渲染图形
if(gvRenderData(gvc、g、格式、输出结果、输出长度)!=成功)
抛出新异常(“渲染失败”);
//创建一个数组以保存渲染的图形
字节[]字节=新字节[长度];
//从IntPtr复制图像
Marshal.Copy(结果,字节,0,长度);
//释放资源
全球价值链(gvc,g);
agclose(g);
全球价值链;
使用(内存流=新内存流(字节))
{
返回Image.FromStream(stream);
}
}
}
允许您使用C#代码构建图形,使用graphviz库计算布局,并使用C#读取布局信息(如位置等),或直接生成和图像文件


通过这种方式,您可以选择是嵌入原始图像,还是根据提供给您的布局信息自己绘制图像。

因此,我假设您不想从C#应用程序中运行dot实用程序?谢谢您的输入。这确实管用,但这不是我想要的。我更愿意使用一个库,它有一个方法,将.dot文件作为参数(或文件中的字符串)并返回图像。@Rachel没问题,有点胡说八道,但我所能想到的一切。+1是的,这是一个黑客。但有时,像这样的黑客可以让你摆脱困境。大卫·布朗的项目实际上完全符合问题中的要求。唯一的问题是,在最近的版本中似乎有一个bug——另请参见David Brown关于SO的问题:@marapet+1以查看该bug。快速搜索不会给我任何关于此错误是否已修复的信息。你必须尝试一下才能找到答案。事实并非如此——至少从@David Brown提交的bug报告(和)的状态来看是如此。有人建议在windows上使用相同的编译器构建graphviz本身,但不知道这是否有帮助。@marapet OK。奇怪的是,我希望dot工具使用相同的底层libs。太棒了!您介意分享一下您使用的操作系统和graphviz版本吗?@marapet我使用的是64位Windows 7 Professional SP1。GraphViz版本为2.28.0,从下载。代码仍然没有崩溃:)嘿,你还有样本吗?该网站已关闭,我需要查看该代码。对于2.38版(Windows),我必须更改3件事:(1)graph.dll->cgraph.dll,(2)agclose返回int,(3)对于所有DllImports:我必须添加CallingConvention=CallingConvention.Cdecl。((3)固定的不平衡堆栈,在多次调用时仅由VS托管调试助手或StackOverflowException观察到)