[HOWTO] Convert Images to Enterprise Architect Model Images

We wanted to use the official cisco network topology icons (B/W: EPS (7.6 MB) | JPG (4 MB)) in Enterprise Architect to associate them with elements. To avoid importing these icons manually one by one we automated this process by creating model images reference data using PowerShell. The model images reference data can then be imported into Enterprise Architect. Below I’ll show you how it works.

The example is based on the following versions of Enterprise Architect and PowerShell.
EA Version: 14.0.1423
PowerShell Version: 5

Script for Conversion of Images to Model Images Ref Data

The PowerShell script takes two parameters; the path to the directory that contains the images and an optional parameter to specify the name of the output file. It iterates over all files in the images directory, converts every file to PNG and then converts the byte array of the PNG to a base 64 string. The base 64 string gets added as inner text to the Image column tag. At the end the generated XML will be saved to the images directory.

#Requires -Version 5.0

PARAM
(
    [Parameter(Mandatory=$true)]
    [string] $PathToImagesDirectory
    ,
    [Parameter(Mandatory=$false)]
    [string] $ImageLibraryFileName = "image-library.xml"
)

Add-Type -Assembly System.Drawing;

# variables
$xmlVersion = "1.0";
$xmlEncoding = [System.Text.Encoding]::GetEncoding(1252);
$exporter = "EA.25";

# load images
$images = Get-ChildItem -Path $PathToImagesDirectory;

# create XML document
$xmlDoc = [System.Xml.XmlDocument]::new();
$xmlDeclaration = $xmlDoc.CreateXmlDeclaration($xmlVersion, $xmlEncoding.HeaderName, $null);
$null = $xmlDoc.AppendChild($xmlDeclaration);

$rootNode = $xmlDoc.CreateNode("element", "RefData", $null);
$rootNode.SetAttribute("version", $xmlVersion);
$rootNode.SetAttribute("exporter", $exporter);
$rootNode.SetAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");
$null = $xmlDoc.AppendChild($rootNode);

$dataSet = $xmlDoc.CreateNode("element", "DataSet", $null);
$dataSet.SetAttribute("name", "Model Images");
$dataSet.SetAttribute("table", "t_image");
$dataSet.SetAttribute("filter", "Name='#Name#'");
$dataSet.SetAttribute("stoplist", ";ImageID;");
$null = $rootNode.AppendChild($dataSet);

foreach ($img in $images)
{
    $dataRow = $xmlDoc.CreateNode("element", "DataRow", $null);

    # convert to PNG
    try
    {
        $bitmap = [System.Drawing.Bitmap]::FromFile($img.FullName);
    }
    catch
    {
        # ignore files that do not have a valid image format
        continue;
    }
    $memoryStream = [System.IO.MemoryStream]::new();

    try
    {
        $bitmap.Save($memoryStream, [System.Drawing.Imaging.ImageFormat]::Png);
        $bytes = $memoryStream.ToArray();
    }
    finally
    {
        $memoryStream.Close();
    }

    $arrayLength = (4.0d/3.0d) * $bytes.Length;
    if ($arrayLength % 4 -ne 0)
    {
        $arrayLength += 4 - $arrayLength % 4;
    }

    $result = new-object char[] $arrayLength;
    $null = [convert]::ToBase64CharArray($bytes, 0, $bytes.Length, $result, 0);
    $result = [convert]::ToBase64String($bytes, [System.Base64FormattingOptions]::InsertLineBreaks);

    $column1 = $xmlDoc.CreateNode("element", "Column", $null);
    $column1.SetAttribute("name", "ImageID");

    $column2 = $xmlDoc.CreateNode("element", "Column", $null);
    $column2.SetAttribute("name", "Name");
    $column2.SetAttribute("value", $img.Name);

    $column3 = $xmlDoc.CreateNode("element", "Column", $null);
    $column3.SetAttribute("name", "Type");
    $column3.SetAttribute("value", "Bitmap");

    $column4 = $xmlDoc.CreateNode("element", "Column", $null);
    $column4.SetAttribute("name", "Image");
    $null = $column4.SetAttribute("dt", "urn:schemas-microsoft-com:datatypes", "bin.base64");
    $column4.InnerText = $result;

    $null = $dataRow.AppendChild($column1);
    $null = $dataRow.AppendChild($column2);
    $null = $dataRow.AppendChild($column3);
    $null = $dataRow.AppendChild($column4);
    $null = $dataSet.AppendChild($dataRow);
}

# initialize XML writer
$xmlWriterSettings = [System.Xml.XmlWriterSettings]::new();
$xmlWriterSettings.Encoding = $xmlEncoding;
$xmlWriterSettings.ConformanceLevel   = [System.Xml.ConformanceLevel]::Document;
$xmlWriterSettings.OmitXmlDeclaration = $false;
$xmlWriterSettings.CloseOutput        = $true;
$xmlWriterSettings.Indent             = $true;
$xmlWriterSettings.IndentChars        = "    ";
$xmlWriterSettings.NewLineHandling    = [System.Xml.NewLineHandling]::Replace;

$path = Join-Path -Path $PathToImagesDirectory -ChildPath $ImageLibraryFileName;

$sw = [System.IO.File]::CreateText($path);
$xmlWriter = [System.Xml.XmlWriter]::Create($sw, $xmlWriterSettings);

# save XML
try
{
    $xmlDoc.WriteContentTo($xmlWriter);
}
finally
{
    $xmlWriter.Close();
}

#
# Copyright 2018 d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

XML Output

The XML created by the above script looks as follows. The following XML file just contains a single image however the script can handle multiple images.

<?xml version="1.0" encoding="Windows-1252"?>
<RefData version="1.0" exporter="EA.25" xmlns:dt="urn:schemas-microsoft-com:datatypes">
    <DataSet name="Model Images" table="t_image" filter="Name='#Name#'" stoplist=";ImageID;">
        <DataRow>
            <Column name="ImageID" />
            <Column name="Name" value="100baset hub.jpg" />
            <Column name="Type" value="Bitmap" />
            <Column name="Image" dt:dt="bin.base64">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
7vI9vAAAAABJRU5ErkJggg==</Column>
        </DataRow>
    </DataSet>
</RefData>

Import Model Images Ref Data into Enterprise Architect

The reference data can then be imported into EA as follows.

  1. Open Enterprise Architect
  2. Create a new or open an existing Enterprise Architect project
  3. Navigate to Configure tab
  4. Click on Transfer and select Import Reference Data...
  5. Click Select File button on the top right corner and browse for the before created XML file, which is located in the same directory as the images
  6. Click Import
  7. To verify and manage the model images click on Images
  8. Now you can see the available images including the ones that got imported

Trackbacks

  1. […] is a follow-up to the blog post [HOWTO] Convert Images to Enterprise Architect Model Images. As already described there, we wanted to use the official cisco network topology icons (B/W: EPS […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: