diff --git a/inc/base.inc b/inc/base.inc
index bd030af..221b133 100644
--- a/inc/base.inc
+++ b/inc/base.inc
@@ -219,6 +219,42 @@ class StateMachine {
    * Whether State Machine to be ignored
    */
   public function ignore() { return FALSE; }
+
+  /**
+   * Return a GraphViz object representing the state machine.
+   */
+  public function toGraphViz() {
+    if (!state_machine_graphviz_include()) {
+      return FALSE;
+    }
+
+    $gv = new Image_GraphViz(TRUE);
+
+    foreach ($this->states as $key => $options) {
+      $state = $this->get_state($key);
+      $attributes = $state->graphviz_attributes();
+
+      if ($this->current == $key) {
+        $attributes['style'] = 'filled';
+        $attributes['label'] .= '*';
+      }
+
+      $gv->addNode($key, $attributes);
+    }
+
+    foreach ($this->events as $key => $options) {
+      $event = $this->get_event($key);
+      $origins = $event->get_option('origin');
+      $target = $event->get_option('target');
+      $attributes = $event->graphviz_attributes();
+
+      foreach ($origins as $origin) {
+        $gv->addEdge(array($origin => $target), $attributes);
+      }
+    }
+
+    return $gv;
+  }
 }
 
 class StateMachine_State {
@@ -265,6 +301,21 @@ class StateMachine_State {
       call_user_func_array($this->options['on_exit'], $args);
     }
   }
+
+  /**
+   * Provide an attributes array for use with an Image_GraphViz node.
+   */
+  public function graphviz_attributes() {
+    $base = $this->get_option('graphviz');
+    if (empty($base)) {
+      $base = array();
+    }
+
+    return $base + array(
+      'label' => $this->get_option('label'),
+      'shape' => 'box',
+    );
+  }
 }
 
 class StateMachine_Event {
@@ -344,4 +395,19 @@ class StateMachine_Event {
   public function can_transition_from($state) {
     return in_array($state, $this->options['origin']);
   }
+
+  /**
+   * Provide an attributes array for use with an Image_GraphViz edge.
+   */
+  public function graphviz_attributes() {
+    $base = $this->get_option('graphviz');
+    if (empty($base)) {
+      $base = array();
+    }
+
+    return $base + array(
+      'label' => $this->get_option('label'),
+      'fontsize' => 12,
+    );
+  }
 }
diff --git a/modules/state_flow/state_flow.module b/modules/state_flow/state_flow.module
index fb27e07..25d9579 100644
--- a/modules/state_flow/state_flow.module
+++ b/modules/state_flow/state_flow.module
@@ -22,6 +22,14 @@ function state_flow_menu() {
     'weight' => 10,
     'file' => 'state_flow.pages.inc',
   );
+  $items['node/%node/workflow.png'] = array(
+    'type' => MENU_CALLBACK,
+    'page callback' => 'state_flow_workflow_image',
+    'page arguments' => array(1),
+    'access callback' => 'state_flow_menu_node_access',
+    'access arguments' => array(1),
+    'file' => 'state_flow.pages.inc',
+  );
   $items['node/%node/revisions/%/edit'] = array(
     'title' => 'Edit an earlier revision',
     'load arguments' => array(3),
diff --git a/modules/state_flow/state_flow.pages.inc b/modules/state_flow/state_flow.pages.inc
index 105eb6d..dbde5ee 100644
--- a/modules/state_flow/state_flow.pages.inc
+++ b/modules/state_flow/state_flow.pages.inc
@@ -158,6 +158,15 @@ function state_flow_events($node) {
       ),
     );
   }
+  if (state_machine_graphviz_include()) {
+    $output['content']['image'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Visualization'),
+      'image' => array(
+        '#markup' => theme('image', array('path' => 'node/'. $node->nid .'/workflow.png')),
+      ),
+    );
+  }
   if (count($history_table['rows'])) {
     $output['content']['history'] = array(
       '#type' => 'fieldset',
@@ -250,3 +259,16 @@ function state_flow_events_revision_submit($form, &$form_state) {
     }
   }
 }
+
+/**
+ * Menu callback for node/%node/workflow.png
+ */
+function state_flow_workflow_image($node) {
+  if (state_machine_graphviz_include()) {
+    $state_flow = state_flow_load_state_machine($node);
+    $state_flow->toGraphViz()->image('png');
+    drupal_exit();
+  }
+  drupal_not_found();
+}
+
diff --git a/state_machine.module b/state_machine.module
index 41ef481..0c003a1 100644
--- a/state_machine.module
+++ b/state_machine.module
@@ -11,3 +11,17 @@ function state_machine_load_class_file() {
     require_once drupal_get_path('module', 'state_machine') . '/inc/base.inc';
   }
 }
+
+/**
+ * Include the PEAR Image_GraphViz library and report if it was found.
+ */
+function state_machine_graphviz_include() {
+  static $enabled;
+
+  if (!isset($enabled)) {
+    @include_once 'Image/GraphViz.php';
+    $enabled = class_exists('Image_GraphViz');
+  }
+
+  return $enabled;
+}
