Fig 1. dgrm.net can open diagrams from PNG images
dgrm.net - is a diagram editor, with an eye to transformation into a knowledge map tool.
Distinctive features:
- asceticism,
- works on phones,
- open source.
In the development process, interesting moments appear. Today we will talk about reading data from PNG. The source code for use in your projects is attached.
Why open diagrams from PNG images?
Developer-made user interfaces are notorious for being weird. Perhaps the idea of using images as project files is just that. At least the approach is original.
All editors use their own project files. But this is inconvenient:
- no previews,
- when sending an image, you must also send the source.
It is more convenient to have a picture of the diagram, which can be edited if necessary.
Looking at Figure 1, we can assume that steganography, or image recognition, is being used. It's actually much simpler, and without hacks - the PNG format supports storing additional information, such as a timestamp, author's name, or any other.
dgrm.net writes JSON with diagram data to png files.
PNG Chunks
Here is the PNG specification: “Portable Network Graphics (PNG) Specification”.
Highlight:
- png files are made up of blocks called chunks,
- you can add your own chunks to the file.
Fig 2. Structure of one PNG chunk
For custom data you can think of any chunk name (for example “dgRm”):
- The length of the name is strictly 4 Latin letters;
- Letter case matters. For custom chunks, put all letters in lowercase, and the 3rd in uppercase.
Thus, to store a JSON string inside a PNG file, you need to add your own chunk to the file.
Read/Write PNG chunks in JavaScript in the browser
Read a chunk
Chunks follow each other, the required chunk is searched by enumeration.
Chunk search algorithm (listing 1):
- take the name of the first chunk
- if the name does not match the search one
- take the length of the chunk (the first 4 bytes see Fig. 2)
- knowing the length of the chunk, move the cursor to the beginning of the next chunk
- repeat 1 and 2 until we find the desired chunk or 'IEND' (end of file).
/**
* @param {ArrayBuffer} pngData
* @param {number} chunkNameUint32 chunk name as Uint32
* @returns {DataView | null} chunk data
*/
function chunkGet(pngData, chunkNameUint32) {
const dataView = new DataView(pngData, 8); // 8 byte - png signature
let chunkPosition = 0;
let chunkUint = dataView.getUint32(4);
let chunkLenght;
while (chunkUint !== 1229278788) { // last chunk 'IEND'
chunkLenght = dataView.getUint32(chunkPosition);
if (chunkUint === chunkNameUint32) {
return new DataView(pngData, chunkPosition + 16, chunkLenght);
}
chunkPosition = chunkPosition + 12 + chunkLenght;
chunkUint = dataView.getUint32(chunkPosition + 4);
}
return null;
}
Listing 1. Chunk lookup function
Quick reference:
JavaScript has an interesting way of working with binary data.
Quote:
The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer. …
You cannot directly manipulate the contents of an ArrayBuffer
developer.mozilla.org
To read the data, you can wrap it in a DataView. The DataView allows you to read the data in any position as a number (using the getInt8(), getUint32() methods, etc.).
Write a chunk
To write a chunk, you need to insert a new chunk into the chain. If a chunk with the given name already exists, it must be replaced.
See implementation on GitHub - the chunkSet function.
Source code
Functions for working with PNG chunks are located in one file. The file has no dependencies, so you can simply copy it into your project.
Usage example:
// Write a chunk, new blob output
const newPngBlob = await pngChunkSet(
// png-image
pngBlob,
// chunk name
'dgRm',
// chunk value: string as a bytes
new TextEncoder().encode('...'));
// read a chuk
const dgrmChunkVal = await pngChunkGet(newPngBlob, 'dgRm');
const str = new TextDecoder().decode(dgrmChunkVal);
Listing 2. Calling functions to write and read PNG chunks
Other articles about dgrm.net
- JavaScript SVG diagram editor 3.9 KB (open source library)
- JavaScript diagram editor that renders diagrams from PNG images (open source)
- JavaScript text editor for SVG
- Flowchart editor UI
- JavaScript: Zoom like in maps for SVG/HTML
Top comments (0)