JavaScript редактор диаграмм, который открывает диаграммы из PNG картинок (open source)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Рис 1. dgrm.net умеет открывать диаграммы из PNG картинок
Рис 1. dgrm.net умеет открывать диаграммы из PNG картинок

dgrm.net | GitHub

<< предыдущая статья

dgrm.net - это редактор диаграмм, с прицелом на трансформацию в карту знаний.

Отличительные особенности:

  • аскетичность,

  • работает на телефонах (одно из немногих web-решений),

  • открытый исходный код.

В процессе разработки появляются интересные моменты. Статья про один из таких моментов: чтение данных из PNG. Исходный код для использования в своих проектах прилагается.

Зачем открывать диаграммы из PNG изображений

Пользовательские интерфейсы сделанные разработчиками славятся своей самобытностью. Возможно, идея использовать изображения в качестве файлов проекта как раз этот случай. Как минимум подход оригинальный.

Все редакторы используют свои файлы проекта. Но это же неудобно:

  • нет превьюшек,

  • при пересылке изображения, надо еще и исходник пересылать.

Удобнее иметь картинку диаграммы, которую при необходимости можно отредактировать.

Глядя на рисунок 1 можно предположить что используется стеганография, или распознавание изображений. На самом деле гораздо проще, и без хаков - формат PNG поддерживает хранение дополнительной информации, например метки времени, имени автора, или любой другой.

dgrm.net записывает в png-файлы JSON с данными диаграммы.

PNG Chunks

Формат PNG хорошо описан на Хабре в статье “PNG — not GIF!”.

Основной момент:

  • png-файлы состоят из блоков, которые называются chunk-и,

  • в файл можно добавлять свои chunk-и.

Рис 2. Структура одного chunk-a PNG (источник “PNG — not GIF!”)
Рис 2. Структура одного chunk-a PNG (источник “PNG — not GIF!”)

Для своих данных имя chunk-a (например “dgRm”):

  • Можно придумать любое, лишь бы оно не было зарезервировано;

  • Длина имени строго 4 латинских буквы;

  • Регистр букв имеет значение. Для самодельных chunk-ов ставьте все буквы в нижнем регистре, а 3-ю в верхнем.

Таким образом, для хранения строки JSON внутри файла PNG нужно добавить в файл свой chunk.

Чтение/запись PNG chunk-ов на JavaScript в браузере

Чтение chunk-а

Chunk-и следуют друг за другом, нужный chunk находится перебором.

Алгоритм поиска chunk-а (листинг 1):

  1. берем название первого chunk

  2. если название не совпадает с искомым
    a. берем длину chunk (первые 4 байта см. рис 2)
    b. зная длину chunk смещаем курсор на начало следующего chunk

  3. повторяем 1 и 2 пока не найдем нужный chunk или 'IEND' (конец файла).

/**
 * @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;
}

Листинг 1. Функция поиска chunk-а

Краткая справка:

В JavaScript интересный способ работы с бинарными данными.

Цитата:
Объект ArrayBuffer используется для работы с бинарными данными. Он представляет собой ссылку на поток "сырых" двоичных данных, однако работать с ними напрямую возможности не даёт.
developer.mozilla.org

Для чтения данных можно обернуть их в DataView. DataView позволяет прочитать данные в любой позиции в виде числа (с помощью методов getInt8(), getUint32() и др.).

Запись chunk-а

Для записи chunk-а, нужно вставить новый chunk в цепочку. Если chunk с данным именем уже есть - его нужно заменить.

Реализацию можно посмотреть на GitHub - функция chunkSet.

Исходный код

Функции работы с PNG chunk-ами вынесены в один файл. У файла нет зависимостей, поэтому его можно просто скопировать в свой проект.
png-chunk-utils.js

Пример использования:

// Запись chunk-а, на выходе новый blob
const newPngBlob = await pngChunkSet(
    // png-изображение
    pngBlob,
    // имя chunk-а
    'dgRm',
    // значение chunk-а: строка в виде массива byte
    new TextEncoder().encode('...'));
 
 
// чтение chuk-а
const dgrmChunkVal = await pngChunkGet(newPngBlob, 'dgRm');
const str = new TextDecoder().decode(dgrmChunkVal);

Листинг 2. Вызов функций записи и чтения PNG chunk-ов

Как поддержать проект

  • Начните использовать, расскажите что думаете.
    Любым способом: комментарии, личные сообщения, на GitHub.
    Все читаю, веду список предложений.

  • Расскажите знакомым.

  • Ставьте звездочки на GitHub.

Источник: https://habr.com/ru/post/658109/


Интересные статьи

Интересные статьи

Мы привыкли создавать некоторые элементы пользовательского интерфейса с помощью JavaScript, например аккордеоны, всплывающие подсказки (тултипы), усечение текста и т. д. ...
В охоте на проблемы безопасности погоня за неизведанными активами и скрытыми конечными точками часто заканчивается тем, что вы отвлекаетесь от очевидной, но по-прежнему в...
Наш онлайн-университет GeekUniversity запускает факультет управления продуктами. За 14 месяцев студенты получат знания и навыки, необходимые для работы менеджером продукта, выполнят задания от ...
Китайская компания DJI, поставляющая на рынок разного рода беспилотные аппараты, разработала дрон-оператор. Это устройство может нести на себе видеокамеры и снимать с воздуха происходящее вни...
Американские компании, например Google, пошли на поводу у правительства США и стали разрывать отношения с Huawei из-за подозрений в шпионаже. В 80-х годах у американских производителей полупро...