Такая задачка.
Есть два цвета принятые как основные. Палитра 8bpp (rrrgggbb).
Нужно привести (приравнять) третий цвет к одному из основных цветов, который больше всего подходит.
Может кто подскажет алгоритм или направление куда рыть?
Вид для печати
Такая задачка.
Есть два цвета принятые как основные. Палитра 8bpp (rrrgggbb).
Нужно привести (приравнять) третий цвет к одному из основных цветов, который больше всего подходит.
Может кто подскажет алгоритм или направление куда рыть?
как вариант -покурить сырки bmp2scr или другого продвинутого конвертера. или, как вариант, почитать про квантизацию цветов например.
Ответ найден (но ещё не тестировал). Поиск ближайшего цвета в палитре.
Этот алгоритм Вам может понадобиться когда например нужно перекодировать картинку с одной палитры на другую. Для решения рассмотрим более простую задачу - нужно найти в некоторой палитре из n цветов, цвет максимально похожий на некоторый заданный цвет.
Введем обозначения:
(R0,G0,B0) - цвет, аналог которого нужно найти в палитре.
(Ri,Gi,Bi) - i-тый цвет в палитре.
Различие цветов будем оценивать с помощью следующей функции:
fi = 30*(Ri-R0)2+59*(Gi-G0)2+11*(Bi-B0)2.
Множители 30;59;11 - отражают различную чувствительность человеческого глаза к красному,зеленому и синему цветам соответственно. Далее мы поочереди перебираем все цвета палитры и ищем цвет, для которого fi принимает минимальное значение. Это и будет искомый цвет.
Код:// структуры
typedef struct RGB_type
{
char r,g,b;
} RGB;
typedef struct Pal_type
{
int n; // число цветов в палитре
RGB* C;
} Pal;
// это подпрограмма поиска
// P - палитра
// С - цвет, который требуется найти
// Возвращаемое значение - индекс цвета в палитре
int FindColor(Pal *P,RGB *C)
{
int i, fi, best_color, f_min=1000000;
for(i=0;i<P->n,i++)
{
fi=30*(P->C.r-C->r)*(P->C.r-C->r)+
59*(P->C.g-C->g)*(P->C.g-C->g)+
11*(P->C.b-C->b)*(P->C.b-C->b);
if(fi<f_min){best_color=i,f_min=fi;}
}
return(best_color); }
У меня была задача преобразовать полноцветные картинки RGB888
в палитру для Spec256. В палитре - 256 цветов в кодировке RGB888.
В картинках, где преобладал синий цвет, поиск минимума отличий
был лучше по формуле 1R+1G+1B вместо 3R+6G+1B.
В других наоборот.
Вложение 67771
Вложение 67772
Вложение 67773
Вложение 67774
Вложение 67775
Вложение 67776
...отображаемым на устройстве древнего стандарта NTSC. Для других стандартов другие пр0центы:
http://www.brucelindbloom.com/index....YZ_Matrix.html (в матрицах смотреть на вторую строку)
Lethargeek, И что лучше взять для Профи 5.06, палитра 16 из 256 (rrrgggbb) с выводом на жк монитор?
Я не спец по графике, можно для таких ткнуть пальцем? Была бы одна матрица, а там целый веер.
tae1980, лучше - знать, на какой стандарт рассчитывал автор пикчи :)
да не парься, просто напиши конвертер с выводом кучи вариантов всех сразу
просматривай потом результаты и выбирай каждый раз один на свой вкус
В продолжении темы.
В текущей версии конвектора изображения под экран Profi реализованы две схемы выборки цветов для байта:
1. Находим два самых частых цвета, остальные приводим к ним.
2. То же, но если по краям находятся два самых светлых или самых темных цвета, приводом все цвета к ним.
Начитался про квантизацию изображений, но тут не много другая задача. Не вижу возможности применить её здесь. Или я не прав?
Вопрос: можно ли улучшить качество? Будут ли советы, рекомендации?
Вот два примера:
Скрытый текст
Скрытый текст
Про дизеринг напомнить?
https://ru.wikipedia.org/wiki/Дизеринг
marinovsoft, думал о нем. Но для меня это сложно.
Поступаю так в фотошопе сначала индексирую цвет к 256 в палитре Профи. Потом делаю цвет снова 24 битным. После привожу к 16 цветам. Такая последовательность, так как фотошоп не позволяет привести к 16 цветам если загружена палитра 256 цветов.
если я правильно понимаю, то квантизацию и дизеринг изображения делает при этих манипуляциях фотошоп.
Я же беря подготовленный файл, привожу палитру 24bpp к палитре Профи и объединяю последовательность из 8 точек в байт. Так как у Профи 2 цвета на 8 точек. Для чего нужно выкинуть до 6 цветов, приведя их к двум основным (правила их выбора из 8 возможных описал выше). От сюда и вылазит "размазывание" картинок.
Думаю дизеринг в данной ситуации мог бы помочь "сгладить" изображение. Но вот как его организовать я не пойму.
ну какбэ https://en.wikipedia.org/wiki/Dither
- - - Добавлено - - -
и далее по ссылкам под картинками, например
https://en.wikipedia.org/wiki/Floyd–Steinberg_dithering
формулы простые совсем
Lethargeek, формулы может и просты, только вот хорошо бы ещё и разбираться в теме, с чем у меня туго, так как от графики и разных художеств я очень далёк. Мозги заточены под другое. Тут просто выхода иного нет :)
Теорию уже немного начитался. Тут вот в чём вопрос: все статьи относятся к картинкам где у каждого пикселя свой цвет. На Профи же два цвета на 8 точек. То есть понятие "левый"/"нижний" пиксель не очевидное. Если пиксель в начале байта, какой пиксель считать "слева", тот который в этом байте или тот который уже в следующем байте?
Как теорию подтянуть под наши реали?
Изначально картинки готовятся во внешних программах, они всё это проделывают сами. "Размытие" получается уже после адаптации к экрану Профи. Когда применять теорию и какую? Не пойму как в теории перейти от цвета на точку, к двум цветам на байт.
Применять что-то после адаптации уже поздно, многие детали утеряны. Применять до - так оно как бы уже применялась (во внешних программах). ИМХО тут вопрос посложнее да же приведения к двум цветам. Тут как нужно и цвета сохранить, и пиксели встроить так что бы сохранить детали.
Мне не хватает теоретически-практических знаний. То что для художника очевидно, для меня темный лес.
Есть мысль сделать два прохода. На первом приводим как сейчас. На втором каждый пиксель результата сравниваем с оригиналом, если он стал темнее/светлее более чем на некий порядок, меняем его значение.
при распределении ошибки попробуй выбирать внизу ближайший цвет из доступных двух
для начала сделай в один проход
Извини, если достал.
На первом этапе нет двух цветов на байт, у каждого пикселя свой цвет.
Нужно сначала привести всю картинку к двум цветам на байт? Но тогда теряются детали.
Или берем первые 8 точек, приводим их к двум цветам, и полученную общую ошибка на байт распределяем так же на 8 точек? А что делать с "деталями" в первом байте? Мы их теряем?
А может так, берем за основу два крайних цвета в байте, а для средних 6 из сочетания цвета и пикселей (дизеринга) пытаемся найти оптимальную комбинацию?
С одной стороны не вижу необходимости двигаться по вертикали, так как две соседние по вертикали точки могут иметь разные цвета и они уже обработаны по внешних программах.
С другой стороны, учет (и влияние) вертикальных соседей даст возможность применять более хитрые пиксельные маски (забыл правильно название) для цвета.
Нужна некая комбинация из методов поучения двухцветных и 16 цветных картинок. Когда часть цветов эмулирются плотностью пикселей с учетом деления на байты. Возможно стоит работать с исходными файлами с числом цветов более 16. Но от одной мысли об этом у меня начинаются головные боли.
ну тогда переводи построчно в два цвета, а ошибку вниз сноси попиксельно
потом переходишь к этой уже изменённой нижней строке и повторяешь