WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  C / C++ / Visual C++
  Из 24 -> 8

СПРОСИТЬ  +8">ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Из 24 -> 8
Rechkin опубликован 27-12-2001 18:52 MSK   Click Here to See the Profile for Rechkin   Click Here to Email Rechkin  
Как преобразовать 24битное изображение в 8битное
Исходные данные:
массив unsigned char размерности
ImageWidth x ImageHeight x 3
Я вроде понимаю, что каждый пиксель предствлен 3 байтами, переписываю исходную матрицу как средневзвешанное всех цветов, но ни чего нае выходит!
Rechkin опубликован 27-12-2001 23:19 MSK     Click Here to See the Profile for Rechkin  Click Here to Email Rechkin     
Ответье, пожалуйс
Drunkard опубликован 28-12-2001 02:27 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
8-бит это 256 цветов. Насколько мне известно, в BMP файле используется таблица цветов и математической функции переводящей из 24-бит в 8-бит нету. Т.е. если мне не изменяет память все 256 цветов заданы в самом ВМР файле. Насчет 16 цветов я уверен на все 100%. Приходилось преобразовывать 24-битное изображение в 4-битное. Я поступал так. На бумажке нарисовал единичный куб, оси координат которого есть R G и B. В 24-битном представлении 8-бит это R, следующие 8 - G, последние 8- B. Точный порядок не помню :(. Тем самым мы имеем точку, которая принадлежит этому кубу. Нужно определиться с границами разных цветов в этом кубе и в зависимости от попадания точки в границы, назначать урезанный цвет. Я уверен, что эта задача решена, но где взять решение не знаю. Для 16 цветов, я решал ее самостоятельно.
ADK опубликован 28-12-2001 07:49 MSK     Click Here to See the Profile for ADK  Click Here to Email ADK     
Насколько я понимаю, это весьма нетривиальная задача. Нужно подобрать оптимальную палитру. Здесь я думаю, сплошная математика. Photoshop при индексировании цветов предлагает много вариантов, только интересно, насколько трудно хотя бы один самому сделать?
Rechkin опубликован 28-12-2001 08:47 MSK     Click Here to See the Profile for Rechkin  Click Here to Email Rechkin     
А для 16 как решается?
ADK опубликован 28-12-2001 09:42 MSK     Click Here to See the Profile for ADK  Click Here to Email ADK     
Ну, это большая разница. Если 256 цветов вполне конкурентноспособный формат при правильно подобранной палитре, то 16 стандартных цветов - это полная туфта. Я не пробовал преобразовывать, но думаю, дело решит обычная таблица сопоставляения цветов - ведь 16 - не так уж и много. Если 24-bit цвет принадлежит какому-либо диапазону (выбери 16 диапазонов), то преобразуй его в один из 16-ти цветов.
Rechkin опубликован 28-12-2001 13:49 MSK     Click Here to See the Profile for Rechkin  Click Here to Email Rechkin     
Пробою сделать вот - так
//Для перевода 24 -> 8 вычисляем среднегеометрическое деленое на 3
for (i =0; i < BufferLength; i++){
for (j=0; j < 3;j++){
temp += pow(Sourse [3*i+j],2);
}
Normal[i] = (unsigned char)sqrt(temp/3);
temp = 0;
}
Но ничего не выходит,хотя в matcad все работает!
Drunkard опубликован 29-12-2001 05:07 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Вот тебе готовое решение для 16 цветов. Честно скажу, что бился я над ним почти месяц. Подгонял цвета по вышеописанному кубику. Если же возьмешься за 256 цветов - я тебе не завидую! Видимо, поэтому и не публикуется данный алгоритм, уж больно много трудов положили, небось, чуваки. Кто может предложить решение отличное от моего - буду рад воспользоваться :-))

BYTE PreobrColor(BYTE R,BYTE G,BYTE B)
{
if(((B+B-G-R)<=0)&&((G+G-B-R)<=0)&&((G+B-R)<=0))
if(R>191) return (BYTE)0x0C;// Red
else return (BYTE)0x04;// Red Dark
else if(((B+B-G-R)>0)&&((B-G-G)>=0)&&((R-B)>=0))
if(R>191) return (BYTE)0x0D;// Red + Blue
else return (BYTE)0x05;// Red + Blue Dark
else if(((G+G-B-R)>0)&&((G-B-B)>=0)&&((R-G)>=0))
if(R>191) return (BYTE)0x0E;// Red + Green
else return (BYTE)0x06;// Red + Green Dark
if(((G+G-B-R)<=0)&&((R+R-G-B)<=0)&&((R+G-B)<=0))
if(B>191) return (BYTE)0x09;// Blue
else return (BYTE)0x01;// Blue Dark
else if(((G+G-B-R)>0)&&((G-R-R)>=0)&&((B-G)>=0))
if(B>191) return (BYTE)0x0B;// Blue + Green
else return (BYTE)0x03;// Blue + Green Dark
else if(((R+R-B-G)>0)&&((R-G-G)>=0)&&((B-R)>=0))
if(B>191) return (BYTE)0x0D;// Red + Blue
else return (BYTE)0x05;// Red + Blue Dark
if(((R+R-G-B)<=0)&&((B+B-G-R)<=0)&&((B+R-G)<=0))
if(G>191) return (BYTE)0x0A;// Green
else return (BYTE)0x02;// Green Dark
else if(((R+R-B-G)>0)&&((R-B-B)>=0)&&((G-R)>=0))
if(G>191) return (BYTE)0x0E;// Red + Green
else return (BYTE)0x06;// Red + Green Dark
else if(((B+B-R-G)>0)&&((B-R-R)>=0)&&((G-B)>=0))
if(G>191) return (BYTE)0x0B;// Green + Blue
else return (BYTE)0x03;// Green + Blue Dark
if((R>223)

Drunkard опубликован 29-12-2001 05:09 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Из-за болтовни не уместилось. Попробую еще.

BYTE PreobrColor(BYTE R,BYTE G,BYTE B)
{
if(((B+B-G-R)<=0)&&((G+G-B-R)<=0)&&((G+B-R)<=0))
if(R>191) return (BYTE)0x0C;// Red
else return (BYTE)0x04;// Red Dark
else if(((B+B-G-R)>0)&&((B-G-G)>=0)&&((R-B)>=0))
if(R>191) return (BYTE)0x0D;// Red + Blue
else return (BYTE)0x05;// Red + Blue Dark
else if(((G+G-B-R)>0)&&((G-B-B)>=0)&&((R-G)>=0))
if(R>191) return (BYTE)0x0E;// Red + Green
else return (BYTE)0x06;// Red + Green Dark
if(((G+G-B-R)<=0)&&((R+R-G-B)<=0)&&((R+G-B)<=0))
if(B>191) return (BYTE)0x09;// Blue
else return (BYTE)0x01;// Blue Dark
else if(((G+G-B-R)>0)&&((G-R-R)>=0)&&((B-G)>=0))
if(B>191) return (BYTE)0x0B;// Blue + Green
else return (BYTE)0x03;// Blue + Green Dark
else if(((R+R-B-G)>0)&&((R-G-G)>=0)&&((B-R)>=0))
if(B>191) return (BYTE)0x0D;// Red + Blue
else return (BYTE)0x05;// Red + Blue Dark
if(((R+R-G-B)<=0)&&((B+B-G-R)<=0)&&((B+R-G)<=0))
if(G>191) return (BYTE)0x0A;// Green
else return (BYTE)0x02;// Green Dark
else if(((R+R-B-G)>0)&&((R-B-B)>=0)&&((G-R)>=0))
if(G>191) return (BYTE)0x0E;// Red + Green
else return (BYTE)0x06;// Red + Green Dark
else if(((B+B-R-G)>0)&&((B-R-R)>=0)&&((G-B)>=0))
if(G>191) return (BYTE)0x0B;// Green + Blue
else return (BYTE)0x03;// Green + Blue Dark
if((R>223)

Drunkard опубликован 29-12-2001 05:10 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Во, падла, не дает! Концовка, которая не уместилась:

if((R>223)

Drunkard опубликован 29-12-2001 05:13 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Наваждение какое-то!
Ладно, высылаю в Си-шном варианте тебе на Мыло.
Drunkard опубликован 29-12-2001 05:19 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Ага, понял, он вертикальную палку не пропускает! Знак логического "или" состоит из двух таких палок.
Приведенный алгоритм довольно сносно хреначит из 24 бит в 4 бита. Для 8 бит тебе придется делать нечто подобное. Брось это дело, придумай, что-нибудь другое, типа оттенков серого, там все просто. Иначе я тебе не завидую :-))
Drunkard опубликован 29-12-2001 05:54 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Да, вот еще нашел, как она, эта процедура вызывается.
// Выделим черный куб и преобразуем
if((Red<65)&&(Green<65)&&(Blue<65))
tetrH=(BYTE)0x00;
else tetrH=(BYTE)(PreobrColor(Red,Green,Blue)<<4);

В ВМР файле при 24 битах цвета идут байты R,G потом B. При 32 - сначала незначащий байт, потом R,G,B. При 16 битах идут по 5 битов на цвет. Это так, для информации.

Drunkard опубликован 29-12-2001 06:11 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Теоретическая база под всей этой ерундой (преобразование цвета) есть. Я это понял, когда бился над этим кубиком.
Нужно исходить из того, что из общей точки, вершины трех осей координат построены три конуса, не полые. Конуса имеют три цвета R,G и В. Где-то они идут не смешиваясь и мы получаем чистый цвет, где-то пересекаются и получаем смесь, а по пространственной биссектрисе получим серый цвет. Также эти конуса порублены шестью плоскостями, с координатами 0(3 плоскости) и 255(3 плоскости). Вот нашелся бы умник, владеющий теорией множеств и расписал бы универсальный алгоритм попадания точки с координатами R,G,B в область пространства с таким-то цветом. :-))
Rechkin опубликован 30-12-2001 19:00 MSK     Click Here to See the Profile for Rechkin  Click Here to Email Rechkin     
Извини, за нетривиальную просьбу, но не мог бы ты выслать еще раз! Тут были проблемы с провайдером, вернее у него, за что тот жолго извинялся, поэтому за несколько дней почта потирялась.
Заранее спасибо!
Drunkard опубликован 31-12-2001 03:45 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Выслал это тебе, также и на мыло
//Дело в том, что прога написана для обработки любой цветовой гаммы, начиная от 4 бит и
//кончая 32 битами, т.е. любым, которое может быть на экране. Вот кусок из нее, где идет
//вызов ф-ии PreobrColor для 24битного цвета
//здесь- lpBits - указатель на битовый массив в BitMape из которого читаем (исходный)
//lpBits16 - указатель на битовый массив в 16 цветном BitMape в который пишем
//В цикле идет обработка сразу двух пикселей, т.к. потом потетрадно пишется в байт.
//Надеюсь, с созданием своих битмапов справишься :-))
//Написано корявенько, но работает на все 100
if(pbihU->biPlanes*pbihU->biBitCount==(WORD)24) {
j=0;
for(i=0;i<pbihU->biSizeImage;i+=(DWORD)6) {
// Выделим черный куб и преобразуем
if((*(lpBits+i)<65)&&(*(lpBits+i+1)<65)&&(*(lpBits+i+2)<65)) tetrH=(BYTE)0x00;
else tetrH=(BYTE)(PreobrColor(*(lpBits+i),*(lpBits+i+1),*(lpBits+i+2))<<4);
// Обрабатываем 2 пиксель
if((*(lpBits+i+3)<65)&&(*(lpBits+i+4)<65)&&(*(lpBits+i+5)<65)) tetrL=(BYTE)0x00;
else tetrL=PreobrColor(*(lpBits+i+3),*(lpBits+i+4),*(lpBits+i+5));
*(lpBits16+j)=tetrH|tetrL; // Загоняем в массив
j++;
}
Drunkard опубликован 31-12-2001 04:01 MSK     Click Here to See the Profile for Drunkard  Click Here to Email Drunkard     
Доплнение, в конце потерялась еще одна }
В переменной j - при выходе из цикла получишь размер нового изображения ImageSize.

СПРОСИТЬ  +8">ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.