2011-12-13 15 views
5

Estoy construyendo un archivo .dot para representar un gráfico acíclico dirigido.Crear imagen del archivo .dot en C#

Necesito generar una imagen desde este archivo graph.dot (usando C#) para que pueda mostrar la imagen en una Picture Box en mi aplicación. ¿Qué biblioteca debería usar?

Usando el mando de GraphViz en el símbolo del sistema:

dot -Tpng graph.dot -o graph.png 

soy capaz de generar la imagen fina, así que sé que el formato de mi archivo .dot es correcta.

Gracias.

+0

Así que supongo que no desea simplemente ejecutar la utilidad de punto de su aplicación C#? – RQDQ

+0

No, eso no es lo que quiero. – Rachel

Respuesta

4

Gracias @marapet por señalarme el proyecto de David Brown.

he descargado la muestra en: David Brown's Implicit Operator

La muestra funciona bien.

He copiado el código requerido en mi proyecto. Tuve que cambiar mi .NET Target Framework de 4.0 a 3.5, pero eso no es un problema.

Hasta ahora, el código nunca se ha bloqueado. (A pesar de que otras personas han informado de problemas.)

ACTUALIZACIÓN

página web de David Brown parece estar abajo por lo que he actualizado esta respuesta con el código que había tomado de la página web.

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

¡Eso es genial!¿Le importaría compartir qué sistema operativo y qué versión de gráficos usa? – marapet

+1

@marapet Estoy usando Windows 7 Professional de 64 bits con SP1. La versión de GraphViz es 2.28.0, tal como se descargó de http://www.graphviz.org/Download_windows.php. El código aún no se ha bloqueado :) – Rachel

+0

Oye, ¿todavía tienes la muestra? El sitio web está caído y necesito ver ese código. – pmichna

2

Se podría utilizar el proceso para iniciar dot.exe

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

Process.Start(startInfo); 
+0

Gracias por su contribución. Eso funciona, pero no es lo que estoy buscando. Preferiría si pudiera usar alguna biblioteca que tenga un método que tome el archivo .dot como parámetro (o la cadena encontrada en el archivo) y devuelva la imagen. – Rachel

+0

@Rachel no hay problema, un poco dulce, pero todo lo que pude pensar. –

+0

+1 Sí, es un truco. Pero a veces un truco como este puede sacarte de un aprieto. – user

2

Este es dura, me encontré con un envoltorio de .NET para GraphViz llama GrapVizNet la que tal vez lo hace posible.

Una más interesante es crear un contenedor con PInvoke. Creo que this es exactamente lo que necesita. No es la solución más elegante, pero tal vez la única que tienes.

+2

El proyecto de David Brown realmente hace exactamente lo que se pregunta en la pregunta. El único problema es que parece haber un error en las versiones recientes; consulte también la pregunta de David Brown sobre SO: http://stackoverflow.com/a/4876966/63733 – marapet

+0

@marapet +1 para ver esa. Una búsqueda rápida no me proporciona ninguna información sobre si este error se ha solucionado. Tendrás que probarlo para averiguarlo. –

+0

No tiene, al menos, no según el estado de los informes de errores ([1870] (http://www.graphviz.org/bugs/b1870.html) y [1775] (http: //www.graphviz .org/bugs/b1775.html)) archivado por @David Brown. Alguien sugiere construir graphviz en las ventanas con el mismo compilador, no sé si eso ayuda. – marapet