Просмотр полной версии : Чанка 2х2
Ищу материал по организации чанки 2х2.
Как грамотно построить блоки чанки? Их можно сделать приличное количество, но большая часть будет зеркальным отображением друг друга. Нужно понять, какие конструкции блоков лучше всего взять и как распределить их по "яркости".
Хочу попробовать применить технология при конверсии картинок с IBM под экран Профи.
Из ходя из структуры экрана, на 4 блок чанки 2х2 можно будет использовать 4 цвета, 2 для верхней и 2 для нижней линии, но общих для линии из 4 блоков чанки.
Что видится в первом приближении.
Берем два вертикальных байта графики. Для каждого находим:
* два самых частых цвета, или по другим критериям (например, самые яркие/темный цвета)
* выстраиваем все используемые цвета по яркости (на основе приведения цвета к градации серости).
* как-то цвета нужно соотнести с чанками или построить чанки из ходя из текущих условий.
После чего если цветов в обоих байтов всего один или два, выводим как есть.
Если в одном из двух байтов цветов 3 и более, начинаем обработку. Для 4 точек 2х2 исходной картинки находим усредненный цвет, и заменяем их на соответствующую ему чанку. Но вот как понять как она должна выглядеть?
Как рассчитывать чанки: для каждой линии из 4 блоков с учетом их цветов или для всей картинки сразу?
Есть только общая идея. Нужна консультация художника и других знающих людей.
чанки 2х2 тут не причем, они используются для картинок иным методом.
Генерация описана здесь, например:
https://zxaaa.net/view_demo.php?id=7885
Shiny, Спасибо, материал очень хороший. Главное очень доходчивый и с примерами. Что встречается очень редко.
Но ИМХО проблема с конверсией картинок для Профи более сложная. Весь материал посвящен картинкам с одинаковым цветовым разрешения на всей площади. Не важно это два цвета или 256 цветов.
Тогда как на Профи 2 цвета на 8 точек. От сюда я не пониманию как разбрасывать ошибку. Например, берем первый бит в байте, куда бросать его ошибку? В следующий бит или в следующий байт? Кидать в бит в 90% бесполезно, так как они взаимосвязанные.
Подготовка изображения для конверсии начинается с его обработке во внешних программах (например фотошоп), где оно масштабируется, цвета приводиться к 16 из 256 палитры Ппрофи. То есть всё что описано в материале делает внешняя программа. Мне нужно это перенести в формат Профи.
На текущий день я реализовал 6 алгоритмов расчета 2 цветов на 8 точек. Вот пример их работы.
http://www.imageup.ru/img11/3269415/2019-01-25_23-58-52.png (http://www.imageup.ru/img11/3269415/2019-01-25_23-58-52.png.html)
На мой взгляд лучший результат у шестого метода. Но и там видны горизонтальные полосы, возникшие из-за объединения цветов, когда в исходных 8 точках было 3 и более цвета. Моя задача избавиться от них. Вот как это сделать я пока не знаю.
Тут и возникла идея использовать пиксельные маски для цветов. Но как это сделать внутри одной линии тоже не понятно. Что и заставило подумать о чанках. Думаю их использование позволит передать более 16 цветов на картинки и избавиться от горизонтальных полос.
Так что вопрос открыт.
Lethargeek
27.01.2019, 04:33
Тогда как на Профи 2 цвета на 8 точек. От сюда я не пониманию как разбрасывать ошибку. Например, берем первый бит в байте, куда бросать его ошибку? В следующий бит или в следующий байт? Кидать в бит в 90% бесполезно, так как они взаимосвязанные
Блин. Ты не биты обрабатываешь, а ПИКСЕЛИ. Ошибку бросаешь в те же самые ПИКСЕЛИ, в которые предписывает конкретный алгоритм, какой ты там выберешь (того же Флойда-Стейнберга). Вопрос к том, к каким ЦВЕТАМ ты ПРИВОДИШЬ пиксели. Всей-то разницы, что при конверсиях на пц обычно заранее задают просто одинаковую глубину цвета (битность) любого пикселя, но самом деле с тем же успехом задавать можно несколько произвольных целевых палитр с произвольным разбиением исходного изображения на участки любых форм и размеров. У тебя участки будут группами 8x1 пикселей, каждая со своей целевой палитрой в два цвета, к ним пошагово и приводишь. А еще НЕПРИВЕДЁННЫЕ пиксели, включая правые в той же группе, могут быть пока что ЛЮБОГО цвета. А также отсюда следует, что задача выбора целевых палитр - полностью самостоятельная, по своему какому-либо критерию. Притом выбор может быть статическим (все целевые палитры для всех групп целой картинки задать заранее) и динамическим (пересчитываешь целевую палитру каждый раз при переходе вправо в новую группу). Пробуй оба.
Открыт вопрос или нет, но есть реализации разные: - покурить dithering 16 colors; - поизучать исходники bmp2scr(хотя автор сам признает, что в них трудно разобраться)
Если не возражаешь, давай детально разберем твоё сообщение. Так сказать для так неучей как я.
Блин. Ты не биты обрабатываешь, а ПИКСЕЛИ. Ошибку бросаешь в те же самые ПИКСЕЛИ, в которые предписывает конкретный алгоритм, какой ты там выберешь (того же Флойда-Стейнберга). Вопрос к том, к каким ЦВЕТАМ ты ПРИВОДИШЬ пиксели.
1. ИМХО с сточки зрения Профи это всё таки биты, а то что раскрашены, это частный случай их применения. Я кончено могу ошибаться, то это диктует физическое строение экрана.
2. Все описанный метод УЖЕ применялись с данной картинке (я использую фотошоп). Картинка уже 16 цветов из 256 в палитре Профи. Есть смыл применять их ещё раз? Тем более, что шаг между цветами у Профи весьма ограничен.
3. При переводе цвета в биты у нас из 3-8 цветов остается только 2. И тут дилемма, какие оставить. 6 удаляемых цветов привожу по формуле к ближайшему из двух основных цветов:
Цитата:
(R0,G0,B0) - цвет, аналог которого нужно найти в палитре.
(Ri,Gi,Bi) - i-тый цвет в палитре.
Различие цветов будем оценивать с помощью следующей функции: fi = 30*(Ri-R0)2+59*(Gi-G0)2+11*(Bi-B0)2.
Для которого fi принимает минимальное значение, это и будет искомый цвет.
====
Выше писал, что в попытках найти лучший алгоритм было разработано 6 вариантов. Вот их описание (готовлю материал к хелпу):
1. По байту. Два самых частых цвета. - тут я думаю понятно, берем за основу два наиболее часто встречающийся цвета.
2. По байту. Два самых темных и светлых цвета. - принцип тот же, только берутся два противоположные по яркости цвета. Цвета сравниваются по градации серости.
3. Комбинированный, учёт крайних совместный. - комбинация первых двух, если оба крайних цвета максимальные/минимальные по яркости в байте, то используется второй метод, иначе первый.
4. Комбинированный, учёт крайних раздельный. - то же но крайние цвета оцениваться отдельно. Если какой либо из них самый светлый/темный цвет, он используется как один из основных, вторым использоваться самый частый. Так же есть контроль, что бы цвета не оказались одинаковыми.
5. По байту. По крайним цветам. - Тут за основу берутся два крайних цвета в байте.
6. По полубайтам. Самый частый цвет. - Вот тут интересно. После общения в эхе (особая благодарность Lethargeek, за терпение) и начитки статей, пришла мысль, что нужно как-то дробить информацию и работать с каждой частью в отдельности. А как это сделать в наших условиях? Только делить байт по полам. Что и было сделано (ох и намучился я с реализацией). Байт делиться на два полубайта, для каждого и них определяться самый частый цвет. Которые и используются как основные. Проверяться частота появления у крайних цветов каждого полубайта, если она такая же как и у признанного самым частым, то используется крайний цвет. Проводится контроль выбранных цветов, если он одинаковые, то берется следующий цвет из левого полубайты. Если цвета в нём кончились, начинаем их брать из правого полубайта.
Проблемы начинаются когда подряд идут два и более пикселя разными, но близкими цветами (например, градиент). Было 01234567, а получим 00007777 на одном и 77770000 на соседнем байте. От сюда и полосатость.
А хотелось бы получить 00070777 или иной вариант.
Если вернуться к идеи чанки то аналогичная ситуация может разрешиться так (вариант):
01234567 -> 00070777
01234567 -> 11161666
Как видно и цветов может быть больше. Только их нужно грамотно увязать.
Всей-то разницы, что при конверсиях на пц обычно заранее задают просто одинаковую глубину цвета (битность) любого пикселя, но самом деле с тем же успехом задавать можно несколько произвольных целевых палитр с произвольным разбиением исходного изображения на участки любых форм и размеров. У тебя участки будут группами 8x1 пикселей, каждая со своей целевой палитрой в два цвета, к ним пошагово и приводишь. А еще НЕПРИВЕДЁННЫЕ пиксели, включая правые в той же группе, могут быть пока что ЛЮБОГО цвета. А также отсюда следует, что задача выбора целевых палитр - полностью самостоятельная, по своему какому-либо критерию. Притом выбор может быть статическим (все целевые палитры для всех групп целой картинки задать заранее) и динамическим (пересчитываешь целевую палитру каждый раз при переходе вправо в новую группу). Пробуй оба.
Если правильно, имелось ввиду: проведение 3-8 цветов к двум основным внутри одного байта?
Предлагаемый алгоритм для каждого байта:
1. Определяем два основных цвета в байте.
2. Берем первый цвет, приводим к одному из двух цветов,
3. Получаем ошибку. (входит, что передать ошибку можем только вправо, так как байт линейный)
4. Передаем её следующему цвету в байте.
А что делать с цветами которые совпадают с основными? Ведь если цвет не первый, в него будет внесена поправка. А так как поправка не большая, то при приведении по формуле fi к одному из двух цветов, она будет по сути уничтожена. Или все эти вопросы не актуальны, и будут разрешены автоматически внутри алгоритма?
Shiny, так в том том то и вопрос, что исходники сложно читать. Я и прошу ссылки на статьи и ли объяснить. Тем более меня сейчас больше интересует теория чем практика.
Shiny, так в том том то и вопрос, что исходники сложно читать. Я и прошу ссылки на статьи и ли объяснить. Тем более меня сейчас больше интересует теория чем практика.
Честно говоря, я и сам не видел толкового описания, только решения с сырками. Тут или читать, или учиться. Другого не знаю.
Мысли в слух.
А что если так: берем две линии по 8 цветов подряд (верхняя и нижняя). Для них находим общие два самых темных и два самых светлых цвета. Самый темный и светлый цвет берутся как основные для верхнего байта, остальные для нижнего.
После чего разбиваем линии на блоки 2х2. Для каждого блока считаться среднюю яркость. После определяем значение каждого бита блока: если цвет темнее среднего бит=1, если ярче бит=0. Собираем два байта из блоков.
Непонятен смысл телодвижений. Разобраться самостоятельно? это вы форумом ошиблись, есть stackoverflow и другие ресурсы.
Написать просмотр графики под Профи? это утопия. Есть немало готовых конвертеров.
Если не ошибаюсь, 2х2 использовался в BBC Micro Image Converter (http://www2.kecskebak.co.uk/category/bbc-image-converter/)
- - - Добавлено - - -
и здесь еще:
http://kecskebak.blogspot.com/2010/
Вот отличная статья http://zxpress.ru/article.php?id=7968
Но как это состыковать с цветом, я пока не понимаю.
- - - Добавлено - - -
Написать просмотр графики под Профи? это утопия.
1. Он уже есть. Я его только улучшаю.
2. Хотите так считать ваше право.
Есть немало готовых конвертеров.
Покажите мне хотя бы один конвектор для Профи?
Он должен удовлетворять следующем двум требованиям: на выходе файлы 16 цветов из 256 в палитре Профи 2 цвета на 8 точек, формат выходного файла GRF в формате Профи.
Образцы работ приведенных выше конвекторов хуже, чем получается у меня уже сейчас под экран Профи. Хотя скорее всего это образцы работ под стандартный экран спектрума.
Lethargeek
27.01.2019, 21:07
1. ИМХО с сточки зрения Профи это всё таки биты, а то что раскрашены, это частный случай их применения. Я кончено могу ошибаться, то это диктует физическое строение экрана.
2. Все описанный метод УЖЕ применялись с данной картинке (я использую фотошоп). Картинка уже 16 цветов из 256 в палитре Профи.
Вот это-то и плохо! Еще раз говорю: ЗАБУДЬ про биты и профик, это знание сейчас только тебе мешает, сбивает с толку. У тебя задача конвертировать картинку с исходным пиксельным форматом (допустим, RGB32) в картинку с ТАКИМ ЖЕ пиксельным форматом, но с ДРУГИМИ ЦВЕТАМИ, которые умеет профик. И вот её уже потом, на самом последнем этапе, элементарно конвертируешь в свои биты.
3. При переводе цвета в биты у нас из 3-8 цветов остается только 2.
Неверно. Нужно не выбирать два цвета из имеющихся (притом уже испорченных фотошопом), а найти два НОВЫХ целевых цвета обработкой восьми оригинальных. К сожалению, объективного критерия для выбора быть не может. Я бы для начала поступил так:
1) находим субъективную яркость каждого из 8 цветов по коэффициентам матриц по прошлой ссылке
2) находим статистическую медиану по этим яркостям и делим яркости на две группы
3) находим средневзвешенную яркость для каждой группы
4) находим наиболее близкие по субъективной яркости цвета профика
Это и будут два новых ЦЕЛЕВЫХ (то есть напрямую сразу в них НЕ меняем) цвета полоски 8x1, нужных в качестве ВХОДНЫХ ДАННЫХ для совершенно самостоятельного алгоритма распределения ошибки (который сам по себе попиксельный и которому хоть на каждом шаге можно новые входные подсовывать).
Что касается фотошопа, то его лучше применить для предварительного сглаживания картинки, уборки шума, но не для конвертирования цвета.
Предлагаемый алгоритм для каждого байта:
1. Определяем два основных цвета в байте.
2. Берем первый цвет, приводим к одному из двух цветов,
3. Получаем ошибку. (входит, что передать ошибку можем только вправо, так как байт линейный)
4. Передаем её следующему цвету в байте.
Вот о чём я и говорю - постоянно рассуждаешь о битах-байтах, в результате возникают странные мысли наподобие рассуждений в скобках в п.3
Еще раз - обрабатываешь НЕ биты-байты, обрабатываешь ПИКСЕЛИ! - соответственно передать ошибку можешь в ЛЮБЫЕ ПИКСЕЛИ, вправо, вниз, по диагонали, через один - как захочется конкретному алгоритму.
Покажите мне хотя бы один конвектор для Профи?
ручками это делается. 16 цветов можно загнать в Fast Stone:
https://i110.fastpic.ru/big/2019/0127/b1/fd515b735462cd545ad2e81c8c7b7eb1.png
С другими требованиями можно поискать, наверное.
насчет .GRF не знаю, знал бы формат, то попробовал бы перенести картинку.
Lethargeek, пока я сживаюсь с основным ответом, хочу задать два косвенных вопросов.
1. Почему вы считаете, Фотошоп портит рисунка? Он же проделывает те же операции.
2. После прохождения алгоритма, на выходе получаем картинку с цветом на пиксель? И при конверсии в байт получим те же проблемы? Или можно выстроить алгоритм так, что на выходе на картинке будет два цвета на 8 точек, и тогда конверсия в байт будет элементарной?
Допустим у нас чёрно-белое изображение. 8 пикселей имеют яркость 50, 102, 54, 106, 58, 100, 62, 150. Если их преобразовать из оригинала, можем получить яркости 55 110 55 110 55 110 55 110. Два цвета, с малой погрешностью, причём недостаток яркости последнего пикселя можем не напрягаясь перебросить на соседний, в любом направлении - вверх, вниз, вправо... После приведения редактором картинки к 16 цветам получаем номера цветов 4 9 4 10 5 9 5 15 и мучительно думаем что с этим богатством теперь делать, потому что цветов в этой группе аж 5, и переброс погрешности в 16-цветной RGB палитре нетривиальная задача.
Lethargeek
28.01.2019, 11:21
1. Почему вы считаете, Фотошоп портит рисунка? Он же проделывает те же операции.
Если те же, то зачем писать свой конвертер и к чему вообще все вопросы? Если нет, то ненужная потеря информации происходит.
2. После прохождения алгоритма, на выходе получаем картинку с цветом на пиксель? И при конверсии в байт получим те же проблемы? Или можно выстроить алгоритм так, что на выходе на картинке будет два цвета на 8 точек, и тогда конверсия в байт будет элементарной?
Так именно об этом и говорил.
- - - Добавлено - - -
и переброс погрешности в 16-цветной RGB палитре нетривиальная задача.
ё-моё, ну так и не надо в 16-цветной фигнёй страдать, вся конверсия производится в палитре оригинала
а точнее даже, в общем случае - в наиболее богатой палитре, покрывающей и результат, и оригинал
просто в получившейся картинке остаётся намного меньшее количество уникальных цветов
Lethargeek, это сообщение предназначалось для tae1980, и я полностью согласен что не надо страдать 16-цветной фигнёй :)
Из спортивного интереса пробовал выводить видео микроконтроллером, использовал дельта-кодирование 8 бит на пиксель и некоторые другие способы сжатия. Самому теперь интересно попробовать оптимизировать изображение в такой формат и посмотреть что из этого получится.
https://i84.fastpic.ru/big/2019/0128/92/76427a40710b5f7843c6e24e8255a192.gif
хех, страдал я 16-цветной фигней на тс-конф. выглядело неплохо.
Заранее прошу прощения за тупиз. Повторюсь, я геодезист, по этому эта тема очень далека от меня, а школьный курс алгебры я благополучно забыл 20 лет назад. Так что мне банально не хватает базы.
Вот это-то и плохо! Еще раз говорю: ЗАБУДЬ про биты и профик, это знание сейчас только тебе мешает, сбивает с толку. У тебя задача конвертировать картинку с исходным пиксельным форматом (допустим, RGB32) в картинку с ТАКИМ ЖЕ пиксельным форматом, но с ДРУГИМИ ЦВЕТАМИ, которые умеет профик. И вот её уже потом, на самом последнем этапе, элементарно конвертируешь в свои биты.
Всё, забыли.
Неверно. Нужно не выбирать два цвета из имеющихся (притом уже испорченных фотошопом), а найти два НОВЫХ целевых цвета обработкой восьми оригинальных. К сожалению, объективного критерия для выбора быть не может. Я бы для начала поступил так:
1) находим субъективную яркость каждого из 8 цветов по коэффициентам матриц по прошлой ссылке
То есть для каждого цвета применяем эту формулу: "RGB Значение яркости = 0,3 R + 0,59 G + 0,11 B"?
Нашел статью "Об относительной яркости, или насколько живучим бывает легаси (https://habr.com/ru/post/304210/)"
Исходя из нее формула должна быть такой: Y= 0.2126R + 0.7152G + 0,0722В
Но у Профи слабая синяя составляющийся цвета только 2 бита, тогда как у остальных 3. Нужно ли здесь, что-то корректировать?
2) находим статистическую медиану по этим яркостям и делим яркости на две группы
Сортируем полученные значения от большего к меньшему, и за медиану берем то значение которое окажется в центре?
Или нашел такое: "
* Если у вас нечетное количество чисел, вычеркните левое крайнее число, затем правое крайнее число и так далее. Один оставшийся номер и будет искомой медианой. Если вам дан ряд чисел 4, 7, 8, 11, 21, тогда 8 — медиана, так как 8 стоит посередине.
* Если у вас четное количество чисел, вычеркните по одному числу с каждой стороны, пока у вас не останется два числа посередине. Сложите их и разделите на два. Это и есть значение медианы. Если вам дан ряд чисел 1, 2, 5, 3, 7, 10, то два средних числа — это 5 и 3. Сложим 5 и 3, получим 8, разделим на два, получим 4. Это и есть медиана."
3) находим средневзвешенную яркость для каждой группы
За вес берётся количество повторения цвета?
Тогда: для каждого цвета: яркость цвет*число повторений
Складываем получившееся и делим на размер группы.
4) находим наиболее близкие по субъективной яркости цвета профика
Это и будут два новых ЦЕЛЕВЫХ (то есть напрямую сразу в них НЕ меняем) цвета полоски 8x1, нужных в качестве ВХОДНЫХ ДАННЫХ для совершенно самостоятельного алгоритма распределения ошибки (который сам по себе попиксельный и которому хоть на каждом шаге можно новые входные подсовывать).
То есть нужно все цвета Профи перевести по формуле из первого пункта в серый цвет. И потом найти ближайший?
Сначала мы картинку прогоняем через алгоритма распределения ошибки к 16 из 256 цветам, а потом собираем байт по этому алгоритму?
А приводить цвета внутри байта к каким? К 16 или 256? Если к 256, потом снова нужно прогоняем через алгоритма распределения ошибки?
Lethargeek, попробовал применить описанный алгоритм на 16 цветной картинке, получил такой результат.
http://www.imageup.ru/img231/3270958/2019-01-28_23-38-11.png (http://www.imageup.ru/img231/3270958/2019-01-28_23-38-11.png.html)
http://www.imageup.ru/img231/3270981/2019-01-28_23-47-40.png (http://www.imageup.ru/img231/3270981/2019-01-28_23-47-40.png.html)
Lethargeek
29.01.2019, 01:06
Но у Профи слабая синяя составляющийся цвета только 2 бита, тогда как у остальных 3. Нужно ли здесь, что-то корректировать?
ничего, в формулу идут относительные доли от разных максимальных уровней компонент
...
ok (хотя я не утверждаю, что это лучший метод, но для начала)
Сначала мы картинку прогоняем через алгоритма распределения ошибки к 16 из 256 цветам, а потом собираем байт по этому алгоритму?
:v2_dizzy_facepalm:
Это и будут два новых ЦЕЛЕВЫХ (то есть напрямую сразу в них НЕ меняем) цвета полоски 8x1, нужных в качестве ВХОДНЫХ ДАННЫХ для совершенно самостоятельного алгоритма распределения ошибки (который сам по себе попиксельный и которому хоть на каждом шаге можно новые входные подсовывать).
Входных данных! Даже выделено нарочно! Вот как можно "сначала прогонять алгоритм", для которого еще не готовы входные данные?? И про байты не было там ни слова!
попробовал применить описанный алгоритм на 16 цветной картинке,
1) сначала желательно найти оригинальную (и не слишком сильно пожатую) фотографию в RGB32 формате, а не испорченное штрихованное убожество
2) даже если такая не нашлась, всё равно конвертировать сперва картинку в этот формат, потому что для распределения ошибки кодировка цвета нужна прямая
3) выбрать целевую палитру профика из 16 цветов (а вот хз как, это отдельная задача, для начала попробуй фиксированную или подбери творчески)
4) вычислить все целевые цвета для всех групп 8x1 пикселей и отдельно запомнить их (с самой картинкой еще ничего не делаем!)
5) вот только теперь прогнать по картинке алгоритм распределения ошибки, в каждой группе приводя к двум целевым цветам этой группы
6) полученная картинка (всё в том же формате RGB32) должна элементарно конвертироваться для профи, поскольку в ней всего 16 уникальных цветов
1) сначала желательно найти оригинальную (и не слишком сильно пожатую) фотографию в RGB32 формате, а не испорченное штрихованное убожество
2) даже если такая не нашлась, всё равно конвертировать сперва картинку в этот формат, потому что для распределения ошибки кодировка цвета нужна прямая
Исходные разумеется есть, и нет проблема взять другие.
3) выбрать целевую палитру профика из 16 цветов (а вот хз как, это отдельная задача, для начала попробуй фиксированную или подбери творчески)
Фиг с ним, взяли 16 стандартных цветов спектрума в формате RGB24
Видел статьи по подбору палитры, но надеялся это меня не коснется.
Пока можно в фотошопе приводить к 16 цветам, и эту палитру брать за основу.
3) вычислить все целевые цвета для всех групп 8x1 пикселей и отдельно запомнить их (с самой картинкой еще ничего не делаем!)
В памяти всегда исходная картинка, картинка в 8Bpp (она служит источником для перевода и сюда же возвращаться результат для отображения на IBM) и сама GRF, которую так же можно использовать как источник информации.
То есть, из исходной картинке рассчитываем массив, в котором для каждых 8 точек храним два 2 из 16 цветов.
4) вот только теперь прогнать по картинке алгоритм распределения ошибки, в каждой группе приводя к двум целевым цветам этой группы
* берём первый пиксель, приводим его к одному из 2 для данной восьмерки цветов. Путем нахождения ближайшего по серости.
* получаем ошибку.
* передаем ошибка следующим пикселям: влево, влево-вниз, вниз.
И так для всей картинки, только для каждых 8 точек свой набор из 2 цветов.
5) полученная картинка (всё в том же формате RGB32) должна элементарно конвертироваться для профи, поскольку в ней всего 16 уникальных цветов
Если ни чего не путаю в RGB32, последний байт отвечает за прозрачность и в BMP не использоваться. Так что для BMP RGB24=RGB32.
Lethargeek
29.01.2019, 11:15
В памяти всегда исходная картинка, картинка в 8Bpp
какой 8bpp? по 8 на каждую компоненту, итого 24 (RGB32 я по привычке пишу програмерской)
или даже больше, чем по 8, для пущей точности, это же не отображаемая картинка,
а чисто служебное представление, не обязано в правильном стандартном формате быть
и сама GRF, которую так же можно использовать как источник информации
не нужно как источник (собственно, какой такой информации?) - это результатом конечным будет
* передаем ошибка следующим пикселям: влево, влево-вниз, вниз.
зависит от конкретного алгоритма и направления движения по строке, но всегда "вперёд" - в еще не приведённые пиксели
(для флойда-стейнберга, если слева направо двигаться, то ошибка в правую и в три нижних, с разными коэфициентами)
какой 8bpp? по 8 на каждую компоненту, итого 24 (RGB32 я по привычке пишу програмерской)
или даже больше, чем по 8, для пущей точности, это же не отображаемая картинка,
а чисто служебное представление, не обязано в правильном стандартном формате быть
Это просто перечислил текущие буфера.
В BMP 8bpp поровожу обратное преобразование из GRF, что бы иметь возможность видеть результат сразу без железного Профи.
не нужно как источник (собственно, какой такой информации?) - это результатом конечным будет
Информацию о двух цветах можно сразу запихнуть сюда, вместо массива. Минимум, но экономия.
зависит от конкретного алгоритма и направления движения по строке, но всегда "вперёд" - в еще не приведённые пиксели
(для флойда-стейнберга, если слева направо двигаться, то ошибка в правую и в три нижних, с разными коэфициентами)
Хорошо. Значит утверждаем приведенный алгоритм. Мне нужно пару дней на реализация (приходиться отвлекаться на работу, к сожалению).
Lethargeek
29.01.2019, 12:47
Это просто перечислил текущие буфера.
ааа, не понял с недосыпу (тебе надо было двоеточие там поставить))
Информацию о двух цветах можно сразу запихнуть сюда, вместо массива. Минимум, но экономия.
так там в другом формате цвета же будут, конвертировать обратно потом придётся
ну, да сам решай, есть ли смысл в такой экономии
Lethargeek, сегодня получил такой результат:
http://www.imageup.ru/img289/3275882/2019-02-03_18-53-38.jpg (http://www.imageup.ru/img289/3275882/2019-02-03_18-53-38.jpg.html)
Палитру 16 цветов брал ту которую создал фотошоп.
Попробу понять где накосячил.
Начал анализировать ход расчетов.
В первых же 8 пикселях имеем разных 7 цветов. После расчета серости и разбиение на две группы получаем:
для первой группы 64 значение серости и 5 раз встречаться (суммарный вес), для второй значение серости 60 и встреться (суммарный вес) 3 раза.
При подборе цвета из палитры 16 цветов имеем следующее расчеты:
http://www.imageup.ru/img289/3275903/2019-02-03_20-00-04.png (http://www.imageup.ru/img289/3275903/2019-02-03_20-00-04.png.html)
где 1) это передпаваемые данные серости группы цветов
далее, разница между серостью цвета в палитре и переданным цветов
далее, серость цвета в палитре
Я беру тот цвет палитры, у которого разница серости с переданным цветом ближе к нулю. Получается, что для обоих групп берется 6 цвет. То есть 7 исходных цветов прировнялись к одному.
Что-то тут не так....
Lethargeek
04.02.2019, 01:33
tae1980, ну что значит "приравнялись"?? Ты найти сначала должен ЦЕЛЕВЫЕ цвета, и ничего к ним не сразу и не приравнивать, а потом уже ПРИВОДИТЬ, распределяя ошибку. Никакой разницы не надо пока считать. Вот у тебя есть две групповых яркости, теперь из 16-цветной палитры выбирай два разных цвета, самых близких к твоим цифрам (61 и 65). Именно два РАЗНЫХ, даже если один из них намного дальше от этих цифр, чем они друг от друга. Это будут целевые цвета полоски, когда рассчитаешь так же для всех полосок, только тогда прогоняй распределение ошибки по всей картинке.
И начать, наверно, лучше с конвертации чёрно-белой версии оригинальной картинки в серую 16-цветную палитру.
- - - Добавлено - - -
и на всякий случай напоминаю, что ошибку надо распределять отдельно, независимо для каждой цветокомпоненты (а то мало ли))
Lethargeek, Разуметься все действия по оговоренному алгоритму.
Цикл 1. Подбор двух цветов на 8 точек. Путем расчета серости для каждой точки, сортировки 8 точек по серости, делением на две группы по медиане, нахождение средневзвешенного цвета для группа (за вес принимаем число рез сколько цвет встретился).
Цикл 2. Независимо от Цикла 1, для исходной картинки разбрасываем невязки.
Цикл 3. На основе Циклов 1 и 2 находим для каждой точки цвет (один из двух найденных в Цикле 1).
Так как внутри есть ещё другие мелкие циклы но для каждой точки, все работает очень долго (используемый язык не Си). Как укоротит ума не приложу. Объединять циклов в общем безполезно, так как на организацию цикла тратиться не много времени, а вот объем расчетов при этом не изменится.
Так вот, то что я назвал "приравнивание" происходит на первом цикле. Когда подряд идут несколько разных, но близких цветов. При нахождении двух средневзвешенных серостей, получаем очень близкие значение. Специально привел значения серости для палитры 16 цветов (правда в не очень удобном виде). Видно, что шаг серости очень значителен и измеряется десятками. В описном случае, для 8 точек было получены близкие значения средневзвешенной серости 60 и 64 (разница 4 единицы), что при вело к выбору одного цвета для обоих групп. По этому как бы не сработали циклы 2 и 3, на экране будет линий одного цвета.
Подобная ситуация наблюдается по большей части изображения, разбор на два цвета происходит только в самых контрастных местах.
Пробовал в таких случаях в Цикле 1 принудительно брать два самых подходящих цвета. Но в Цикле 3, они всё равно приводятся к одному самому подходящему.
Возможно нужно как-то "увеличивать" разницу средневзвешенной серости двух групп (получаться от 5 до 10 раз). Обоснованием сможет служить резкое сужение диапазон цветов с 16М до 2.
Lethargeek
04.02.2019, 15:46
Пробовал в таких случаях в Цикле 1 принудительно брать два самых подходящих цвета. Но в Цикле 3, они всё равно приводятся к одному самому подходящему.
что за циклы? это явно не мои пункты, распиши уже тогда подробно свой алгоритм
фокус в том, что при распределении ошибки еще неприведённые пиксели обязаны стать контрастнее
и если здесь всё правильно, то не должно бы получаться кучи таких полосок
а при конверсии чёрно-белого оригинала что получилось?
еще стоит попробовать выбирать целевые цвета по крайностям:
темнее самого тёмного и ярче самого яркого в той полоске
что за циклы? это явно не мои пункты, распиши уже тогда подробно свой алгоритм
Цикл1. Идет последовательный перебор всех строк
В каждой строке последовательно берутся пиксели по 8 шт.
Для каждого пикселя считается серость и заноситься в массив (#Gray=0.2126*#24rrr + 0.7152*#24ggg + 0.0722*#24bbb). Массив сразу сортируется от самого светлого к самому темному.
Медину не нахожу, так как число цветов до 8, проще через if. Делим массив на два блока.
Для каждого блока считаем средневзвешенное значение: СуммаN(СеростьN*ЧислоПовтор овN) / ОбщееЧислоПовторов всех цветов
Для каждого блока определяем номер цвета в палитре 16, для чего находим ближайший цвет по серости.
Создаем массив, где каждого пикселя храниться два возможных цвета.
Цикл2. Распределяем ошибку.
Каждый пиксель приравниваться к ближайшему из двух рассчитанных цветов.
Считаться ошибка: #ERR.r=#24rrr-#24rrr1; #ERR.g=#24ggg-#24ggg1; #ERR.b=#24bbb-#24bbb1. Где 24xxx - исходный цвет пикселя, 24xxx1 - цвет к которому привели.
Распределяем ошибку:
вправо 7/16 ;
вниз-назад 3/16;
вниз 5/16;
вниз-вперед 1/16.
данные хранятся в массиве в виде строк BMP. Собственно это и вывожу на экран.
Цикл3. Перевод в GRF. Не реализован.
фокус в том, что при распределении ошибки еще неприведённые пиксели обязаны стать контрастнее
и если здесь всё правильно, то не должно бы получаться кучи таких полосок
да, но цвета мы определяем по исходному изображению. Толку от контрастности если оба цвета получились одинаковыми?
а при конверсии чёрно-белого оригинала что получилось?
Не приводил.
еще стоит попробовать выбирать целевые цвета по крайностям:
темнее самого тёмного и ярче самого яркого в той полоске
Есть подобный режим для 16 цветов, результат не очень, так как в ряде мест высвечиваются не главные цвета. Например: на небе. Но возможно тут заработает по другому, так как идет разброс ошибки.
Lethargeek
04.02.2019, 19:14
Для каждого блока определяем номер цвета в палитре 16, для чего находим ближайший цвет по серости.
неправильно - нужно два не самых ближайших, а два таких, между яркостями которых лежат обе яркости блоков
Распределяем ошибку:
влево 7/16 ;
почему влево? справа налево по строке движемся?
и всё-таки начни с чёрно-белого
неправильно - нужно два не самых ближайших, а два таких, между яркостями которых лежат обе яркости блоков
Имелось ввиду. Что если для двух блоков будет определен одинаковый цвет, а в исходных данных более 1 цвета, то выбираем этот цвет и второй самый ближний.
На 16 цветах очень хорошо показал себя метод определения самого частого цвета для каждых 4 точек из 8. Так как важно не просто найти два самых частых цвета, а соблюсти переход цвета между байтами (группами из 8 точек). Без этого линии которые идут под углом теряют плавность и получаются угловатыми, так как цвета внутри группы необязательно распределены равномерно. Но и просто хватать крайние нельзя.
Думаю можно упростить подбор основных цветов до этого.
Lethargeek
05.02.2019, 06:52
Имелось ввиду. Что если для двух блоков будет определен одинаковый цвет, а в исходных данных более 1 цвета, то выбираем этот цвет и второй самый ближний.
нет, и это неправильно, для нормального распределения ошибки нужно полное покрытие, повторяю:
два таких, между яркостями которых лежат обе яркости блоков
то есть, если групповые условно 4.9 и 5.1 - выбирать нужно 4 и 6 (а не 5 и 6 и не 4 и 5)
если 3.7 и 7.2 - выбираем 3 и 8 итд, а вовсе не "самый ближний"
- - - Добавлено - - -
главный минус - с ограниченной целевой палитрой могут подвернуться посторонние цвета, например, белый и чёрный вместо светло-синего и тёмно-синего
так что, возможно, для цветной картинки придётся заранее подготовить и потом перебирать на целевые несколько градиентов
потому для простоты отладки начать лучше с чёрно-белого оригинала, как говорил
а вовсе не "самый ближний"
Как писал в примере выше, получаем в двух группах 64 и 60. В палитре ближайшие цвета 66, 73. То есть для обоих групп будет возвращен цвет 66. И все 8 точек получит одинаковый цвет. По этому вторым цветом будет взят 73.
Долго думал об округление. В статьях сказано, что округлять нельзя вообще. Но у нас градации серости идут от 0 до 256, а цветов всего 16, получаем средний шаг в 16 единиц. На практике видел шаг и в 50 единиц. То есть, округлять можно в любую сторону, на результате это не отразится.
Так же я пробовал выставить все 256 цветов по значению их серости, надеялся получить плавный переход одного цвета в другой, для палитры. На практике же оказалась, что цвета перемешаны, хотя и в меньшей степени. Например, идет ряд черных оттенков, потом потом один синий оттенок и снова пошли черный. Такие аномалии есть и в других цветах. То есть используя серость для поиска ближайшего цвета, можно без проблем получить синий вместо черного. Что мне крайне не нравиться. Но другого метода поиска ближайшего цвета я не нашел.
несколько градиентов
Собственно, эту задачу я и хотел решить с помощью чанки. Исходя из палитры разработать несколько видов чанки с учетом возможных цветов. После чего просто подбираем цвета и вид чанки для группы точек 2х2.
Пробовал вместо чанки использовать для группы 2х2 и отличие точке от средней серости по группе (как при переводе в чб). Надеялся, что так получится сохранить направления основных линий.
Но получилось не ахти, как раз все линии оказались размыты, как веником прошли. Хотя может просто рано бросил тему, не найдя своих косяков.
Lethargeek
05.02.2019, 10:32
Как писал в примере выше, получаем в двух группах 64 и 60. В палитре ближайшие цвета 66, 73. То есть для обоих групп будет возвращен цвет 66. И все 8 точек получит одинаковый цвет. По этому вторым цветом будет взят 73.
говорю же - НЕПРАВИЛЬНО! нужно первым брать 66 и вторым - какой там ближайший будет меньше 60 - чтобы твои 64 и 60 находились МЕЖДУ ними
точно так же, как при конверсии в монохром любой цвет по яркости расположен между нулевой и максимальной яркостями (они же целевые цвета)
- - - Добавлено - - -
ты пойми, что цель распределения ошибки - получить ближайшую к оригиналу среднюю яркость локального участка (у тебя 8x1)
которая выражается формулой n*max+(8-n)*min; должна быть между 64 и 60; а у тебя получается даже min=66 больше чем 64
выражается формулой n*max+(8-n)*min; должна быть между 64 и 60; а у тебя получается даже min=66 больше чем 64
А нету цвета между 64 и 60.
Для данной картинке фотошоп подобрал такую палитру: 0 33 66 73 90 107 113 115 139 141 173 179 213 215 221 255.
Ближайшие цвета 33 66 73. Как быть?
CodeMaster
05.02.2019, 11:18
А нету цвета между 64 и 60.
Да не между ними, а что бы они были между, т.е. 33 и 66
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot