Вернуться к разделу "Материалы по сканированию и оцифровке бумажных книг".
В этой статье приводится описание нового метода создания серых полутоновых или цветных фотографических иллюстраций в многостраничных чёрно-белых DjVu-файлах. Я предлагаю назвать его условно "метод подклейки фона".
Смысл и суть этого метода состоит в добавлении ("подклеивании") на произвольные страницы готового многостраничного чёрно-белого DjVu-файла серых или цветных иллюстраций/фона. Обратите внимание - речь идёт именно об уже готовом DjVu-файле, то есть данная технология позволяет взять любой, скажем, скаченный из Интернета, многостраничный чёрно-белый DjVu-файл, и вставить на любую из его страниц (по желанию) серую/цветную иллюстрацию (или просто равномерный цветной фон).
При этом качество исходного DjVu-файла никак не меняется - метод работает абсолютно без потери качества. Размер получаемого DjVu-файла (после вставки иллюстраций/фона) равен размеру исходного файла плюс сумма размеров файлов всех вставляемых иллюстраций - т.е. никакие дополнительные издержки в плане роста размера файла не возникают.
Эта технология похожа по смыслу на метод разделённых сканов - отличаясь, однако, по сути выполняемых в ней процедур. Поэтому можно вполне ставить вопрос о том, какой из этих двух методов лучше, и для каких ситуаций.
Работа метода построена исключительно на бесплатных консольных утилитах из состава DjVuLibre.
Метод подклейки фона не существовал ранее и возник вместе с появлением данной статьи. Причина его небытия заключалась в ошибке в консольной программе djvumake (из состава DjVuLibre), которую устранил Леон Боту по моей просьбе - что и послужило поводом для написания данной статьи. Ошибка заключалась в том, что программа djvumake ранее аварийно "вылетала" на чанке INCL, представляющем из себя ссылку на файл-словарь разделённых символов. А т.к. практически все обычные DjVu-книги содержат словари разделённых символов, то и, соответственно, метод подклейки фона не работал.
Леон прислал мне исправленный исходник утилиты djvumake - который я самостоятельно скомпилировал в готовую к работе программу. Выкладываю её здесь:
Скачать исправленную версию djvumake (вместе с исходником) (139 КБ) |
Надеюсь, она войдёт в состав будущих версий DjVuLibre - последующих после версии 3.5.21 (текущая на данный момент). Этот исправленный исходник также доступен (на момент написания статьи) в CVS проекта DjVuLibre.
Возможность подклеивать задний фон к чёрно-белым DjVu-файлам существовала и ранее. Она уже давно была реализована под именем "DjVu Sepia" в программе JRA Publish 3.0. До написания данной статьи это был единственный способ подклейки заднего фона к DjVu-файлам. Но программа JRA Publish 3.0 мало того, что коммерческая - она ещё и совершенно недоступна, т.к. пока даже и не продаётся, бесплатная триальная версия отсутствует (всегда была только платная (!), а её предыдущие версии уже сняты с продажи. К счастью, теперь эта "монополия" (на технологию подклейки фона) разрушена.
Данная статья рассматривает метод подклейки фона только применительно к чёрно-белым однослойным DjVu-файлам. Хотя не исключено, что его можно будет впоследствии адаптировать и для иных DjVu-файлов.
Кратко алгоритм подклейки заднего фона выглядит так:
1. Создаём DjVu-файл заднего фона. Делаем заготовку заднего фона - белый TIF-файл с размерами (длина и ширина), равными размерам DjVu-страницы (многостраничного DjVu-файла), куда будет внедряться картинка. Помещаем на заготовку картинку-иллюстрацию (полутоновую серую или цветную фотографию) в нужное место - так, чтобы она потом (после подклейки) оказалась в желаемой позиции на результирующем DjVu-файле (аналогично методу разделённых сканов).
Полученную заднюю заготовку желательно уменьшить по формуле [(W+2)/3,(H+2)/3], где H - длина, W - ширина листа (округление результата делается путём простого отбрасывания дробной части). Это приведёт к 3-х-кратному уменьшению разрешения слоя заднего фона в будующем DjVu-файле (аналогично методу разделённых сканов) - что даст в итоге неплохую экономию размера DjVu-файла.
Готовую заднюю заготовку сохраняем в формате PPM (если иллюстрация - цветная) или в формате PGM (если иллюстрация - серая) при помощи IrfanView и кодируем в DjVu посредством утилиты c44 . Из полученного DjVu-файла извлекаем BG44-чанк посредством djvuextract.
2. Создаём пустой передний план. Просто подклеить задний фон к однослойному чёрно-белому DjVu-файлу (представляющему из себя одну лишь маску) недостаточно. Нужно ещё сделать передний план (в данном случае пустой), и тоже подклеить его к исходному DjVu-файлу - иначе подклеенный задний фон не будет отображаться в DjVu-просмотрщике одновременно с исходным слоем маски (а можно будет увидеть либо только маску, либо только задний фон - переключаясь между режимами просмотра в WinDjView).
Пустой передний план делаем так: создаём его заготовку - чёрный TIF-файл с размерами (длина и ширина), рассчитываемыми по формуле: [(W+11)/12,(H+11)/12)], где H - длина, W - ширина листа DjVu-страницы (многостраничного DjVu-файла), куда будет внедряться картинка (округление результата делается путём простого отбрасывания дробной части). Чёрный - в смысле равномерно залитый чёрным цветом по всей своей площади. Коэффициент деления разрешения 12 применяется для переднего плана в большинстве обычных DjVu-файлов - ради экономии размера файла.
Готовую заготовку переднего плана сохраняем в формате PGM при помощи IrfanView (преобразовав предварительно в 8-битный формат, если надо) и кодируем в DjVu посредством c44 . Из полученного DjVu-файла извлекаем BG44-чанк посредством djvuextract. Важная деталь: Полученный BG44-чанк называем как "FG44.cnk" - поскольку в дальнейшем он будет использован в качестве чанка переднего плана, а не заднего фона. Вот такая маленькая хитрость (от Леона Боту).
3. Разбираем исходный многостраничный чёрно-белый DjVu-файл на отдельные страницы посредством djvmcvt.
4. Разбираем на чанки ту DjVu-страницу, куда будем подклеивать задний фон - посредством djvuextract. Получаем в итоге один-единственный чанк - Sjbz-чанк (других чанков там просто нет).
5. Добавляем к смеси чанков (т.е. просто копируем в папку с ними) из п.4. чанки BG44 (задний фон) и FG44 (передний план) и собираем из этой смеси DjVu-страницу (на замену DjVu-страницы из п.4) посредством (исправленного) djvumake. Теперь она будет иметь подклеенный задний фон (т.е. вставленную иллюстрацию).
6. Собираем назад из отдельных страниц многостраничный DjVu-файл посредством djvmcvt. Всё готово - получаем многостраничный DjVu-файл, на одну из страниц которого вставлен задний фон.
Я сделал рабочий пример, демонстрирующий работу метода подклейки фона. Этот пример можно скачать по следующей ссылке:
Пример метода подклейки фона (589 КБ) |
В этом архиве находится всё необходимое для того, чтобы Вы смогли самостоятельно вставить (прилагаемую) цветную иллюстрацию на первую страницу (прилагаемого) многостраничного чёрно-белого DjVu-файла.
Для этого Вам необходимо пройтись по внутренним папкам архива и выполнить действия, указанные в приведённой ниже инструкции.
В каждой папке нужно запускать соответствующий bat-файл, который выполняет определённое Действие, а Переходящий результат данного действия нужно копировать в соответствующую (указанной в инструкции) папку.
Папка "1":
Действие:
c44 back.ppm
Переходящий результат:
Файл back.djvu. Копируется в папку 5.
Папка "2":
Действие:
c44 -slice 120 fore.pgm
Переходящий результат:
Файл fore.djvu. Копируется в папку 6.
Примечание: опция -slice 120 не обязательна. Она выставляется для того, чтобы результирующий DjVu-файл получился не из 3-х маленьких IW44-чанков (по умолчанию), а из 1-го большого. Тогда при обработке в папке 7 не выскочит предупрежение: "djvumake: FG44 file contains more than one chunk". Это предупреждение не критично, даже с ним потом всё получается, как нужно.
Папка "3":
Действие:
djvmcvt -i source.djvu dir index.djvu
Переходящий результат:
В подпапке dir файлы 1.djvu и 3.djbz.
Копируются в папку 4 и в папку 7.
Содержимое подпапки dir (кроме файла 1.djvu)
копируется в папку 8.
Папка "4":
Действие:
djvuextract 1.djvu Sjbz=Sjbz.cnk
Переходящий результат:
Файл Sjbz.cnk. Копируется в папку 7.
Папка "5":
Действие:
djvuextract back.djvu BG44=BG44.cnk
Переходящий результат:
Файл BG44.cnk. Копируется в папку 7.
Папка "6":
Действие:
djvuextract fore.djvu BG44=FG44.cnk
Переходящий результат:
Файл FG44.cnk. Копируется в папку 7.
Папка "7":
Действие:
djvumake 1.djvu INFO=2479,3507,300 INCL=3.djbz Sjbz=Sjbz.cnk
FG44=FG44.cnk BG44=BG44.cnk
Переходящий результат:
Файл 1.djvu. Копируется в папку 8.
Примечание: параметры INFO можно взять из свойств страницы "Информация о странице", которые можно увидеть по правой кнопке в WinDjView. Длина и ширина страницы также выводится в протоколе работы утилиты djvuextract в папке 4.
Папка "8":
Действие:
djvmcvt -b index.djvu target.djvu
Переходящий результат:
Файл target.djvu. Это готовый файл - результат
работы всего алгоритма. Сравните его с файлом source.djvu
в папке 3.
Примечание:
В папке "Summary" находятся (для справки) файл-источник source.djvu, файл вставляемого заднего фона back.djvu и результирующий файл target.djvu.
Результаты метода выявили небольшую проблему в WinDjView v1.0. Оказалось, что результирующий DjVu-файл (со вставленным задним фоном) отображается в программе без антиалиасинга (сглаживания) - в отличие от исходного DjVu-файла. По словам Леона Боту, наиболее вероятно, что это есть некая особенность WinDjView v1.0 - различный антиалиасинг "цветных" и "чёрно-белых" DjVu-файлов - а не какая-то разница в этих 2-х DjVu-файлах.
Леон утверждает, что исходный и результирующий DjVu-файлы абсолютно идентичны в отношении переднего плана (т.е. отображаемого текста, на котором, собственно, и заметно наличие/отсутствие антиалиасинга).
Я заметил, что эту проблему можно полностью устранить, если включить в Настройках WinDjView v1.0 флажок "Более качественная (но медленная) прорисовка цветных страниц" - в этом случае текст исходного и результирующего DjVu-файла выглядит абсолютно идентично - в плане антиалиасинга.
Подобная разница в антиалиасинге "цветных" и "чёрно-белых" DjVu-файлов отсутствует в DjVu-просмотрщике DjView 4 (из состава DjVuLibre) - там антиалиасинг "чёрно-белых" DjVu-файлов одинаков с антиалиасингом "цветных" DjVu-файлов (т.е. они отображаются одинаково "плохо").
Те, у кого не установлен WinDjView, могут увидеть эту проблему на прилагаемых скриншотах (289 КБ).
Проблема качественного антиалиасинга "цветных" DjVu-файлов в WinDjView, на мой взгляд, настолько серьёзна, что, к сожалению, ставит под вопрос всю целесообразность применения метода подклейки фона (т.к. именно WinDjView является наиболее популярным DjVu-просмотрщиком под Windows). В смысле, что никто не захочет получить из "качественно-отображаемого" "чёрно-белого" DjVu-файла "некачественно-отображаемый" "цветной" DjVu-файл - даже ради его "иллюстрирования".
Я сообщил Андрею Жежеруну, автору программы WinDjView, о возникшей проблеме. Вот что он мне ответил:
Вы сами описали решение возникшей у Вас
проблемы - включить настройку, которая применяет
другой, более качественный, но и более медленный
алгоритм масштабирования цветных картинок
(антиалиасинг в данном случае - неправильный
термин). Этот алгоритм взят из пакета netpbm и он
включается для цветных DjVu-файлов, когда
установлен флажок "Более качественная (но
медленная) прорисовка цветных страниц". Он слишком медленный, чтобы включить его по умолчанию, поэтому галочка по умолчанию выключена. Ранее уже поднимался вопрос об альтернативных быстрых алгоритмах масштабирования - мне они неизвестны, а других вариантов никто не предложил. Без этой галочки используется стандартное масштабирование из DjVuLibre, которое даёт результат, идентичный DjView; вполне возможно что и в DjVu-плагине картинка будет точно такая же. Да, в Вашем примере в DjView исходная и новая страницы будут выглядеть одинаково - так, как в WinDjView выглядит цветная страница без установленной галочки. Для чёрно-белых страниц всегда используется алгоритм из пакета netpbm, который более медленный, но даёт более хороший результат. Именно поэтому чёрно-белые DjVu-файлы отображаются в WinDjView по-умолчанию более качественно, чем цветные. Для чёрно-белых страниц этот алгоритм работает быстрее, чем для цветных, и его скорость приемлема для того, чтобы всегда использовать именно его. Ещё отмечу, что на стандартных масштабах (50,100,150,200% и др.) при разрешении документа 300/600 dpi, получается масштабирование в целое число раз, которое выполняется простым даунсэмплингом - это очень быстро, и результат выглядит хорошо. Термины "сглаживание" и "антиалиасинг" относятся к ситуациям, когда нужно растеризовать векторную графику и добиться, чтобы контуры имели правильный вид. Здесь же никакой векторной графики нет: есть картинка большого размера (например, 2480x3508 пикселей - a4, 300 dpi), и производится её масштабирование до другого размера (например, 1024x1448 - fullscreen, fit width). В исходной картинке текст чёткий (он находится в битональном слое), а в отмасштабированной - зависит от алгоритма. "Размазанность" в стандартном масштабировании из DjVuLibre возникает из-за того, что оно производится в два этапа - сначала картника даунсэмплится в целое число раз (в моём примере - до 1240x1754), а затем уже применяется быстрый билинейный скейлинг. Это значительно уменьшает время работы. Если не делать сначала даунсэмплинг, то результат билинейного скейлинга и алгоритма из netpbm почти одинаков, но последний немного быстрее. Бикубический скейлинг медленнее, чем билинейный, поэтому я сомневаюсь, что он может оказаться быстрее чем алгоритм из netpbm. В WinDjView алгоритм из netpnm ("Более качественная (но медленная) прорисовка цветных страниц") используется только при уменьшении картинки. Для увеличения применяется fast bilinear scaling из djvulibre. На больших зумах нужно много памяти для любого алгоритма: например, если у Вас страница A4 отсканированная в 300 dpi и Вы её ещё в 2 раза увеличиваете (масштаб 600% в WinDjView), то для хранения битмапа нужно 100 мегабайт памяти. Понятно, что можно хранить только части картинки, предназначенные для вывода на экран, но тогда процедура кэширования становится сложней, и на самом деле мне просто не хочется делать такую оптимизацию - оперативной памяти сейчас устанавливают всё больше и больше, поэтому это не так актуально. К тому же высокие зумы не так часто нужны при чтении книг. Про реализацию на ассемблере - не так просто написать код, который будет работать быстрее, чем тот, который генерируют современные оптимизирующие компиляторы. Для этого нужно быть очень опытным специалистом по ассемблеру. |
Попутно пришлось разобраться с некоторыми терминами. Как известно, в программах, отображающих растровое изображение на экране, применяется его сглаживание. Например, это делается в WinDjView, в СканКромсаторе, в ACDSee и т.д.
Однако, подобное сглаживание действительно нельзя называть антиалиасингом. Как выяснилось, сглаживание изображения можно поделить на 2 принципиальных вида:
1. Антиалиасинг - сглаживание векторных графических объектов.
2. Интерполяция - сглаживание растровых графических объектов. Делается путём применения интерполяционных фильтров - самыми известными из которых являются Bicubic, Bilinear, Nearest-neighbor. Наиболее часто (но не обязательно) интерполяция применяется при масштабировании растрового изображения - чтобы сгладить визуальные артефакты масштабирования.
Метод подклейки фона - это практически совершенно новая, перспективная и революционная DjVu-технология. Пока что её ещё рано рекомендовать к массовому применению - сначала её нужно как следует протестировать на разных DjVu-файлах, решить вышеуказанную проблему с WinDjView, а также провести её сравнение с методом разделённых сканов.
Не исключено, что в перспективе метод подклейки фона сможет полностью заменить собою метод разделённых сканов - по крайней мере, для случая не-цветных DjVu-книг (т.е. чёрно-белых, содержащих серые полутоновые иллюстрации). Уже сейчас ясно, что он более удобен, чем метод разделённых сканов - например, он не требует использования коммерческой утилиты msepdjvu (но, в то же время, как и msepdjvu, пользуется преимуществом "сквозного" использования словарей разделённых символов (что не умеет делать DjVu Sep), даёт большую гибкость формирования качества заднего фона (за счёт использования полнофункциональной утилиты c44) и т.д.
Сравнение 2 методов - это тема для отдельных (будущих) исследований. Принципиальная разница между ними состоит в том, что метод подклейки фона создаёт 3-х-слойные DjVu-файлы с чанком переднего плана FG44, а метод разделённых сканов создаёт 2-х-слойные DjVu-файлы с чанком переднего плана FGbz (считается, что он совмещён с чанком маски Sjbz).
Одним из существенных параметров сравнения 2-х методов может служить скорость отрисовки DjVu-файлов в DjVu-просмотрщике. Что отрисовывается быстрее: FGbz или FG44? На этот вопрос Леон Боту ответил: "На текущий момент, FG44 отрисовывается немного быстрее".
В заключение я хотел бы выразить огромную благодарность Леону Боту (один из создателей формата DjVu), исключительно благодаря советам и помощи которого и стала реальностью разработка данного метода подклейки фона.
Автор: monday2000.
15 мая 2009 г.
E-Mail (monday2000 [at] yandex.ru)