Дизеринг для монохромных LCD и конвертер растровых изображений

Дизеринг для монохромных LCD и конвертер растровых изображений
Dithering for a monochrome LCD and Bitmap converter

Внимание! Материал содержит большое количество полноразмерных иллюстраций и может навредить вашему трафику!

Немного теории
Как работать с программой
Интерпретация выходного кода
Корректировка изображения для LCD c «неквадратным» пикселем
Error-Diffusion Dithering vs Thresholding, или когда дизеринг не помогает
Артефакты дизеринга
Другие полезные применения программы
Заключение



Немного теории

Дизеринг — это давно известная и очень широко используемая технология подмешивания в основной сигнал дополнительного искусственного шума с определенными параметрами, позволяющая уменьшить ошибку квантования исходного сигнала. Это - прикладная математика, дающая замечательные практические результаты в любой сфере, где происходит обработка цифровых сигналов. Но в теорию мы особенно углубляться не будем, желающие могут самостоятельно погрузиться в бездонное море информации по DSP.

При обработке изображений дизеринг позволяет создать иллюзию расширения цветовой палитры у ограниченной по возможностям системы визуального отображения. Например, для монохромного дисплея (то есть такого, когда каждый пиксел может иметь только два состояния яркости — максимальное или минимальное) можно создать иллюзию полутоновых переходов и отображать градации серого цвета.

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

Если вы не работаете с микроконтроллерами или не имеете под рукой подобных LCD экранов, программа позволит вам «полюбоваться» дизерингом и на экране ПК, кроме того, она может использоваться и в некоторых других полезных целях, о чем будет рассказано в главе Другие полезные применения программы. Если же вам приходится иметь дело с подготовкой изображения с дизерингом для вывода на экран, то программа быстро сгенерирует вам программный код, соответствующий изображению, пригодный для непосредственной вставки в исходный файл в среде разработки, при этом можно выбрать синтаксис ассемблера или С/C++.

Существуют несколько алгоритмов дизеринга. Самый простой и быстрый из них — когда цветность (или яркость для монохромного вывода) каждого пиксела исходного изображения сравнивается с некоторым постоянным значением (thresholding value) и по результатам сравнения принимается решение о цвете пиксела выходного изображения. В случае монохромного вывода цвет может иметь два значения. В программе этот метод реализован, так как для небольшого разрешения малогабаритных монохромных дисплеев другие методы дизеринга зачастую просто не пригодны.

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

Следующая ступень усложнения алгоритма - вычисление граничного значения порога квантования путем сравнения с фиксированным образцом (набором пикселов). Метод имеет несколько разновидностей, одна из которых широко используется в полиграфии. Кроме того, многие из тех, кому сейчас лет за 40, помнят и обязательный атрибут, украшавший стенку операционного зала, серверных комнат или просто помещения «компьютерщиков» в 70-80 года прошлого века - портрет Моны Лизы или другого узнаваемого персонажа, отпечатанный матричным принтером на перфорированной бумаге. При этом как раз и использовался подобный метод.

Эти алгоритмы в программе не применяются.

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

В программе реализованы девять популярных алгоритмов дизеринга с распределением ошибки.

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

Подробнее о методах дизеринга можно прочитать по ссылке:
http://en.wikipedia.org/wiki/Dither

Как работать с программой

Программа не требует установки, не модифицирует реестр и может быть размещена в любом удобном для вас месте, так как ее размер менее 60КБ(v.0.1.0.5). Инсталлятор бы добавил еще полмегабайта.

Запускаем:


Интерфейс программы (v.0.1.0.5)

В программе использован упрощенный интерфейс, без стандартного меню и пиктограмм. В нижней части окна большинство опций обработки доступны и без загрузки исходного изображения, но рассмотрение интерфейса лучше начать с загруженным графическим файлом. Исходным изображением может быть файл типа bmp, jpeg, png, tiff или gif, с пиксельным форматом 1bppIndexed, 8bppIndexed, 24bppRgb, 32bppRgb или 32bppArgb.

Разумеется, файл с пиксельным форматом 1bppIndexed конвертировать нет смысла (так как ничего не изменится), но необходимость его поддержки описана подробнее в главе Артефакты дизеринга, кроме того, можно настроить отображаемые цвета и сделать предеформацию под «неквадратный» пиксел.

Ограничения на максимальный размер для исходного файла у программы нет, но не надо забывать про ее основное назначение, поэтому файлы больших размеров лучше заранее подготовить в каком-нибудь графическом редакторе, изменив их размеры или вырезав необходимые фрагменты.

Минимальный размер исходной картинки по любой стороне — 32 пиксела. Файлы с меньшими размерами не обрабатываются.

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

Откроем приятное для глаза изображение:


Загружен исходный файл «20euro.jpg»

По умолчанию, опции «Auto» и «Clip» отмечены галочкой (в принципе, все опции могут устанавливаться по своему предпочтению автоматически файлом инициализации, включая и некоторые опции, не управляемые через визуальный интерфейс программы).

«Auto» означает автоматическую конвертацию исходного изображения (картинка слева) в формат 1bpp по порогу (в центре) и в формат 1bpp с дизерингом (картинка справа). Конвертация при этом происходит динамически при любом изменении параметров, доступных через интерфейс, которые приводят к изменениям в выходном изображении. Так как при исходном файле большого размера или при большой области клиппинга конвертация может занять и несколько секунд, в зависимости от параметров процессора, то опцию «Auto» можно отключить. При этом станет доступной кнопка «Convert» и конвертация в форматы 1bpp будет происходить только при ее нажатии, то есть, можно будет без раздражающих задержек подготовить требуемые настройки. Но и при включенной опции «Auto» на Sempron3100+ 1800MHz серьезного дискомфорта с конвертацией изображения 800х600 точек не ощущается.

Активация опции «Clip» обеспечивает возможность конвертации не всего исходного файла, а только его прямоугольной области, в данном случае 128х64 точки, что является одним из распространенных форматов экрана у LCD. По умолчанию верхняя левая точка прямоугольника клиппирования располагается в левом верхнем углу исходного изображения.

Ниже изображений размещается текстовая информация. Она состоит из имени файла (или его типа для обработанного изображения), процентного отношения размера картинки к максимальному месту под нее в окне программы (160х160 пикселов), размера файла в пикселах и формата представления данных.
Если размер картинки не превышает 160х160 пикселов, то она отображается полностью и процентное отношение будет указано как 100%.

Снимем галочку у опции «Clip»:


Загружен исходный файл «20euro.jpg», клиппинг не используется

Сжатие форматов 1bpp средствами .Net (т.е. методами бикубической или билинейной фильтрации) приводят к серьезной деградации при визуализации, особенно, если изображение с хорошей контрастностью. Поэтому можно воспользоваться кнопками «View» для просмотра «полноформатного» изображения. Кавычки использованы потому, что «полноформатное» изображение ограничено 800х600 пикселами (хотя и это настраиваемый параметр), изображения большего размера вписываются (сжимаются без искажения пропорций) в размер 800х600.

Нажимаем кнопочку «View», находящуюся выше обработанного дизерингом изображения и получаем на экране картинку:


«Полноформатное» изображение, обработанное дизерингом

Так как это изображение не имеет привычных атрибутов окна в виде рамки, заголовка и меню, то «перетаскивается» оно удерживанием в любом месте картинки LMB (левой кнопки мыши) и перемещением в любое место экрана.

Каждое изображение, открываемое через любую кнопку «View», имеет контекстное меню, вызываемое кликом RMB (правой кнопки мыши) :


Контекстное меню, подсвечен заголовок

Верхняя строчка меню (т.е. заголовок) содержит тип файла и метод обработки, название исходного файла и отношение размера картинки к максимальному размеру показа в 800х600 пикселов. Если размер картинки меньше или равен 800х600, то будет показываться 100%.

Опции «Minimize» и «Close» - стандартные для оконных приложений.
Опция «Save Аs...» вызывает диалоговое окно сохранения файла. Файл сохраняется в формате 1bppIndexed, можно использовать контейнеры bmp, png, jpg, tiff, gif. Если не указывать расширение, файл сохраняется как bmp. Допускается использовать расширения jpeg и tif.

Опция «Topmost» позволяет окну находиться поверх всех остальных (вернее, поверх всех окон с бОльшим индексом z-сортировки). Повторное открытие контекстного меню после клика по «Topmost» покажет активацию опции «поверх всех окон»:


Режим «поверх всех окон» активирован

Опция «Orphan» («Сирота») позволяет «отвязать» изображение с контекстным меню от обновлений обработок программы. То есть, до активации этой опции все изменения в родительском изображении (поверх которого находилась кнопка «View») одновременно касались и этой картинки. Кроме того, по нажатию кнопки «View» может создаваться только одно изображение каждого типа (Origin, Grayscale, Thresholded, Dithered). Изображение, сделанное «сиротой», больше не обновляется и дает возможность генерации нового окна, при нажатии кнопки «View» для этого типа изображений. То есть, количество открытых изображений ограничивается только возможностями компьютера, прежде всего наличием RAM.

Если опция «Orphan» была активирована, то она больше не появится в контекстном меню.


Опция «Orphan» уже активирована для данного изображения и отсутствует в контекстном меню

Все изображения без активированной опции «Orphan» закрываются при нажатии кнопки «Close». Для закрытия всех изображений с уже выбранной опцией «Orphan» нужно нажать на кнопку «Del orphans».

Все изображения автоматически закрываются при выходе из программы.

В череде кнопок верхнего ряда присутствует кнопка «Gray», которая аналогична функции «View», но приводит к появлению «обесцвеченного» участка изображения, то есть создается изображение формата 8bppIndexed типа Grayscale с 256 градациями серого цвета, с размерами и местоположением клиппингового прямоугольника (или с размерами исходного, если снята галочка с опции «Clip»).

Программный код обработанных изображений генерируется при нажатии на кнопку «Get Code» и копируется в Clipboard. В зависимости от активной опции «Asm» или «C/C++», код пригоден для непоследстенной вставки в текстовый редактор систем разработки ПО на ассемблере или C/C++. Подробнее об этом написано в главе Интерпретация выходного кода.

В центре нижней части окна программы находится ползунок, определяющий порог при простейшем квантовании по яркости изображения. При активной опции «Auto» изменения сразу визуализуются. Если размер выходнго изображения превышает по одной стороне 160 пикселов, удобнее открыть «полноразмерную» картинку нажатием кнопки «View», при этом
изменения будут одновременно происходить и в ней, и в изображении в окне программы.

Правее ползунка находится опция «Inv», которая меняет местами два цвета в обработанных изображениях формата 1bppIndexed.


Файл «20euro.jpg» после дизеринга и инверсии. Выглядит даже лучше неинвертированного изображения

Повторное изменение опции «Inv» возвращает предыдущее назначение цветов. Действующая в данный момент палитра отображается в правом нижнем углу экрана. Левее кнопки «W» цветной прямоугольник показывает цвет переднего плана, прямоугольник правее кнопки «B» показывает цвет заднего плана. Нажатие кнопки «W» или «B» вызывает стандартное диалоговое окно Windows для изменения цвета. Таким образом, можно всегда подобрать палитру, соответствующую вашему дисплею.

Вот что я вижу на своем дисплее DOGM-128e, который технически голубой негатив с белой подсветкой. Но из экономии (белая подсветка стоит около $20) куплена желто-зеленая, поэтому цвет изображения примерно такой:


Монохромное изображение с «цветной» палитрой

Опция сохранения формата 1bppIndexed записывает в файл текущую цветовую палитру. Есть одно маленькое отличие, по сравнению с контекстным меню. Сохранение из окна программы всегда записывает полный размер обработанного изображения, если же делать это из контекстного меню, то максимальный размер не превышает 800х600 точек (или по пользовательской инициализации).

Загружаемый файл формата 1bppIndexed цветовую палитру не меняет:


Загружен 1bppIndexed файл «d1.bmp» с «цветной» палитрой, выходная палитра не меняется

В любое время палитру можно вернуть к «нормальному» черно-белому варианту нажатием кнопки «D».

Слева, в самой нижней части окна программы, находится блок трансформации исходного изображения. Опцию «Trf» можно активировать только без загруженного исходного файла. При этом изображение по каждой стороне может быть изменено в пределах от 50% до 150% от исходного размера. Эта опция полезна, если у LCD «неквадратный» пиксел. Подробнее о технике этой работы написано в главе Корректировка изображения для LCD c «неквадратным» пикселем.

Правее блока трансформации находится выпадающий список доступных наиболее популярных алгоритмов дизеринга. В случае изменения алгоритма и при установленной опции «Auto» изображение с дизерингом автоматически обновится.

При выбранной опции «Clip», если размер клиппинга меньше размера исходного файла, клиппирующий прямоугольник можно визуализовать на исходном изображении (только в окне программы). Для этого курсор мыши нужно переместить на исходное изображение, при этом его форма изменится со стандартной стрелки на «руку с указующим перстом». Указательный палец руки будет указывать на центр клиппирующего прямоугольника. Область клиппинга выбирается при нажатии LMB, при этом в соответствующем масштабе на экране появится рамка, курсор примет форму из пересеченных двунаправленных стрелок. Удерживая LMB нажатой, рамку можно перемещать. Если рамка целиком находится в пределах исходного изображения, ее цвет желтый. Как только она выходит за пределы исходного изображения, ее цвет становится красным и показывается только часть рамки, находящаяся в поле изображения. Красный цвет является только индикатором и не влияет на размер клиппируемой области, так как, по достижении границы изображения по любому измерению, размер клиппирующего прямоугольника по этому измерению отсчитывается «внутрь», что будет хорошо заметно по конвертированным изображениям, так как конверсия, при включенной опции «Auto», будет происходить при каждом изменении положения мыши.

При отпускании LMB курсор, если находится в пределах исходного изображения, принимает форму руки. Рамка остается там, где была в момент отпускания LMB.


Клиппирующая рамка на исходном изображении

Нажатие LMB в другом месте исходного изображения приведет к перемещению рамки в новое положение. Нажатие RMB убирает рамку с экрана, но параметры клиппинга при этом не меняются.

Изменение размеров клиппинга при активной рамке будет приводить к соответствующему изменению ее размеров и к коррекции размеров конвертированных изображений. Рамка не может быть больше размера исходного изображения и меньше 32 пикселов по любой стороне (в пересчете на реальный масштаб).

Последний и самый важный элемент интерфейса — кнопка «About». При ее нажатии появляется диалоговое окно:


Диалоговое окно «About»

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


Интерпретация выходного кода

При нажатии на кнопку «Get Code» в Clipboard записывается отформатированный код выбранного изображения в текстовом виде, пригодный для использования в среде разработки на языке ассемблера или C/C++, в зависимости от выбранной опции.

Полученный код можно вставить в любой текстовый редактор. Например, в обычный Notepad.


Первые 16 строк изображения из файла «eyes.bmp» в варианте для ассемблера


Первые 16 строк изображения из файла «eyes.bmp» в варианте для C/C++. Разница в данных с предыдушим листингом обусловлена сменой метода дизеринга, при одинаковом методе код будет идентичен

Каждый байт данных соответствует восьми точкам изображения по вертикали. Данные на экран выводятся последовательно, показывая в строке на экране представление в шестнадцатеричном формате каждых 16 байт кода картинки. После того, как показаны все байты восьми полных строк изображения, вставляется пустая строка. Таким образом, если верхний угол принять за точку отсчета (0,0), то, при размере картинки 128х64 пикселов (при этом максимальные координаты будут (127,63)), первый байт соответствует точкам (0,0),(0,1)...(0,7), а последний байт перед первым пробелом — точкам (127,0),(127,1)...(127,7). Младший бит в байте соответствует самой первой (верхней) строке.

Такая конфигурация соответствует адресации экранной памяти большинства монохромных LCD и требует простой передачи массива байтов в контроллер дисплея по любому доступному интерфейсу. При наличии и возможности можно использовать дополнительные видеобуфера в RAM (для упрощения программной генерации изображения, текста и спецэффектов), а при передаче применять DMA.

Как правило, число пикселов LCD по вертикали кратно восьми. Поэтому при генерации кода изображения, если высота картинки не кратна восьми пикселам, в код автоматически добавляются паддинговые нулевые биты в последний блок данных, чтобы итоговый размер сгенерированного кода соответствовал бы высоте изображения, кратной восьми пикселам. Для C/C++ это сразу будет заметно по заголовку кода и увеличенной длине массива. Вот пример для картинки размером 129х65 пикселов:


Первые 16 строк изображения «20euro.jpg» размером 129х65 пикселов

Длина массива 1161 байт, что соответствует наличию дополнительных (129 * 7) паддинговых битов, то есть:

129 * (65+ 7) / 8 = 1161 байт.

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

Еще про паддинговые биты : сохранение, например, в формате bmp, приводит к увеличению размера файла, если размер по ширине не выровнен по 4-х байтной границе, за счет дополняющих паддинговых битов в каждой строке (это не прихоть программы, а требования спецификации этого формата). Генерируемый код никогда не содержит этих дополняющих битов по горизонтали.

Корректировка изображения для LCD c «неквадратным» пикселем

Большинство современных LCD имеют «квадратные» пиксели, т.е. ширина точки матрицы плюс межпиксельное расстояние по ширине равно высоте точки плюс межпиксельное расстояние по высоте. У цветных RGB экранов ширина пиксела состоит из трех разноцветных субпикселов. Но встречаются и другие варианты.

Рассмотрим конкретный пример — LCD DOGM-128е производства Германии. Геометрические размеры его элемента изображения представлены на рисунке:


Размеры пиксела LCD дисплея DOGM-128е

Оценим, как это повлияет на искажение вертикального размера изображения, рассчитанного на соотношение сторон пиксела 1:1. Учитывая, что по высоте располагаются 64 пиксела и 63 межпиксельных расстояния, получаем итоговый вертикальный размер изображения:

64 * 0.42 мм + 63 * 0.015 мм = 27.825 мм,

хотя правильный геометрический формат картинки получался бы при высоте:

64 * 0.36 мм + 63 * 0.015 мм = 23.985 мм.

Процентное превышение :

(27.825 / 23.985) * 100 = 116%

Для вывода текста это не является помехой, а вот растянутые графические изображения - вытянутые лица, эллипсы вместо окружностей и т.д. - могут быть неприемлимыми. Для программно генерируемой графики придется усложнять алгоритмы, а для вывода изображений, получаемых из обычных графических файлов, надо будет исходный файл сжать по высоте с обратным соотношением ( 23.985 / 27.825 ).

Для подобной коррекции программа позволяет настроить предварительную трансформацию размеров исходного файла.

Опция трансформации активна только до загрузки исходного файла, то есть параметры трансформации устанавливаются либо при первом запуске программы, либо после нажатия кнопки «Close», которая удаляет из программы исходный файл и обработанные изображения, не помеченные как «orphan».

Ставим галочку у чекбокса «Trf» и выставляем нужную степень сжатия или расширения для размера по высоте и/или по ширине, в процентах от действительного размера (от 50% до 150%). Сам исходный файл изменяться не будет, так как программа всегда делает его копию и только копия подвергается трансформациям.

Определим для нашего LCD DOGM-128e значение трансформации, которое бы не давало геометрических искажений, размер корректируем по высоте:

( 23.985 / 27.825 ) * 100 = 86.20

Так как шаг изменения процентного параметра равен единице, то для этого дисплея необходимо выставлять корректировку исходного размера по высоте, равную 86% от исходной.

Проверяем на практике.

Без коррекции:


Звездочки на флаге ЕС расположены по правильной окружности

С коррекцией:


Звездочки на флаге ЕС расположены по эллипсу

При установленной опции «Trf» у исходного изображения можно заметить изменение не только вертикального размера с 304 до 261 пиксела, но и формата с 24bppRgb на 32bppArgb. Это связано с тем, что встроенный в .Net метод изменения размера объекта класса Bitmap всегда создает измененную картинку в формате 32bppArgb, а сохраняемый bmp файл получает формат 32bppRgb. Программа распознает и эти форматы, отбрасывая, при необходимости, ненужные для обработки данные.


Исходное изображение без коррекции на LCD DOGM-128e приводит к растягиванию по вертикали


Исходное изображение, предварительно сжатое по вертикали, восстанавливает правильные пропорции на LCD DOGM-128e

Но «неквадратный» пиксел — это не только минусы. При «продолговатом» пикселе увеличивается площадь и информационная емкость экрана, в нашем случае примерно на 16% по сравнению с традиционным соотношением сторон пиксела, равным единице.

Для DOGM-128e можно исправить геометрию, не сжимая исходный файл по высоте, а растягивая по ширине. Но это равносильно уменьшению удельной полезной площади экрана и трудно найти ситуацию, при которой это было бы оправдано.

Артефакты дизеринга

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


Тестовое изображение, серый цвет {127,127,127}

Из примененных девяти методов дизеринга ни один не справился без появления в конвертированном изображении серьезных артефактов.


Артефакты дизеринга при отсутствии маскирующих перепадов яркости исходного изображения

Поскольку сжатый масштаб может привести к искажениям обработанного изображения и при качественном дизеринге, представлена полноразмерная картинка, с дизерингом по методу Sierra3:


Дизеринг тестового изображения методом Sierra3. Фон «штормит»

Наиболее приемлимым при таком входном сигнале оказывется результат дизеринга по методу Sierra Filter Lite, вероятно, из-за наименьшего числа дробления исходной ошибки и нахождения серого цвета на границе порога отсечения при квантовании:


Дизеринг тестового изображения методом Filter Light. Фон тоже не идеален, но заметно однороднее

Серый цвет {192,192,192} у вышеприведенного теста кардинально меняют ситуацию — проваливаются все методы, кроме Stucki, результат которого можно считать идеальным:


Дизеринг тестового изображения методом Stucki при сером цвете {192,192,192}

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

Еще один хорошо различимый артефакт происходит из самого алгоритма подсчета, когда ошибка квантования для текущего пиксела распределятся на некоторе число пикселов правее и ниже от текущего. Это означает, что самые верхние и все боковые ряды пикселов не дополучают составляющих рассчитанной ошибки, что будет заметно, если верхняя и правая часть исходного изображения имеют небольшие изменения яркости.





Дизеринг исходной фотографии в «полный рост». На краях изображения на темном фоне слева, вверху и справа хорошо заметна неконсистентность распределения белых точек

Клиппинг фрагмента размером 300х300 точек не избавляет от артефактов, так как обработка любого изображения всегда начинается с верхнего левого угла:


Clip & Convert – артефакты хорошо заметны

Избавиться от этого негативного эффекта можно, сохранив дизеринг полноразмерного изображения в формате 1bpp и использовать его как исходный файл в программе, вырезая нужный размер:


Full Size To 1bpp, Save, Load As Input & Clip – артефактов нет

Существуют «змеевидные» реализации алгоритмов дизеринга, меняющие направление прохода массива пикселов после каждой горизонтальной строки, однако и они не устранят артефакты самых верхних строк.

Error-Diffusion Dithering vs Thresholding, или когда дизеринг не помогает

Полезность дизеринга как технологии сомнений не вызывает, но его применимость в нашем конкретном случае (для монохромных LCD небольшого разрешения) оправдана далеко не всегда. Самые мелкие детали дизеринг «рассеивает по окрестностям», что для фотографий может привести к серьезной потере разборчивости и назойливым шумам:


Фотография моей очередной поделки. Рассматриваем маркировку на микросхеме. Для сравнения, под обработанные изображения помещена картинка обесцвеченного «исходника»

Текст на корпусе микросхемы при дизеринге любым методом абсолютно нечитаем (хотя он с трудом читается и на оригинальной фотографии даже при большем разрешении), но при простом квантовании можно подобрать такой порог, пусть и в ущерб остальной части изображения, при котором надпись можно различить, и, при некотором старании, идентифицировать.

Правильный текст, построчно, выглядит так:
4411Е
TP904
NTMS
+
Хотя достаточно и первой строчки, это микросхема MAXIM 4411E+.


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

На мой взгляд, дизеринг и здесь проигрывет простому квантованию.

Восприятие дизерингового изображения сильно зависит от углового размера. Или от "удельной пиксельной плотности".

Вот как выглядит дисплей с расстояния в несколько сантиметров:


(кликните по картинке для увеличения)

Исходный материал — персонаж из предыдущего сюжета

То же изображение дисплея в масштабе около 1:1, примерно как при просмотре информации с мобильного телефона :


Персонаж тот же, только в черно-белом варианте. «А то я похожа на Шрека!»


Размер изображения эквивалентен просмотру с расстояния в 1 метр. Почти фотографическое качество

Это вполне понятно, попробуйте сравнить два дисплея одного размера, но с разным разрешением. К примеру, у меня под рукой есть гаджеты от Asus и Blackberry. Небо и земля.

Кстати, проявился интересный глюк в Windows. Первоначально все три вышеприведенных изображения были цветными, а-ля Шрек. Затем два были конвертированы в черно-белый формат. Но в проводнике все равно они показываются цветными, несмотря на то, что любой редактор открывает и показывает их правильно:


Черно-белое изображение в проводние Windows по-прежнему остается цветным

Проблема непонимания программами пиксельного формата 1bppIndexed встречается довольно часто. К примеру, при попытке загрузки на сайт www.overclockers.ru изображений формата 1bppIndexed в контейнере png, подготовленных для иллюстраций к статье, получаем ошибку:


Сайт не понимает пиксельный формат 1bppIndexed, хотя он был завернут в правильную обложку png. Пришлось увеличивать размеры изображений в несколько раз (не в пикселах, а в байтах), увеличив число bpp

При этом все графические редакторы эти иллюстрации в форматах 1bppIndexed корректно открывают и отображают.

Другие возможные полезные применения программы

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

Кроме того, можно воспользоваться тем, что программа выводит на экран изображения без внешнего обрамления и может устанавливать режим «всегда поверх остальных окон». Это может пригодиться, если приходится часто работать с электронной технической документацией, ссылающейся на иллюстрации в разных частях документов. Необходимые иллюстрации следует предварительно скопировать в файлы, а для их открытия и размещения воспользоваться предлагаемой программой:


(кликните по картинке для увеличения)

Иллюстрации, открытые программой, на фоне основного документа

Всем открытым через программу изображениям присваиваем статус «Orphan» и «Topmost». Теперь любую картинку можно быстро сдвинуть в нужное место или минимизировать, при восстановлении она вновь появится на прежнем месте, а прокрутка или работа с основным документом не затрагивают их видимость и расположение.


Заключение

Программа написана на С#, полностью на управляемом коде, за исключением нескольких операций Marshall.Copy для перемещения массивов даных графических файлов, и без использования WinApi.

Можно еще поработать над распараллеливанием алгоритма дизеринга, несмотря на то, что даже г-н Кнут высказался, что алгоритм Флойда-Штейнберга является классическим образцом последовательного алгоритма и не распараллеливается. На самом деле, все это достаточно просто делается при использовани не построчного направления прохода массива, а диагонального. Только вот на эту безделушку уже ушло две недели времени, поэтому дальнейшие модификации пока не планируются. Еще проще распараллелить генерацию выходного кода и на многоядерниках будет заметен прирост скорости. Но и сейчас на Sempron 3100+ 1800МГц для картинки 5000х4000 пикселов генерация кода длится немногим более 10 секунд (текстовый файл будет более 13 мегабайт), для 800х600 — менее секунды. Поэтому прямой необходимости в этом нет.

Следующим шагом в развитии проекта станет обработка изображений с выходным файлом для цветных LCD, с оптимизированной палитрой в 256 цветов и более. Но это только когда я вплотную начну заниматься цветными дисплеями, то есть осенью.

Надеюсь, кому-нибудь эта программа может пригодиться и в текущем варианте.

Автор не удержался и воспользовался без разрешения фотографией детеныша долгопята, выложенной в интернете на сайте mail.ru. Кроме просто очаровательного существа, она содержит и темный фон, идеально подошедший под иллюстрацию артефактов дизеринга.

Изображения существ женского пола принадлежат моей дочери (или она им принадлежит). Мужские силуэты - авторства Микеланджело.

Деньги тоже были не мои. Мои - вот такие:


Самая твердая валюта в мире (после латвийского лата)

Помогал выводить все безобразия на экран LCD DOGM-128e микроконтроллер ATMega32U4, сгенерированный программой код без изменения использовался в среде разработки AVR Studio 4.18.

Скачать последнюю версию программы, высказать замечания и предложения можно здесь.

Zauropod,
6 июля 2010 года


Telegram-канал @overclockers_news - это удобный способ следить за новыми материалами на сайте. С картинками, расширенными описаниями и без рекламы.
Оценитe материал

Возможно вас заинтересует

Популярные новости

Сейчас обсуждают