diff --git a/doc/commands.doc b/doc/commands.doc
index 1b3f2bd..b0bb23d 100644
--- a/doc/commands.doc
+++ b/doc/commands.doc
@@ -95,6 +95,7 @@ documentation:
 \refitem cmdenum \\enum
 \refitem cmdexample \\example
 \refitem cmdexception \\exception
+\refitem cmdextimagefile \\extimagefile
 \refitem cmdextends \\extends
 \refitem cmdfdollar \\f\$
 \refitem cmdfbropen \\f[
@@ -2644,6 +2645,39 @@ Without the name doxygen will choose a name automatically.
   stripped before the caption is displayed.
 
 <hr>
+\section cmdextimagefile \\extimagefile <file> ["caption" [<sizeindication>=<size>]]
+
+  \addindex \\extimagefile
+  Inserts an image into the documentation. The image file is converted
+  for the output format using an external program or script (see \ref
+  cfg_extimage_converter "EXTIMAGE_CONVERTER").
+
+  The first argument specifies the file name of the image. Doxygen will
+  look for files in the paths (or files) that you specified after the
+  \ref cfg_extimagefile_dirs "EXTIMAGEFILE_DIRS" tag. If the image is
+  found it will be converted using the
+  \ref cfg_extimage_converter "configured" external script and placed in
+  the correct output directory. If the image name contains spaces you'll
+  have to put quotes ("...") around it.
+
+  The second argument is optional and can be used to specify the caption
+  that is displayed below the image. This argument has to be specified
+  on a single line and between quotes even if it does not contain any
+  spaces. The quotes are stripped before the caption is displayed.
+
+  The third argument is also optional and can be used to specify the
+  width or height of the image. This is only used
+  for LaTeX and DocBook output. The \c sizeindication can be
+  either \c width or \c height. The size should be a valid
+  size specifier in LaTeX and DocBook (for example <code>10cm</code> or
+  <code>6in</code>).
+
+  \sa sections \ref cmdimage "\\image",
+               \ref cmddotfile "\\dotfile",
+               \ref cmddiafile "\\diafiel", and
+               \ref cmdmscfile "\\mscfile".
+
+<hr>
 \section cmde \\e <word>
 
   \addindex \\e
@@ -2889,6 +2923,8 @@ Without the name doxygen will choose a name automatically.
            Doxygen does not check if the image is in the correct format.
            So \e you have to make sure this is the case!
 
+  \sa sections \ref cmdextimagefile "\\extimagefile".
+
 <hr>
 \section cmdlatexonly \\latexonly
 
diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp
index b0ca85f..1a36396 100644
--- a/src/cmdmapper.cpp
+++ b/src/cmdmapper.cpp
@@ -140,6 +140,7 @@ CommandMap cmdMap[] =
   { "diafile",       CMD_DIAFILE },
   { "--",            CMD_NDASH },
   { "---",           CMD_MDASH },
+  { "extimagefile",  CMD_EXTIMAGEFILE },
   { 0,               0 },
 };
 
diff --git a/src/cmdmapper.h b/src/cmdmapper.h
index 75fd8ec..abb48bb 100644
--- a/src/cmdmapper.h
+++ b/src/cmdmapper.h
@@ -129,7 +129,8 @@ enum CommandType
   CMD_NDASH        = 99,
   CMD_MDASH        = 100,
   CMD_STARTUML     = 101,
-  CMD_ENDUML       = 102
+  CMD_ENDUML       = 102,
+  CMD_EXTIMAGEFILE = 103
 };
 
 enum HtmlTagType
diff --git a/src/compound.xsd b/src/compound.xsd
index be897c3..89556b9 100644
--- a/src/compound.xsd
+++ b/src/compound.xsd
@@ -418,6 +418,7 @@
       <xsd:element name="dotfile" type="docFileType" />
       <xsd:element name="mscfile" type="docFileType" />
       <xsd:element name="diafile" type="docFileType" />
+      <xsd:element name="extimagefile" type="docFileType" />
       <xsd:element name="toclist" type="docTocListType" />
       <xsd:element name="language" type="docLanguageType" />
       <xsd:element name="parameterlist" type="docParamListType" />
diff --git a/src/config.xml b/src/config.xml
index b66d583..431cad2 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -3391,4 +3391,321 @@ remove the intermediate dot files that are used to generate the various graphs.
     <option type='obsolete' id='XML_SCHEMA'/>
     <option type='obsolete' id='XML_DTD'/>
   </group>
+
+  <group name='ExtImage' docs='Configuration options related to the external image converter tool'>
+    <option type='list' id='EXTIMAGE_CONVERTER' format='string' defval=''>
+      <docs>
+<![CDATA[
+ Image files included with the \ref cmdextimagefile "\\extimagefile"
+ command are converted to the required output format using an external
+ program or script specified by the configuration option \ref cfg_extimage_converter "EXTIMAGE_CONVERTER".
+ <br>
+ The script is invoked with two options:
+ - <code>-f</code>: Absolute path of the input file
+ - <code>-o</code>: Absolute path of the output file to write
+
+ The input and output formats may be detected by the file extensions.
+ Note: Separate the arguments from the executable as in the example.
+]]>
+      </docs>
+      <docs doxywizard='0' doxyfile='0'>
+<![CDATA[
+ <br>
+ Example configuration for a bash script:
+ \verbatim
+ EXTIMAGE_CONVERTER = "bash" "diagram_converter.sh"
+ \endverbatim
+ <br>
+ Example for a bash script:
+ \verbatim
+#!/bin/bash
+#.SYNOPSIS
+#    Transform an input diagram to an image file used by doxygen
+#
+#.EXAMPLE
+#    diagram_converter.sh -o OUTFILE -f INFILE
+#
+#.PARAMETER f
+#    Input file
+#.PARAMETER o
+#     Output file, format is recognized from file extension
+#
+
+#-------------------------------------------------------------------------------
+# Configuration
+#-------------------------------------------------------------------------------
+UMLET_EXE="d:/thirdparty/umlet/12.2/Umlet.exe"
+
+
+#-------------------------------------------------------------------------------
+# Functions
+#-------------------------------------------------------------------------------
+# Print an error message and exit script with error code 2
+#
+# @param $1 message
+exit_error()
+{
+  echo Error: $1 >&2
+  exit 2;
+}
+
+
+#-------------------------------------------------------------------------------
+# Parse script arguments
+#-------------------------------------------------------------------------------
+inputFile=
+ouputFile=
+
+while getopts o:f: flag; do
+  case $flag in
+    o)
+      outputFile=$OPTARG;
+      ;;
+    f)
+      inputFile=$OPTARG;
+      ;;
+    ?)
+      echo Usage: diagram_converter.sh -o OUTFILE -f INFILE
+      exit 2;
+      ;;
+  esac
+done
+shift $(( OPTIND - 1 ));
+
+if [[ -z $inputFile ]]; then
+  exit_error "no input file specified";
+fi
+if [[ -z $outputFile ]]; then
+  exit_error "no output file specified";
+fi
+
+# file formats (from file extension)
+inputFormat=${inputFile##*.}
+outputFormat=${outputFile##*.}
+
+
+#-------------------------------------------------------------------------------
+# Main
+#-------------------------------------------------------------------------------
+case $inputFormat in
+  "uxf")
+    case $outputFormat in
+      "png"|"svg"|"eps"|"pdf"|"bmp"|"gif"|"jpg")
+        $UMLET_EXE -action=convert -format=$outputFormat -filename="$inputFile" -output="${outputFile%.*}"  || exit 1;
+        ;;
+
+      *)
+        exit_error "Unsupported output format for UMLet files";
+        exit 1;
+        ;;
+    esac
+    ;;
+
+  *)
+    exit_error "Unsupported input format $inputFormat";
+esac
+
+exit 0;
+ \endverbatim
+ <br>
+ Example configuration for a Windows PowerShell script:
+ \verbatim
+ EXTIMAGE_CONVERTER = "powershell" "-ExecutionPolicy RemoteSigned -File .\diagram_converter.ps1"
+ \endverbatim
+ <br>
+ Example for a Windows PowerShell script:
+ \verbatim
+<#
+.SYNOPSIS
+    Transform an input diagram to an image file used by doxygen
+
+    diagram_converter.ps1 -o OUTFILE -f INFILE
+
+.DESCRIPTION
+    Automated build: Export UMLet diagram files to image files for
+    including in the generated doxygen documentation. This script is
+    called from the doxygen.exe program (see doxygen configuration
+    EXTIMAGE_CONVERTER).
+
+.EXAMPLE
+    diagram_converter.ps1 -o OUTFILE -f INFILE
+
+.PARAMETER f
+    Input file
+.PARAMETER o
+     Output file, format is recognized from file extension
+#>
+
+#-------------------------------------------------------------------------------
+# Script input parameters
+#-------------------------------------------------------------------------------
+PARAM
+(
+    # output file
+    [Parameter(Mandatory=$true)]
+    [string]
+    $o,
+
+    # input file
+    [Parameter(Mandatory=$true)]
+    [string]
+    $f
+)
+
+
+#-------------------------------------------------------------------------------
+# Configuration
+#-------------------------------------------------------------------------------
+$umletJar   = "d:/thirdparty/umlet/12.2/umlet.jar";
+
+
+#-------------------------------------------------------------------------------
+# Variable definitions
+#-------------------------------------------------------------------------------
+$scriptName     = $MyInvocation.MyCommand.Name
+$inputFile      = $f
+$outputFile     = $o
+
+
+#-------------------------------------------------------------------------------
+# Functions
+#-------------------------------------------------------------------------------
+function Get-Format([string]$filename)
+{
+    $format  = [System.IO.Path]::GetExtension($filename).ToLower()
+    if($format -eq $null -or $format.Length -lt 2)
+    {
+        throw [system.FormatException]"Invalid file extension"
+    }
+
+    $format.SubString(1)
+}
+
+function Call-Exe([string]$exeFile, [string]$arguments)
+{
+    $info = New-Object System.Diagnostics.ProcessStartInfo
+    $info.FileName                  = $exeFile;
+    $info.RedirectStandardError     = $true
+    $info.RedirectStandardOutput    = $true
+    $info.UseShellExecute           = $false
+    $info.Arguments                 = $arguments
+    $proc = New-Object System.Diagnostics.Process
+    $proc.StartInfo = $info
+    $proc.Start() | Out-Null
+    $proc.WaitForExit()
+    if($proc.ExitCode -ne 0)
+    {
+        throw "$exeFile exit with code " + $proc.ExitCode
+    }
+}
+
+function Call-Jar([string]$jarFile, [string]$arguments)
+{
+    Call-Exe "java.exe" "-jar $jarFile $arguments"
+}
+
+
+#-------------------------------------------------------------------------------
+# Main
+#-------------------------------------------------------------------------------
+try
+{
+    $inputFormat        = Get-Format $inputFile
+    $outputFormat       = Get-Format $outputFile
+    $outputFileNoExt    = [System.IO.Path]::Combine(
+        [System.IO.Path]::GetDirectoryName($outputFile),
+        [System.IO.Path]::GetFileNameWithoutExtension($outputFile))
+
+    switch($inputFormat)
+    {
+        "uxf"
+        {
+            $supportedFormats = "png", "svg", "eps", "pdf", "bmp", "gif", "jpg"
+            if($supportedFormats -contains $outputFormat)
+            {
+                $umletArgs =
+                    "-action=convert",
+                    "-format=$outputFormat",
+                    "-filename=`"$inputFile`"",
+                    "-output=`"$outputFileNoExt`"";
+                Call-Jar $umletJar $umletArgs;
+            }
+            else
+            {
+                throw [system.NotImplementedException]"Output format $outputFormat for UMLet is not supported"
+            }
+        }
+
+        default
+        {
+            throw [system.NotImplementedException]"Input format $inputFormat is not supported"
+        }
+    }
+
+    [System.Environment]::Exit(0)
+}
+catch
+{
+    echo "Error in $scriptName : $error"
+    [System.Environment]::Exit(1)
+}
+
+# eof
+ \endverbatim
+ <br>
+ For this configuration and a \\extimagefile foo.uxf command in the code, the script will be invoked as follows:
+ \verbatim
+ powershell -ExecutionPolicy RemoteSigned -File .\diagram_converter.ps1 -o "d:/example/html/foo.png" -f "d:/example/foo.uxf"
+ \endverbatim
+ <br>
+ Output formats used:
+ - HTML (EXTIMAGE_MAPPING not used): png
+ - HTML (EXTIMAGE_MAPPING used): as configured
+ - LaTeX (USE_PDFLATEX = YES): pdf
+ - LaTeX (USE_PDFLATEX = NO): eps
+ - DocBook: png
+ - RTF: png
+ - man page, Perl Module: Not supported
+]]>
+      </docs>
+      <docs documentation='0'>
+<![CDATA[
+ <br>
+ Example configuration for a bash script:
+ \verbatim
+ EXTIMAGE_CONVERTER = "bash" "diagram_converter.sh"
+ \endverbatim
+ <br>
+ For an example script see the documentation.
+]]>
+      </docs>
+    </option>
+    <option type='list' id='EXTIMAGEFILE_DIRS' format='dir'>
+      <docs>
+<![CDATA[
+ The \c EXTIMAGEFILE_DIRS tag can be used to specify one or more directories that 
+ contain external image files that are included in the documentation (see the
+ \ref cmdextimagefile "\\extimagefile" command). The images are converted using an
+ external program (see \ref cfg_extimage_converter "EXTIMAGE_CONVERTER" for further
+ information on how the external converter is used.
+]]>
+      </docs>
+    </option>
+    <option type='list' id='EXTIMAGE_MAPPING' format='string'>
+      <docs>
+<![CDATA[
+ By default the image converter uses the png format for HTML output.
+ With "EXTIMAGE_CONVERTER" With this tag you can override the used
+ format depending on input file format (i.e. extension). The converter
+ specified with \ref cfg_extimage_converter "EXTIMAGE_CONVERTER" must
+ support the formats specified here.
+
+ For instance to convert <code>.uxf</code> files (UMlet) to svg, and
+ <code>.dia</code> files to png, use: `uxf=svg dia=png`. All other (not
+ specified) input formats are converted to png.
+]]>
+      </docs>
+    </option>
+
+  </group>
 </doxygenconfig>
diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp
index a227dd8..678ae77 100644
--- a/src/docbookvisitor.cpp
+++ b/src/docbookvisitor.cpp
@@ -33,6 +33,7 @@
 #include "filedef.h"
 #include "msc.h"
 #include "dia.h"
+#include "extimage.h"
 #include "htmlentity.h"
 #include "plantuml.h"
 
@@ -960,6 +961,18 @@ void DocbookDocVisitor::visitPost(DocDiaFile *df)
   endDiaFile(df->hasCaption());
 }
 
+void DocbookDocVisitor::visitPre(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  startExtImageFile(df->file(),df->width(),df->height(),df->hasCaption());
+}
+
+void DocbookDocVisitor::visitPost(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  endExtImageFile(df->hasCaption());
+}
+
 void DocbookDocVisitor::visitPre(DocLink *lnk)
 {
   if (m_hide) return;
@@ -1372,6 +1385,65 @@ void DocbookDocVisitor::endDiaFile(bool hasCaption)
   m_t << "</para>" << endl;
 }
 
+void DocbookDocVisitor::startExtImageFile(const QCString &fileName,
+    const QCString &width,
+    const QCString &height,
+    bool hasCaption
+    )
+{
+  QCString baseName=fileName;
+  int i;
+  if ((i=baseName.findRev('/'))!=-1)
+  {
+    baseName=baseName.right(baseName.length()-i-1);
+  }
+  while ((i=baseName.find('.'))!=-1)
+  {
+    baseName.replace(i, 1, "_");
+  }
+  baseName.prepend("extimage_");
+  QCString outDir = Config_getString("DOCBOOK_OUTPUT");
+  writeExtImageFileFromFile(fileName,outDir,baseName,EXTIMAGE_PNG);
+  m_t << "<para>" << endl;
+  m_t << "    <figure>" << endl;
+  m_t << "        <title></title>" << endl;
+  m_t << "        <mediaobject>" << endl;
+  m_t << "            <imageobject>" << endl;
+  m_t << "                <imagedata";
+  if (!width.isEmpty())
+  {
+    m_t << " width=\"";
+    m_t << width;
+    m_t << "\"";
+  }
+  else if (!height.isEmpty())
+  {
+    m_t << " depth=\"";
+    m_t << height;
+    m_t << "\"";
+  }
+  m_t << " align=\"center\" fileref=\"" << baseName << ".png" << "\">";
+  m_t << "</imagedata>" << endl;
+  m_t << "            </imageobject>" << endl;
+  if (hasCaption)
+  {
+    m_t << "        <caption>" << endl;
+  }
+}
+
+void DocbookDocVisitor::endExtImageFile(bool hasCaption)
+{
+  if (m_hide) return;
+  m_t << "endl";
+  if (hasCaption)
+  {
+    m_t << "        </caption>" << endl;
+  }
+  m_t << "        </mediaobject>" << endl;
+  m_t << "    </figure>" << endl;
+  m_t << "</para>" << endl;
+}
+
 void DocbookDocVisitor::writeDotFile(const QCString &baseName)
 {
   QCString shortName = baseName;
diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h
index dd67aba..a8dfd35 100644
--- a/src/docbookvisitor.h
+++ b/src/docbookvisitor.h
@@ -105,6 +105,8 @@ class DocbookDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *);
     void visitPost(DocLink *);
     void visitPre(DocRef *);
@@ -152,6 +154,9 @@ class DocbookDocVisitor : public DocVisitor
                       const QCString &height, bool hasCaption);
     void endDiaFile(bool hasCaption);
     void writeDiaFile(const QCString &fileName);
+    void startExtImageFile(const QCString &fileName,const QCString &width,
+                           const QCString &height, bool hasCaption);
+    void endExtImageFile(bool hasCaption);
     void startDotFile(const QCString &fileName,const QCString &width,
     const QCString &height, bool hasCaption);
     void endDotFile(bool hasCaption);
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 144dd24..fb2b586 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -2867,6 +2867,85 @@ void DocDiaFile::parse()
 
 //---------------------------------------------------------------------------
 
+DocExtImageFile::DocExtImageFile(DocNode *parent,const QCString &name,const QCString &context) :
+      m_name(name), m_relPath(g_relPath), m_context(context)
+{
+  m_parent = parent;
+}
+
+void DocExtImageFile::parse()
+{
+  // @extimagefile filename.ext "Caption text" width=1cm Additional text following...
+  //                           ^-- current lexer position
+  g_nodeStack.push(this);
+  DBG(("DocExtImageFile::parse() start\n"));
+
+  // parse caption
+  doctokenizerYYsetStateTitle();
+  int tok;
+  while ((tok=doctokenizerYYlex()))
+  {
+    if (!defaultHandleToken(this,tok,m_children))
+    {
+      switch (tok)
+      {
+        case TK_COMMAND:
+          warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\extimagefile",
+                         qPrint(g_token->name));
+          break;
+        case TK_SYMBOL:
+          warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
+                         qPrint(g_token->name));
+          break;
+        default:
+          warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
+                         tokToString(tok));
+          break;
+      }
+    }
+  }
+  // parse size attributes
+  tok=doctokenizerYYlex();
+  while (tok==TK_WORD) // there are values following the title
+  {
+    if (g_token->name=="width")
+    {
+      m_width=g_token->chars;
+    }
+    else if (g_token->name=="height")
+    {
+      m_height=g_token->chars;
+    }
+    else
+    {
+      warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title",
+                     qPrint(g_token->name));
+    }
+    tok=doctokenizerYYlex();
+  }
+  doctokenizerYYsetStatePara();
+  handlePendingStyleCommands(this,m_children);
+
+  // check if the file exists
+  bool ambig;
+  FileDef *fd = findFileDef(Doxygen::extImageFileNameDict,m_name,ambig);
+  if (fd)
+  {
+    m_file = fd->absFilePath();
+  }
+  else
+  {
+    warn_doc_error(g_fileName,doctokenizerYYlineno,"included image file %s is not found "
+           "in any of the paths specified via EXTIMAGEFILE_DIRS!",qPrint(m_name));
+  }
+
+  DBG(("DocExtImageFile::parse() end\n"));
+  DocNode *n=g_nodeStack.pop();
+  ASSERT(n==this);
+}
+
+//---------------------------------------------------------------------------
+
 DocVhdlFlow::DocVhdlFlow(DocNode *parent)
 {
   m_parent = parent;
@@ -5128,6 +5207,35 @@ void DocPara::handleDiaFile(const QCString &cmdName)
   df->parse();
 }
 
+void DocPara::handleExtImageFile(const QCString &cmdName)
+{
+  // @extimagefile filename.ext "Caption text" width=1cm Additional text following...
+  int tok=doctokenizerYYlex();
+  if (tok!=TK_WHITESPACE)
+  {
+    warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+        qPrint(cmdName));
+    return;
+  }
+
+  // parse filename.ext
+  doctokenizerYYsetStateFile();
+  tok=doctokenizerYYlex();
+  doctokenizerYYsetStatePara();
+  if (tok!=TK_WORD)
+  {
+    warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
+        tokToString(tok),qPrint(cmdName));
+    return;
+  }
+  QCString name = g_token->name;
+  DocExtImageFile *df = new DocExtImageFile(this,name,g_context);
+  m_children.append(df);
+
+  // parse remaining arguments following the filename
+  df->parse();
+}
+
 void DocPara::handleVhdlFlow()
 {
   DocVhdlFlow *vf = new DocVhdlFlow(this);
@@ -5710,6 +5818,9 @@ int DocPara::handleCommand(const QCString &cmdName)
     case CMD_DIAFILE:
       handleDiaFile(cmdName);
       break;
+    case CMD_EXTIMAGEFILE:
+      handleExtImageFile(cmdName);
+      break;
     case CMD_LINK:
       handleLink(cmdName,FALSE);
       break;
diff --git a/src/docparser.h b/src/docparser.h
index 3dc3d84..544f654 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -132,7 +132,8 @@ class DocNode
                 Kind_HtmlBlockQuote = 49,
                 Kind_VhdlFlow       = 50,
                 Kind_ParBlock       = 51,
-                Kind_DiaFile        = 52
+                Kind_DiaFile        = 52,
+                Kind_ExtImageFile   = 53
               };
     /*! Creates a new node */
     DocNode() : m_parent(0), m_insidePre(FALSE) {}
@@ -765,6 +766,30 @@ class DocDiaFile : public CompAccept<DocDiaFile>, public DocNode
     QCString  m_context;
 };
 
+/** Node representing an external converted image file */
+class DocExtImageFile : public CompAccept<DocExtImageFile>, public DocNode
+{
+  public:
+    DocExtImageFile(DocNode *parent,const QCString &name,const QCString &context);
+    void parse();
+    Kind kind() const          { return Kind_DiaFile; }
+    QCString name() const      { return m_name; }
+    QCString file() const      { return m_file; }
+    QCString relPath() const   { return m_relPath; }
+    bool hasCaption() const    { return !m_children.isEmpty(); }
+    QCString width() const     { return m_width; }
+    QCString height() const    { return m_height; }
+    QCString context() const   { return m_context; }
+    void accept(DocVisitor *v) { CompAccept<DocExtImageFile>::accept(this,v); }
+  private:
+    QCString  m_name;
+    QCString  m_file;
+    QCString  m_relPath;
+    QCString  m_width;
+    QCString  m_height;
+    QCString  m_context;
+};
+
 /** Node representing a VHDL flow chart */
 class DocVhdlFlow : public CompAccept<DocVhdlFlow>, public DocNode
 {
@@ -1117,6 +1142,7 @@ class DocPara : public CompAccept<DocPara>, public DocNode
     void handleDotFile(const QCString &cmdName);
     void handleMscFile(const QCString &cmdName);
     void handleDiaFile(const QCString &cmdName);
+    void handleExtImageFile(const QCString &cmdName);
     void handleInclude(const QCString &cmdName,DocInclude::Type t);
     void handleLink(const QCString &cmdName,bool isJavaLink);
     void handleCite();
diff --git a/src/docvisitor.h b/src/docvisitor.h
index a444b47..ba68feb 100644
--- a/src/docvisitor.h
+++ b/src/docvisitor.h
@@ -68,6 +68,7 @@ class DocImage;
 class DocDotFile;
 class DocMscFile;
 class DocDiaFile;
+class DocExtImageFile;
 class DocLink;
 class DocCite;
 class DocRef;
@@ -169,6 +170,8 @@ class DocVisitor
     virtual void visitPost(DocMscFile *) = 0;   
     virtual void visitPre(DocDiaFile *) = 0;
     virtual void visitPost(DocDiaFile *) = 0;
+	virtual void visitPre(DocExtImageFile *) = 0;
+	virtual void visitPost(DocExtImageFile *) = 0;
     virtual void visitPre(DocLink *) = 0;
     virtual void visitPost(DocLink *) = 0;
     virtual void visitPre(DocRef *) = 0;
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 8b72f86..25dc32f 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -136,6 +136,7 @@ FileNameDict    *Doxygen::imageNameDict = 0;       // images
 FileNameDict    *Doxygen::dotFileNameDict = 0;     // dot files
 FileNameDict    *Doxygen::mscFileNameDict = 0;     // msc files
 FileNameDict    *Doxygen::diaFileNameDict = 0;     // dia files
+FileNameDict    *Doxygen::extImageFileNameDict = 0;// extern converted image files
 StringDict       Doxygen::namespaceAliasDict(257); // all namespace aliases
 StringDict       Doxygen::tagDestinationDict(257); // all tag locations
 QDict<void>      Doxygen::expandAsDefinedDict(257); // all macros that should be expanded
@@ -201,6 +202,7 @@ void clearAll()
   Doxygen::dotFileNameDict->clear();
   Doxygen::mscFileNameDict->clear();
   Doxygen::diaFileNameDict->clear();
+  Doxygen::extImageFileNameDict->clear();
   Doxygen::formulaDict->clear();
   Doxygen::formulaNameDict->clear();
   Doxygen::tagDestinationDict.clear();
@@ -269,6 +271,8 @@ void statistics()
   Doxygen::mscFileNameDict->statistics();
   fprintf(stderr,"--- diaFileNameDict stats ----\n");
   Doxygen::diaFileNameDict->statistics();
+  fprintf(stderr,"--- extImageFileNameDict stats ----\n");
+  Doxygen::extImageFileNameDict->statistics();
   //fprintf(stderr,"--- g_excludeNameDict stats ----\n");
   //g_excludeNameDict.statistics();
   fprintf(stderr,"--- aliasDict stats ----\n");
@@ -9976,6 +9980,7 @@ void initDoxygen()
   Doxygen::dotFileNameDict = new FileNameDict(257);
   Doxygen::mscFileNameDict = new FileNameDict(257);
   Doxygen::diaFileNameDict = new FileNameDict(257);
+  Doxygen::extImageFileNameDict = new FileNameDict(257);
   Doxygen::memGrpInfoDict.setAutoDelete(TRUE);
   Doxygen::tagDestinationDict.setAutoDelete(TRUE);
   Doxygen::dirRelations.setAutoDelete(TRUE);
@@ -10017,6 +10022,7 @@ void cleanUpDoxygen()
   delete Doxygen::dotFileNameDict;
   delete Doxygen::mscFileNameDict;
   delete Doxygen::diaFileNameDict;
+  delete Doxygen::extImageFileNameDict;
   delete Doxygen::mainPage;
   delete Doxygen::pageSDict;  
   delete Doxygen::exampleSDict;
@@ -10677,6 +10683,18 @@ void searchInputFiles()
   }
   g_s.end();
 
+  g_s.begin("Searching for external converted image files...\n");
+  QStrList &extImageFileList=Config_getList("EXTIMAGEFILE_DIRS");
+  s=extImageFileList.first();
+  while (s)
+  {
+    readFileOrDirectory(s,0,Doxygen::extImageFileNameDict,0,0,
+                        0,0,0,
+                        alwaysRecursive);
+    s=extImageFileList.next();
+  }
+  g_s.end();
+
   g_s.begin("Searching for files to exclude\n");
   QStrList &excludeList = Config_getList("EXCLUDE");
   s=excludeList.first();
diff --git a/src/doxygen.css b/src/doxygen.css
index 2f4bf70..d1c0c01 100644
--- a/src/doxygen.css
+++ b/src/doxygen.css
@@ -1148,6 +1148,11 @@ dl.section dd {
         text-align: center;
 }
 
+.extimagegraph
+{
+        text-align: center;
+}
+
 .caption
 {
 	font-weight: bold;
diff --git a/src/doxygen.h b/src/doxygen.h
index 6f766c0..fc58663 100644
--- a/src/doxygen.h
+++ b/src/doxygen.h
@@ -111,6 +111,7 @@ class Doxygen
     static FileNameDict             *dotFileNameDict;
     static FileNameDict             *mscFileNameDict;
     static FileNameDict             *diaFileNameDict;
+    static FileNameDict             *extImageFileNameDict;
     static QStrList                  tagfileList;
     static MemberNameSDict          *memberNameSDict;
     static MemberNameSDict          *functionNameSDict;
diff --git a/src/extimage.cpp b/src/extimage.cpp
new file mode 100644
index 0000000..eee273d
--- /dev/null
+++ b/src/extimage.cpp
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 2014 by Michael Waeber.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "extimage.h"
+#include "portable.h"
+#include "config.h"
+#include "message.h"
+
+
+void writeExtImageFileFromFile(const char *inFile, const char *outDir,
+                               const char *outFile,ExtImageOutputFormat format)
+{
+  const char* extension="png";
+  if (format==EXTIMAGE_EPS)
+  {
+    extension="eps";
+  }
+  else if (format==EXTIMAGE_PDF)
+  {
+    extension="pdf";
+  }
+  else if (format == EXTIMAGE_SVG)
+  {
+    extension = "svg";
+  }
+  writeExtImageFileFromFile(inFile, outDir, outFile, extension);
+}
+
+void writeExtImageFileFromFile(const char *inFile, const char *outDir,
+                               const char *outFile,const char *extension)
+{
+  // input parameter checks
+  if (!inFile)
+  {
+    // if the file was not found inFile is NULL, error message already
+    // written in DocExtImageFile::parse()
+    return;
+  }
+
+  if(!extension || *extension=='\0')
+      extension=".png";
+
+  // absolute path of output file
+  QCString absOutFile=outDir;
+  absOutFile+=portable_pathSeparator();
+  absOutFile+=outFile;
+
+  // get executable file/script for the converter
+  QStrList &optList = Config_getList("EXTIMAGE_CONVERTER");
+  QCString converter = optList.first();
+  if (!converter || converter.isEmpty())
+  {
+    err("EXTIMAGE_CONVERTER not configured, required for \\\\extimagefile command.\n");
+    return;
+  }
+
+  // build command line arguments
+  QCString args;
+  char *opt = optList.next();
+  while (opt)
+  {
+      args+=opt;
+      args+=" ";
+      opt = optList.next();
+  }
+
+  args+=" -o \"";
+  args += absOutFile;
+  args+=".";
+  args+=extension;
+  args+="\"";
+
+  args+=" -f \"";
+  args+=inFile;
+  args+="\"";
+
+  // run the converter and check its exit code
+  int exitCode;
+  portable_sysTimerStart();
+  exitCode=portable_system(converter,args,FALSE);
+  portable_sysTimerStop();
+  if (exitCode!=0)
+  {
+      err("Problems running the external image converter (see configuration option EXTIMAGE_CONVERTER): "
+          "Command executed: '%s %s', exit code: %d\n", converter, args, exitCode);
+  }
+}
diff --git a/src/extimage.h b/src/extimage.h
new file mode 100644
index 0000000..813b123
--- /dev/null
+++ b/src/extimage.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 2014 by Michael Waeber
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#ifndef _EXTIMAGE_H
+#define _EXTIMAGE_H
+
+enum ExtImageOutputFormat { EXTIMAGE_PNG, EXTIMAGE_EPS, EXTIMAGE_PDF, EXTIMAGE_SVG };
+
+void writeExtImageFileFromFile(const char *inFile,const char *outDir,
+                               const char *outFile,ExtImageOutputFormat format);
+void writeExtImageFileFromFile(const char *inFile,const char *outDir,
+                               const char *outFile,const char *extension);
+
+#endif
+
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index e319a1f..c83f21e 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -29,6 +29,7 @@
 #include "parserintf.h"
 #include "msc.h"
 #include "dia.h"
+#include "extimage.h"
 #include "util.h"
 #include "vhdldocgen.h"
 #include "filedef.h"
@@ -1496,6 +1497,27 @@ void HtmlDocVisitor::visitPost(DocDiaFile *df)
   m_t << "</div>" << endl;
 }
 
+void HtmlDocVisitor::visitPre(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  m_t << "<div class=\"extimagegraph\">" << endl;
+  writeExtImageFile(df->file(),df->relPath(),df->context());
+  if (df->hasCaption())
+  {
+    m_t << "<div class=\"caption\">" << endl;
+  }
+}
+
+void HtmlDocVisitor::visitPost(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  if (df->hasCaption())
+  {
+    m_t << "</div>" << endl;
+  }
+  m_t << "</div>" << endl;
+}
+
 void HtmlDocVisitor::visitPre(DocLink *lnk)
 {
   if (m_hide) return;
@@ -1989,6 +2011,41 @@ void HtmlDocVisitor::writeDiaFile(const QCString &fileName,
   m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl;
 }
 
+void HtmlDocVisitor::writeExtImageFile(const QCString &fileName,
+                                       const QCString &relPath,
+                                       const QCString &)
+{
+  QCString baseName=fileName;
+  QCString inputExt="";
+  int i;
+  if ((i=baseName.findRev('/'))!=-1) // strip path
+  {
+    baseName=baseName.right(baseName.length()-i-1);
+  }
+  if ((i=baseName.find('.'))!=-1) // strip extension
+  {
+    inputExt=baseName.right(baseName.length()-i-1);  
+  }
+  while ((i=baseName.find('.'))!=-1)
+  {
+    baseName.replace(i, 1, "_");
+  }
+  baseName.prepend("extimage_");
+  QCString outDir = Config_getString("HTML_OUTPUT");
+  QCString outExt=mapExtImageFormat(inputExt);
+
+  writeExtImageFileFromFile(fileName,outDir,baseName,outExt);
+
+  if (outExt=="svg")
+  {
+	  m_t << "<object type = \"image/svg+xml\" data = \"" << relPath << baseName << "." << outExt << "\"></object>" << endl;
+  }
+  else
+  {
+      m_t << "<img src=\"" << relPath << baseName << "." << outExt << "\" />" << endl;
+  }
+}
+
 void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName,
                                        const QCString &relPath,
                                        const QCString &)
@@ -2096,3 +2153,34 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
   }
 }
 
+QCString HtmlDocVisitor::mapExtImageFormat(const QCString &inputExt)
+{
+  QString retval="png";  // default is png
+
+  QStrList &format = Config_getList("EXTIMAGE_MAPPING");
+  char *mapping = format.first();
+  while (mapping)
+  {
+    QCString mapStr = mapping;
+    int i;
+    if ((i=mapStr.find('='))!=-1)
+    {
+      QCString ext=mapStr.left(i).stripWhiteSpace().lower();
+      if (!ext.isEmpty() && ext == inputExt)
+      {
+          QCString outFormat=mapStr.mid(i+1).stripWhiteSpace().lower();
+          if (!outFormat.isEmpty())
+          {
+              return outFormat;
+          }
+          else
+          {
+              err("Invalid EXTIMAGE_MAPPING configuration %s\n", mapping);
+          }
+      }
+    }
+	mapping = format.next();
+  }
+
+  return "png";  // default is png
+}
diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h
index 00ae09e..79be13c 100644
--- a/src/htmldocvisitor.h
+++ b/src/htmldocvisitor.h
@@ -110,6 +110,8 @@ class HtmlDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *);
     void visitPost(DocLink *);
     void visitPre(DocRef *);
@@ -153,6 +155,7 @@ class HtmlDocVisitor : public DocVisitor
     void writeDotFile(const QCString &fileName,const QCString &relPath,const QCString &context);
     void writeMscFile(const QCString &fileName,const QCString &relPath,const QCString &context);
     void writeDiaFile(const QCString &fileName,const QCString &relPath,const QCString &context);
+    void writeExtImageFile(const QCString &fileName,const QCString &relPath,const QCString &context);
     void writePlantUMLFile(const QCString &fileName,const QCString &relPath,const QCString &context);
 
     void pushEnabled();
@@ -161,6 +164,8 @@ class HtmlDocVisitor : public DocVisitor
     void forceEndParagraph(DocNode *n);
     void forceStartParagraph(DocNode *n);
 
+    QCString mapExtImageFormat(const QCString &inputExt);
+
     //--------------------------------------
     // state variables
     //--------------------------------------
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index af1a5fd..b503079 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -28,6 +28,7 @@
 #include "parserintf.h"
 #include "msc.h"
 #include "dia.h"
+#include "extimage.h"
 #include "cite.h"
 #include "filedef.h"
 #include "config.h"
@@ -1194,6 +1195,19 @@ void LatexDocVisitor::visitPost(DocDiaFile *df)
   if (m_hide) return;
   endDiaFile(df->hasCaption());
 }
+
+void LatexDocVisitor::visitPre(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  startExtImageFile(df->file(),df->width(),df->height(),df->hasCaption());
+}
+
+void LatexDocVisitor::visitPost(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  endExtImageFile(df->hasCaption());
+}
+
 void LatexDocVisitor::visitPre(DocLink *lnk)
 {
   if (m_hide) return;
@@ -1846,6 +1860,83 @@ void LatexDocVisitor::writeDiaFile(const QCString &baseName)
   m_t << "\\end{DoxyImageNoCaption}\n";
 }
 
+
+void LatexDocVisitor::startExtImageFile(const QCString &fileName,
+                                        const QCString &width,
+                                        const QCString &height,
+                                        bool hasCaption)
+{
+  QCString baseName=fileName;
+  int i;
+  if ((i=baseName.findRev('/'))!=-1)
+  {
+    baseName=baseName.right(baseName.length()-i-1);
+  }
+  while ((i=baseName.find('.'))!=-1)
+  {
+    baseName.replace(i, 1, "_");
+  }
+  baseName.prepend("extimage_");
+
+  QCString outDir = Config_getString("LATEX_OUTPUT");
+  ExtImageOutputFormat format =
+      Config_getBool("USE_PDFLATEX")
+      ? EXTIMAGE_PDF
+      : EXTIMAGE_EPS;
+  writeExtImageFileFromFile(fileName,outDir,baseName,format);
+  if (hasCaption)
+  {
+    m_t << "\n\\begin{DoxyImage}\n";
+  }
+  else
+  {
+    m_t << "\n\\begin{DoxyImageNoCaption}\n"
+           "  \\mbox{";
+  }
+  m_t << "\\includegraphics";
+  if (!width.isEmpty())
+  {
+    m_t << "[width=" << width << "]";
+  }
+  else if (!height.isEmpty())
+  {
+    m_t << "[height=" << height << "]";
+  }
+  else
+  {
+    m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
+  }
+  m_t << "{" << baseName;
+  //if (Config_getBool("USE_PDFLATEX"))
+  //{
+  //  m_t << ".pdf";
+  //}
+  //else
+  //{
+  //  m_t << ".eps";
+  //}
+  m_t << "}";
+
+  if (hasCaption)
+  {
+    m_t << "\n\\caption{";
+  }
+}
+
+void LatexDocVisitor::endExtImageFile(bool hasCaption)
+{
+  if (m_hide) return;
+  m_t << "}\n"; // end caption or mbox
+  if (hasCaption)
+  {
+    m_t << "\\end{DoxyImage}\n";
+  }
+  else
+  {
+    m_t << "\\end{DoxyImageNoCaption}\n";
+  }
+}
+
 void LatexDocVisitor::writePlantUMLFile(const QCString &baseName)
 {
   QCString shortName = baseName;
diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h
index 64560b9..2b7bc41 100644
--- a/src/latexdocvisitor.h
+++ b/src/latexdocvisitor.h
@@ -112,6 +112,8 @@ class LatexDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *lnk);
     void visitPost(DocLink *);
     void visitPre(DocRef *ref);
@@ -176,6 +178,9 @@ class LatexDocVisitor : public DocVisitor
                       const QCString &height, bool hasCaption);
     void endDiaFile(bool hasCaption);
     void writeDiaFile(const QCString &fileName);
+    void startExtImageFile(const QCString &fileName,const QCString &width,
+                           const QCString &height, bool hasCaption);
+    void endExtImageFile(bool hasCaption);
     void writePlantUMLFile(const QCString &fileName);
 
     void pushEnabled();
diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in
index 703b885..ae406cf 100644
--- a/src/libdoxygen.pro.in
+++ b/src/libdoxygen.pro.in
@@ -80,6 +80,7 @@ HEADERS      =	arguments.h \
 		message.h \
                 msc.h \
                 dia.h \
+                extimage.h \
 		namespacedef.h \
                 objcache.h \
 		outputgen.h \
@@ -179,6 +180,7 @@ SOURCES      =	arguments.cpp \
 		message.cpp \
                 msc.cpp \
                 dia.cpp \
+                extimage.cpp \
 		namespacedef.cpp \
                 objcache.cpp \
 		outputgen.cpp \
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index 1fe5409..c4e4f39 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -760,6 +760,14 @@ void ManDocVisitor::visitPost(DocDiaFile *)
 {
 }
 
+void ManDocVisitor::visitPre(DocExtImageFile *)
+{
+}
+
+void ManDocVisitor::visitPost(DocExtImageFile *)
+{
+}
+
 void ManDocVisitor::visitPre(DocLink *)
 {
   if (m_hide) return;
diff --git a/src/mandocvisitor.h b/src/mandocvisitor.h
index a5906d0..2d20e46 100644
--- a/src/mandocvisitor.h
+++ b/src/mandocvisitor.h
@@ -109,6 +109,8 @@ class ManDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *lnk);
     void visitPost(DocLink *);
     void visitPre(DocRef *ref);
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index c636cdf..1282db2 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -368,6 +368,8 @@ public:
   void visitPost(DocMscFile *);
   void visitPre(DocDiaFile *);
   void visitPost(DocDiaFile *);
+  void visitPre(DocExtImageFile *);
+  void visitPost(DocExtImageFile *);
   void visitPre(DocLink *);
   void visitPost(DocLink *);
   void visitPre(DocRef *);
@@ -1160,6 +1162,19 @@ void PerlModDocVisitor::visitPost(DocDiaFile *)
 #endif
 }
 
+void PerlModDocVisitor::visitPre(DocExtImageFile *)
+{
+#if 0
+  m_output.add("<extimage name=\""); m_output.add(df->file()); m_output.add("\">");
+#endif
+}
+
+void PerlModDocVisitor::visitPost(DocExtImageFile *)
+{
+#if 0
+  m_output.add("</extimage>");
+#endif
+}
 
 void PerlModDocVisitor::visitPre(DocLink *lnk)
 {
diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h
index 1d384b1..12815e7 100644
--- a/src/printdocvisitor.h
+++ b/src/printdocvisitor.h
@@ -520,6 +520,16 @@ class PrintDocVisitor : public DocVisitor
       indent_post();
       printf("</diafile>\n");
     }
+    void visitPre(DocExtImageFile *df)
+    {
+      indent_pre();
+      printf("<extimagefile src=\"%s\">\n",df->name().data());
+    }
+    void visitPost(DocExtImageFile *)
+    {
+      indent_post();
+      printf("</extimagefile>\n");
+    }
     void visitPre(DocLink *lnk)
     {
       indent_pre();
diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp
index a11e42f..1445ab0 100644
--- a/src/rtfdocvisitor.cpp
+++ b/src/rtfdocvisitor.cpp
@@ -31,6 +31,7 @@
 #include "parserintf.h"
 #include "msc.h"
 #include "dia.h"
+#include "extimage.h"
 #include "filedef.h"
 #include "config.h"
 #include "htmlentity.h"
@@ -1094,6 +1095,22 @@ void RTFDocVisitor::visitPost(DocDiaFile *)
   popEnabled();
 }
 
+void RTFDocVisitor::visitPre(DocExtImageFile *df)
+{
+  DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocExtImageFile)}\n");
+  writeExtImageFile(df->file());
+
+  // hide caption since it is not supported at the moment
+  pushEnabled();
+  m_hide=TRUE;
+}
+
+void RTFDocVisitor::visitPost(DocExtImageFile *)
+{
+  DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocExtImageFile)}\n");
+  popEnabled();
+}
+
 void RTFDocVisitor::visitPre(DocLink *lnk)
 {
   if (m_hide) return;
@@ -1717,6 +1734,32 @@ void RTFDocVisitor::writeDiaFile(const QCString &fileName)
   m_lastIsPara=TRUE;
 }
 
+void RTFDocVisitor::writeExtImageFile(const QCString &fileName)
+{
+  QCString baseName=fileName;
+  int i;
+  if ((i=baseName.findRev('/'))!=-1)
+  {
+    baseName=baseName.right(baseName.length()-i-1);
+  }
+  // not all programs are able to convert from foo.bar to foo.bar.png (as done
+  // for dia and msc). We use another pattern here: foo.bar -> foo_bar.png
+  while ((i = baseName.find('.')) != -1)
+  {
+    baseName.replace(i, 1, "_");
+  }
+  QCString outDir = Config_getString("RTF_OUTPUT");
+  writeExtImageFileFromFile(fileName, outDir, baseName, EXTIMAGE_PNG);
+  if (!m_lastIsPara) m_t << "\\par" << endl;
+  m_t << "{" << endl;
+  m_t << rtf_Style_Reset;
+  m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
+  m_t << baseName << ".png";
+  m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
+  m_t << "}" << endl;
+  m_lastIsPara=TRUE;
+}
+
 void RTFDocVisitor::writePlantUMLFile(const QCString &fileName)
 {
   QCString baseName=fileName;
diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h
index c50802d..fc45fae 100644
--- a/src/rtfdocvisitor.h
+++ b/src/rtfdocvisitor.h
@@ -109,6 +109,8 @@ class RTFDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *);
     void visitPost(DocLink *);
     void visitPre(DocRef *ref);
@@ -155,6 +157,7 @@ class RTFDocVisitor : public DocVisitor
     void writeDotFile(const QCString &fileName);
     void writeMscFile(const QCString &fileName);
     void writeDiaFile(const QCString &fileName);
+    void writeExtImageFile(const QCString &fileName);
     void writePlantUMLFile(const QCString &fileName);
 
     //--------------------------------------
diff --git a/src/textdocvisitor.h b/src/textdocvisitor.h
index b17065d..c322777 100644
--- a/src/textdocvisitor.h
+++ b/src/textdocvisitor.h
@@ -108,6 +108,8 @@ class TextDocVisitor : public DocVisitor
     void visitPost(DocMscFile *) {}
     void visitPre(DocDiaFile *) {}
     void visitPost(DocDiaFile *) {}
+    void visitPre(DocExtImageFile *) {}
+    void visitPost(DocExtImageFile *) {}
     void visitPre(DocLink *) {}
     void visitPost(DocLink *) {}
     void visitPre(DocRef *) {}
diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp
index f2da28c..6798492 100644
--- a/src/xmldocvisitor.cpp
+++ b/src/xmldocvisitor.cpp
@@ -771,6 +771,18 @@ void XmlDocVisitor::visitPost(DocDiaFile *)
   m_t << "</diafile>" << endl;
 }
 
+void XmlDocVisitor::visitPre(DocExtImageFile *df)
+{
+  if (m_hide) return;
+  m_t << "<extimagefile name=\"" << df->file() << "\">";
+}
+
+void XmlDocVisitor::visitPost(DocExtImageFile *)
+{
+  if (m_hide) return;
+  m_t << "</extimagefile>" << endl;
+}
+
 void XmlDocVisitor::visitPre(DocLink *lnk)
 {
   if (m_hide) return;
diff --git a/src/xmldocvisitor.h b/src/xmldocvisitor.h
index 3e2236c..495aeb0 100644
--- a/src/xmldocvisitor.h
+++ b/src/xmldocvisitor.h
@@ -111,6 +111,8 @@ class XmlDocVisitor : public DocVisitor
     void visitPost(DocMscFile *);
     void visitPre(DocDiaFile *);
     void visitPost(DocDiaFile *);
+    void visitPre(DocExtImageFile *);
+    void visitPost(DocExtImageFile *);
     void visitPre(DocLink *);
     void visitPost(DocLink *);
     void visitPre(DocRef *);
diff --git a/winbuild/Doxygen.vcproj b/winbuild/Doxygen.vcproj
index 882e514..4f1b5e8 100644
--- a/winbuild/Doxygen.vcproj
+++ b/winbuild/Doxygen.vcproj
@@ -635,6 +635,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\extimage.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\src\diagram.cpp"
 				>
 			</File>
@@ -2307,6 +2311,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\extimage.h"
+				>
+			</File>
+			<File
 				RelativePath="..\src\diagram.h"
 				>
 			</File>
