ImageProcessing-ElectronicPublications / scantailor-experimental

Scan Tailor Experimental is an interactive post-processing tool for scanned pages.
https://github.com/Tulon/scantailor/tree/experimental
GNU General Public License v3.0
37 stars 1 forks source link

TIFF и Mixed Raster Content mode #32

Open plzombie opened 5 months ago

plzombie commented 5 months ago

В RFC 2301 написано, что TIFF может содержать три слоя

The 3 layers of the MRC model are Foreground and Background, which are both multi-level, and Mask, which is bi-level. Each layer may appear only once on a page and is coded independently of the other two. In our earlier example, the black-and-white text could be in the Mask layer, the color chart in the Foreground layer, and the color image in the Background layer.

Насколько я понимаю, Scantailor сейчас не поддерживает такой режим. Изображение созраняется как фон (без маски). Вроде как Scantailor Featured мог сохранять две копии изображения - bg и отдельно mask.

Собственно, предложение. Для смешанного режима реализовать сохранение в mixed raster context. А потом уже разбираться, как сконвертировать это в djvu.

@zvezdochiot @noobie-iv @trufanov-nok (вроде никого не забыл) - нет возражений?

zvezdochiot commented 4 months ago

@plzombie say:

Кто-нибудь может мне в фотошопе

Точно не я, но тут есть участник на макосе: @gasparschott . У него поспрашивай (на буржуйском).

yozhic commented 4 months ago

Вот, произвольный многослойный из PS на macOS: dropbox.com Если что ещё в нём поменять надобно, пишите, поменяем. Можно и на Win сделать (тоже в PS).

Правка от @zvezdochiot : прикрепил к сообщению: PMT.zip (мало ли что с этим дропбокс)

noobie-iv commented 3 months ago

За месяц копипасты с фигурной обрезкой получился такой микротейлор:

screen

Он только показывает фиксированную пару картинок и поворачивает их влево/вправо. До рабочих превьюшек еще далеко. Там всего десяток-другой реально содержательных строк (установка виджета, рисование картинки и т.п.). А общий объем кода уже вышел за 2000 строк. Теперь я понимаю, почему в отладчике не мог понять ни одной строки: гуевый код реально на 99% состоит из обвязки.

zvezdochiot commented 3 months ago

@noobie-iv , круть. :+1:

Советую сохранить эту "поделку", на случай ежели решишь создать отдельную тулзу для создания макетов страниц (QPageMaket) и генерации PDF-страниц (а возможно и целых книг) на базе макетов. Я всё также, как и раньше, вижу решение "вопросов" к ST именно в наличии отдельной тулзы для макетирования страниц и использования цепочки:

ST -> {GIMP, Krita,... } -> QPageMaket -> PDF

PS: И всё же, хотелось бы вынести все (все!) зоны на отдельный этап, перед "Output". Это позволило бы напороч избавиться от мозолящего глаза "Mode" (какой такой режим, ежели всё обрабатывается согласно зон?), а заодно позволило бы добавить так назывемые palette-зоны, с заливкой маски выбранным цветом, как в fill-зонах, но "пипетка" будет работать на оригинальном цветном изображении + 2 зарезервированных (чёрный и белый). Такие вот дела. Да и фильтры можно было бы перенести туда же, чтобы видеть их действие, а не только на "цветном/сером" режиме.

trufanov-nok commented 3 months ago

Впомнилось. В ST очень много всего реализовано с нуля. Если бы его делал я - то собирал бы из готовых частей, тащил бы модули из других опенсорс проектов. В свое время намучался с thumbnails list в ST (но больше всего хотелось бы, конечно, заменить машинерию для манипуляций с изображениями (выделение прямоугольником, эллипсом и пр.) ) и полез искать готовые официальные компоненты для Qt. И нашел для thumbnails list, как мне показалось, неплохой. Больше ничего не нашел. Если бы я сейчас переписывал эту часть GUI, то сперва попробовал бы использовать его: https://marketplace.qt.io/collections/all-products/products/longscroll-qt

noobie-iv commented 3 months ago

@zvezdochiot

ST -> {GIMP, Krita,... } -> QPageMaket -> PDF

А я считаю, что это все как раз и должно быть прямо в тейлоре. Нужен список стадий, которые можно выбирать, а не фиксированный набор. И среди них - встроенные (нарезка страниц, деварп, размер страницы), и внешние (GIMP, GMIC, ImageMagic). Кому не надо - просто не добавляет лишние стадии. Так устроен стек модификаторов в 3D-программах. Если решу делать свое - вот так оно будет. Но литраж моих слюней пока не соответствует емкости желудка 😄.

В идеале это должны быть внешние плагины. В линуксах есть программы с плагинами? В винде нет стандартных каталогов, и обычно программа просто ставится в свою папку. А внутри папки, рядом с программой, заводится папка Plugins, куда сваливают плагины-DLL. При загрузке программа сканирует каталог, и если DLL отзывается, добавляет ее в список плагинов. Дописывать плагины, реализуя десяток стандартных функций по образцу, легче, чем пересобирать программу целиком.

хотелось бы вынести все (все!) зоны на отдельный этап

Я только начинаю слегка въезжать, что тут в коде происходит. До возможности добавлять стадии мне еще далеко (подозреваю, что несколько лет, если терпения хватит).

@trufanov-nok

В ST очень много всего реализовано с нуля

Если бы просто с нуля. Там еще отрицательные величины есть. На сегодня мой любимый образец кода выглядит так:

#include <iostream>

class Widget
{
public:
    void set(int value)
    {
        int old_value = m_value;
        m_value = value;
        if (m_value != old_value)
            update();
    }

private:
    void update()
    {
        std::cout << m_value << std::endl;
    }

    int m_value = 0;
};

int main()
{
    Widget w;
    w.set(1);
}

Но это же плюсы. Нельзя же в коде просто проверить значение и обновиться. Оператор if надо инкапсулировать!

class Widget { public: void set(int value) { Watcher watcher(this); m_value = value; }

private: void update() { std::cout << m_value << std::endl; }

class Watcher
{
public:
    Watcher(Widget* owner)
        : m_owner(owner)
        , m_value(m_owner->m_value)
    {
    }

    ~Watcher()
    {
        if(m_value != m_owner->m_value)
            m_owner->update();
    }

private:
    Widget* m_owner;
    int m_value;
};

int m_value = 0;

};

int main() { Widget w; w.set(1); }


Этот маленький шедевр найден в ImageViewBase (класс TransformChangeWatcher). Как говорил джокер бетмену, "с тобой безумно весело" 😄.
trufanov-nok commented 3 months ago

Но это же плюсы. Нельзя же в коде просто проверить значение и обновиться. Оператор if надо инкапсулировать!

Тут плюсы не при чем. Тут решается конкретная задача. Я уже плохо помню код, но скорее всего update() порождает тяжелые вычисления, и делать их нужно не на каждый чих пользователя, а только когда действительно припрёт. Как пример - рисование зон на вкладке Layers в Mixed mode. Если перегенирировать результат каждый раз, когда пользователь чего-то там двигает - ST повесится. А вот когда он с этой вкладки ушел (миллионом способов он это может сделать), т.е. вызвался ~ImageViewBase() - тогда да. Скорее вот такого отложенного обновления хотели добиться.

zvezdochiot commented 3 months ago

@trufanov-nok say:

Тут плюсы не при чем.

Ещё как при чём! У меня концы с концами из-за них не сходятся:

Стадия 3 "Геометрические искажения":

  1. Без искажений - угол == 0
  2. Поровот - угол == SkewFinder (заностися в параметры)
  3. Перспектива - угол == ???, но SkewFinder используется в TextLineSegmenter. Как его (угол) оттуда вынуть и прописать в параметры?!! (точнее наоборот: как использовать угол из "Поворота" вместо повторного определения?)
  4. Кривые - угол == ???, но SkewFinder используется в TextLineSegmenter. Как его (угол) оттуда вынуть и прописать в параметры?!! (точнее наоборот: как использовать угол из "Поворота" вместо повторного определения?)

Вот тебе и не при чём. Угол поворота определяется везде, а прописывается только в варианте 2. Вот это номер! Отсюда отсутствие сортировки по углу и дубляж кода. Вот это "щастье"! Такие вот дела.

@noobie-iv say:

А я считаю, что это все как раз и должно быть прямо в тейлоре.

Чтобы не быть голословным: Что такое макетирование на примере?:

Вот оригинальный материал: page-1-2-origin.pdf [5M].

А вот обработка в STEX + GIMP и простенькое макетирование с помощью python-cropper-tk + gs и пр.: page-1-2-stex_croppertk.pdf [1M].

noobie-iv commented 3 months ago

@zvezdochiot

Как его (угол) оттуда вынуть

Вроде как Task, CacheDrivenTask, Filter и OptionsWidget имеют указатель на настройки - m_ptrSettings. Внутри любого из них можно вытащить нужную настройку:

m_ptrSettings->getPageParams(m_pageId)->rotationParams().compensationAngleDeg();

Если доступен указатель на фильтр - из него можно получить указатель на настройки, а дальше по той же цепочке:

m_ptrFilter->getSettings()->...;

Угол поворота определяется везде, а прописывается только в варианте 2

Тут вроде как не плюсы виноваты. Это событийно-ориентированная программа. Не знаю как там в линуксах, а в виндах родное API для графических программ - чистый С без плюсов, со времен первой версии винды. Но в нем программа тоже нелинейная. Там тоже надо написать тучу функций обратного вызова, и сводить передачу данных между ними в уме. Реально линейность сидит где-то внутри очереди событий, которой рулит винда, которая дергает эти коллбеки. Но программист этого не видит, только callback-обрывки, и они тоже срабатывают когда захотят. Синхронизация данных между коллбэк-обрывками - головная боль программиста.

Qt - плюсовая обертка, но по факту работает так же. Те же сигналы, что и события винды, те же фишки с установкой фильтров. Те же проблемы с нелинейностью.

Был популярный VisualBasic - вообще не плюсы, но работал так же.

В автокаде API плюсовое (на старых плюсах - до 11), но и там идеи те же: хочешь свой объект - наследуйся и переопределяй пачку стандартных обработчиков, которых будет дергать автокад.

Я бы сказал, тут проблема в том, что большой проект (100 тыс строк) написан в одного, потому не откомментирован, и подключаться к нему тяжело. По WinApi есть описания функций, и примеры программ с нуля. По ObjectARX есть примеры. Про любую функцию есть подробности с примерами - зачем нужна, что за параметры, когда вызывается. А тут надо все три мегабайта кода лопатить, чтобы понять кто где.

Я из-за этого и начал свою микропародию писать. Добавляю десяток строк, и смотрю что они делают. В оригинальных мегабайтах я просто завяз, ни одной строки не понимаю: 99% - либо вызовы Qt, которых я не знаю, либо вызовы самодельных классов, про которые даже нагуглить нечего.

На сегодня скопипащено 2 тыс строк из 100 - это 2% за месяц. Что эти строки делают - теперь понимаю. На полное понимание таким методом, очевидно, надо 5 лет. Разумеется, я не буду смотреть алгоритмы обработки, только базовую логику. Если примитивно-базовое изображение в единственном рабочем фильтре заняло 2тыс строк, есть шанс, что код превьюшек займет столько же, а после этого (через месяц-другой) я смогу вернуться к STD и уже чинить его до первого релиза.

простенькое макетирование

Я бы тоже хотел макетирование в ST. Мне еще и разных размеров страниц не хватает: сканы строительных чертежей разноформатные.

Сейчас в главном окне хранится список ImageId c путями к изображениям, и по щелчкам запускается обработка выбранного Id по цепочке фильтров. Проблема в том, что на этот ImageId завязан весь код всех фильтров, всех виджетов, кеша превью и хз чего еще, Переделка основной логики работы требует перелопатить все три мегабайта кода. Мне такого на несколько лет работы. Самодельный внешний макетировщик, к которому можно потихоньку фильтры прикручивать, может, и проще, но до конца его довести - тоже много лет.

zvezdochiot commented 3 months ago

@noobie-iv say:

Самодельный внешний макетировщик, к которому можно потихоньку фильтры прикручивать, может, и проще, но до конца его довести - тоже много лет.

Ненадо никакого "до конца"! Ну о чём мы говорим? О том, что сейчас я делаю макетирование с помощью откровенного питоновского говна через reportlab, которым даже закодировать "по-людски" никак нельзя (он везде пихает ASCII85). Нафиг мне этот рак, дайте хоть какую-нибудь рыбу!

noobie-iv commented 3 months ago

Нужен макетировщик, который смотрит проект ST с размеченными картинками, и позволяет экспортить в PDF/DJVU?

zvezdochiot commented 3 months ago

@noobie-iv say:

Нужен макетировщик, который смотрит проект ST с размеченными картинками, и позволяет экспортить в PDF/DJVU?

Нет. На данный момент в проектах ST необходимого нет. Макет - это фактически плитка из прямоугольных областей, каждая из которых может быть упакованна разным способом (JPEG, JPX, DEFLATE, CCITT FAX GROUP 4, JBIG2) и со своим масштабным фактором. Сейчас же я делаю подобное с помощью указанной питоновской поделки + GhostScript + препарирую (режу на объекты), вычлеяя JPEG и JPX, перекодирую и сшиваю обратно PDF.

PS: Один рисунок, в зависимости от формы и величины, может содержаться в нескольких прямоугольниках плитки.

zvezdochiot commented 2 months ago

@noobie-iv , @plzombie , @trufanov-nok .

Модифицирую 4-ый этап "Полезная область" под регулятор:

Вконец запутался: всё есть, но ни шиша не работает. Ненавижу плюсы. Может кто подскажет, где собака порылась?

Суть же проста: мне нужно довести коэффициент из ГУЯ в https://github.com/ImageProcessing-ElectronicPublications/scantailor-experimental/blob/acbef1b768f4febb1d58011336e6c2843c161cb2/src/stages/select_content/ContentBoxFinder.cpp#L153 и поставить его вместо 0.0.