Edytowalne diagramy w plikach PNG utworzone w diagrams.net (dawniej draw.io)

Istnieje bardzo fajne, darmowe i intensywnie rozwijane narzędzie do rysowania diagramów i schematów - diagrams.net (dawniej draw.io).

Najprostszym sposobem korzystania z tego narzędzia jest praca w aplikacji webowej dostępnej przez przeglądarkę. Dostępna jest też opcja desktopowa, która jest dostępna na systemy Windows, Linux i MacOs.

Przykładowy diagram może wyglądać tak:

Przykładowy diagram

Często zachodzi potrzeba aktualizacji diagramu, który stworzyliśmy. Standardowo, kiedy zapisujemy diagram z tego narzędzia zapisuje się plik XML (z rozszerzeniem .drawio). Struktura XML opisuje poszczególne elementy i pozycje na diagramie. Dla przykładowego diagramu powyżej zawartość pliku XML wygląda tak:

1<mxfile host="app.diagrams.net" modified="2022-10-05T20:33:03.896Z" agent="5.0 (X11)" etag="eMnXSxJ-HEQeEW0VcJsl" version="20.4.0" type="device"><diagram id="btIxxuHiHrE_vsZ1PSLe" name="Page-1">7Vjbjts2EP0aP9qgqIu9j7G8SQtsii1cpOkjLdESs5SoUvTaytd3KFEXWrK7RjZJga4Aw+IhZ8gZDs8hNHPD7PRBkiL9KGLKZxjFp5m7mWHsrDCCP41UBkGu3yCJZLHBemDLvtJ2oEEPLKalNVAJwRUrbDASeU4jZWFESnG0h+0Ft2ctSEJHwDYifIz+yWKVNujKRz3+C2VJ2s7sINOTkXawAcqUxOI4gNz7mRtKIVTzlp1CynX22rw0du8v9HYLkzRXLzHIUPAr+f0khVN98tYf5g8J+TR3zdpU1QZMY4jfNIVUqUhETvh9j66lOOQx1V4RtPoxD0IUADoAfqFKVWYzyUEJgFKVcdPbzKknuhiKgUpxkBG9sv62JIhMqLoyDncJh1KlIqNKVmAnKSeKPdvrIKZkkm5cn1V4MYm9IclB4/eZ8IOZaX2oJhP/QHZwgKxkEc6SHN4jyA2VADxTqRgU6DvTkbE4bvaFluwr2dX+9M4UguWqjsVfz/xNl3jtgJ5mE6fHGPc1O9ySy/UzzqvxPkcLU2AvTrTx9ajX3jvCnm0h9vsS9vt8Y7oVTO2V2H3RBAFBcRLRFIiAyjMO8X4jmVliyJmO3OB/VIXBH8FI5C2+oWUkWaGYyJvupoM329gAAYcErveijqff7+Dvg2g75mV9VN7BACcoTn0nvCXmv/ay6wHfrBb7bSfEuzs3AKyZ2YZj9txBfuOsDhGc+ZuB7XBcuwR5zdmt0TrXojVeIsGFtLzMsBvVz5Stb2+LlZ+pXJyHif/tODuDOjXHf3CMB0dXz2ZI0NHtmJRpx5vHlClaFqSmtyOopzZgnIddtC5aue+XPuClkuKJDnsC1/FDM8UA39ePtkhJXbHZKdHCvIi8RVFXLp6iFDg05D5myqzbJo41WkAKQ1T/dHWEgDm6ZXAbW9qgAZwzcArDE+CkS3vumtnOue8i041E5iJ5BYYDK7t57G8BuNX6dHgDWKGbZQSahp1uUBV/pCofyRPVE9dhVlnHXz9W3WFaWX3W9gu/bf5l3NWNzclqVcMW0CuDbOmqHOzjq1wV8AuvCt73uSrcJj90XqaQ75H8bMVeHSF4gLdVqWj2pkT/YyUa3mrHStSfZKfVm62tN4NTWxfKmkRPSW3WakoucjoWJgcFzhpdkZ+RwhAZtUqIJgVt46M7ZyxF1++0rWigCXU5x5aXRAxPqdh/QtkGGLbl7hXkzcO2vt1N6Js3pW/4m/XtNip8bKUM7XTRyDdSfCPFa6To/SRSXIUr7y54TVJcusFyhd9I8eeRoot+HCtCs/8Y2HzO6L+puvf/AA==</diagram></mxfile>

Te dziwnie wyglądające znaczki to po prostu skompresowana treść diagramu. Można go zapisać również bez kompresji:

 1<?xml version="1.0" encoding="UTF-8"?>
 2<mxfile host="app.diagrams.net" modified="2022-10-05T20:44:14.068Z" agent="5.0 (X11)" etag="7esYecNTgJvcBK1ZEVuF" version="20.4.0" type="browser">
 3  <diagram id="btIxxuHiHrE_vsZ1PSLe" name="Page-1">
 4    <mxGraphModel dx="1820" dy="1035" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
 5      <root>
 6        <mxCell id="0" />
 7        <mxCell id="1" parent="0" />
 8        <mxCell id="m06IaQxro1yV4BG-LgaV-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="m06IaQxro1yV4BG-LgaV-1" target="m06IaQxro1yV4BG-LgaV-2">
 9          <mxGeometry relative="1" as="geometry" />
10        </mxCell>
11        <mxCell id="m06IaQxro1yV4BG-LgaV-6" value="Buy" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="m06IaQxro1yV4BG-LgaV-3">
12          <mxGeometry x="-0.3" relative="1" as="geometry">
13            <mxPoint x="24" as="offset" />
14          </mxGeometry>
15        </mxCell>
16        <object placeholders="1" c4Name="Client" c4Type="Person" c4Description="" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="m06IaQxro1yV4BG-LgaV-1">
17          <mxCell style="html=1;fontSize=11;dashed=0;whitespace=wrap;fillColor=#083F75;strokeColor=#06315C;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;" vertex="1" parent="1">
18            <mxGeometry x="60" y="60" width="200" height="180" as="geometry" />
19          </mxCell>
20        </object>
21        <mxCell id="m06IaQxro1yV4BG-LgaV-5" value="Make a payment" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="m06IaQxro1yV4BG-LgaV-2" target="m06IaQxro1yV4BG-LgaV-4">
22          <mxGeometry relative="1" as="geometry" />
23        </mxCell>
24        <object placeholders="1" c4Name="e-shop" c4Type="Software System" c4Description="" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="m06IaQxro1yV4BG-LgaV-2">
25          <mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#1061B0;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0D5091;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
26            <mxGeometry x="420" y="90" width="240" height="120" as="geometry" />
27          </mxCell>
28        </object>
29        <object placeholders="1" c4Name="Payment broker" c4Type="Software System" c4Description="" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="m06IaQxro1yV4BG-LgaV-4">
30          <mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
31            <mxGeometry x="420" y="300" width="240" height="120" as="geometry" />
32          </mxCell>
33        </object>
34      </root>
35    </mxGraphModel>
36  </diagram>
37</mxfile>

No dobrze. Jednak zazwyczaj zależy nam, aby przekazać komuś diagram w formie graficznej, a nie zmuszać do załadowania pliku XML do aplikacji w celu podglądu. Na szczęście aplikacja diagrams.net umożliwia zapis w formatach graficznych, między innymi w formacie PNG.

Niedawno dowiedziałem się, że wygenerowany z tego narzędzia plik PNG można załadować do aplikacji i... edytować wszystkie elementy diagramu!

Zacząłem się zastanawiać, cóż to za magia...

Chyba za dużo ostatnio artykułów czytałem i pierwsze myśli skierowałem w stronę zaawansowanego AI lub OCR.
Po chwili, kiedy emocje już opadły wpadłem na pomysł, że w metadanych pliku mógł zostać dodany diagram w postaci XML.
I to był strzał w 10! Zawartości XML'a nie zobaczysz w standardowych metadanych pliku, które można podejrzeć w oknie systemowym.

Plik PNG składa się z nagłówka (8 bajtów) oraz fragmentów informacji (tzw. "chunk" 1) opisujących różne informacje o pliku PNG. Jednym z typów "chunk" jest tEXt, który przechowuje wartość tekstową w postaci mapy klucz-wartość. To właśnie tutaj aplikacja diagrams.net przechowuje plik XML, który umożliwia edycję diagramu.

Możecie załadować powyższy przykładowy diagram na stronę, która pokazuje budowę PNG. Wygląda to tak:

Podgląd fragmentów obrazu PNG

Załączony przykładowy diagram oczywiście możecie załadować do aplikacji diagrams.net i empirycznie potwierdzić, że edycja diagramu po załadowaniu PNG działa.

Mam nadzieję, że komuś ta wiedza się przyda i ułatwi współpracę nad diagramami w Waszych zespołach.

Tłumaczenia: