Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Отобразить картинку в оттенках определенного цвета (Colorize) [D4, WinXP]


Страницы:   1 2

Tahion2 ©   (2004-07-07 10:01:00) 

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

Общий смысл процедуры таков: пробегаем по каждому пикселю битмапа, RGB -> HLS, и затем замена H и S на нужные нам, а L оставляем нетронутым.

Все, вроде, работает, но на темных цветах происходят непонятные "срывы". См. иллюстрацию (Правый результат): http://www.rudnik.com.ua/Example.gif

Вопрос: Что не так я делаю. Где ошибка?

Вот код, который я использую:

procedure RGBtoHLS(R, G, B: Integer; var H, L, S: Integer);
{ H-оттенок, L-яркость, S-насыщенность }
Var
 cMax, cMin: Integer;
 Rdelta, Gdelta, Bdelta: single;
Begin
 cMax:=max(max(R, G), B);
 cMin:=min(min(R, G), B);
 L:=Round((((cMax+cMin)*HLSMAX)+RGBMAX)/(2*RGBMAX));

 if (cMax=cMin) then
   begin
     S:=0; H:=UNDEFINED;
   end
 else
   begin
     if (L<=(HLSMAX/2)) then
       S:=Round((((cMax-cMin)*HLSMAX)+((cMax+cMin)/2))/(cMax+cMin))
     else
       S:=Round((((cMax-cMin)*HLSMAX)+((2*RGBMAX-cMax-cMin)/2))
         /(2*RGBMAX-cMax-cMin));
     Rdelta:=(((cMax-R)*(HLSMAX/6))+((cMax-cMin)/2))/(cMax-cMin);

     Gdelta:=(((cMax-G)*(HLSMAX/6))+((cMax-cMin)/2))/(cMax-cMin);
     Bdelta:=(((cMax-B)*(HLSMAX/6))+((cMax-cMin)/2))/(cMax-cMin);
     if (R=cMax) then
       H:=Round(Bdelta-Gdelta)
     else if (G=cMax) then
       H:=Round((HLSMAX/3)+Rdelta-Bdelta)
     else
       H:=Round(((2*HLSMAX)/3)+Gdelta-Rdelta);
     if (H<0) then H:=H+HLSMAX;
     if (H>HLSMAX) then H:=H-HLSMAX;
   end;
 if S<0 then S:=0; if S>HLSMAX then S:=HLSMAX;
 if L<0 then L:=0; if L>HLSMAX then L:=HLSMAX;
end;

procedure HLStoRGB(H, L, S: Integer; var R, G, B: Integer);
Var
 Magic1, Magic2: single;

 function HueToRGB(n1, n2, hue: single): single;
 begin
   if (hue<0) then hue:=hue+HLSMAX;
   if (hue>HLSMAX) then hue:=hue-HLSMAX;
   if (hue<(HLSMAX/6)) then
     Result:=(n1+(((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)))
   else if (hue<(HLSMAX/2)) then
     Result:=n2
   else if (hue<((HLSMAX*2)/3)) then
     Result:=(n1+(((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12))/(HLSMAX/6)))
   else
     Result:=(n1);
 end;

begin
 if (S=0) then
   begin
     B:=Round((L*RGBMAX)/HLSMAX); R:=B; G:=B;
   end
 else
   begin
     if (L<=(HLSMAX/2)) then
       Magic2:=(L*(HLSMAX+S)+(HLSMAX/2))/HLSMAX
     else
       Magic2:=L+S-((L*S)+(HLSMAX/2))/HLSMAX;
     Magic1:=2*L-Magic2;
     R:=Round((HueToRGB(Magic1, Magic2, H+(HLSMAX/3))*RGBMAX+(HLSMAX/2))/HLSMAX);
     G:=Round((HueToRGB(Magic1, Magic2, H)*RGBMAX+(HLSMAX/2))/HLSMAX);
     B:=Round((HueToRGB(Magic1, Magic2, H-(HLSMAX/3))*RGBMAX+(HLSMAX/2))/HLSMAX);
   end;
 if R<0 then R:=0; if R>RGBMAX then R:=RGBMAX;
 if G<0 then G:=0; if G>RGBMAX then G:=RGBMAX;
 if B<0 then B:=0; if B>RGBMAX then B:=RGBMAX;
end;

procedure ColorizeColor(R,G,B :integer; Color: TColor; var OutR, OutG, OutB:Byte);
//Колоризирует один пиксель цветом Color
var h1, s1, l1, h, s, l : integer;
InColor, OutColor : TColor;
R1,B1,G1:integer;
begin
   InColor := RGB(R,G,B);
   RGBtoHLS(R, G, B, h, l, s);
   RGBtoHLS(GetRValue(Color), GetGValue(Color), GetBValue(Color), h1, l1, s1);
   HLStoRGB(h1,l,s1, r1,g1,b1);
   OutColor:= RGB(r1,g1,b1);
   OutR:=GetRValue(OutColor);
   OutG:=GetGValue(OutColor);
   OutB:=GetBValue(OutColor);
end;

//Next here's a code to make a loop on an image (called Podglad, size is 32*32):
//В данном случае происходит раскраска красным цветом.
var OutR, OutG, OutB:Byte;
Col:TColor;
begin
for y := 0 to 31 do
 for x := 0 to 31 do
   begin
   Col:=Podglad.Picture.Bitmap.Canvas.Pixels[x, y];
ColorizeColor(GetRValue(Col),GetGValue(Col),GetBValue(Col), clRed, OutR, OutG, OutB);
Podglad.Picture.Bitmap.Canvas.Pixels[x, y]:=RGB(OutR, OutG, OutB);
   end;
end;


Tahion2   (2004-07-08 00:26:00) [21]

Да. Уже неплохо. :)
Вот только здается мне, что алгоритм с RGB -> HLS и заменой Н и S правильный, вот только еще что-то нужно делать с L. Вот только что?


Огромное Кулясищще   (2004-07-07 22:25:00) [22]

Первый блин. Комочки большие, но всё же.
http://www.hot.ee/mvps17/exampel2.png


Tahion2   (2004-07-07 22:09:00) [23]

Ждем-с


Огромное Кулясищще   (2004-07-07 20:39:00) [24]

Щас, ты погодь. Сваяю что-нить, раз Fenik плохой алгоритм сделал :)


Tahion2   (2004-07-07 15:30:00) [25]

Эта функция глючит еще сильнее. То что в результатах на картинке
http://www.rudnik.com.ua/Example.gif
слева - это после работы именно этой ф-ции.


Огромное Кулясищще   (2004-07-07 14:37:00) [26]

http://delphibase.endimus.ru/?action=viewfunc&topic=mediaimg&id=10178


Tahion2   (2004-07-07 13:47:00) [27]

Может кто чего подсказать?


Tahion2   (2004-07-07 11:39:00) [28]

>Ты алгоритм сам изобрел? Если ты знаешь критерий неправильности, то знаешь и как правильно. Осталось сравнить.

Нет, не сам. В этом все и дело.

А как правильно я знаю из-за того, что есть программы, которые алгоритм уже реализуют (ПРАВИЛЬНО). Сравинивая их и мои результаты получаю ответ: правильно или нет


REA   (2004-07-07 11:10:00) [29]

Ты алгоритм сам изобрел? Если ты знаешь критерий неправильности, то знаешь и как правильно. Осталось сравнить.

Модуль GraphUtil:
procedure ColorRGBToHLS(clrRGB: COLORREF; var Hue, Luminance, Saturation: Word);
{ Calculates a color given Hue, Luminance and Saturation values }
function ColorHLSToRGB(Hue, Luminance, Saturation: Word): TColorRef;

Если версия Delphi старая, то могу кинуть целиком функции


Tahion2   (2004-07-07 10:49:00) [30]

Что значит "Локализуй неверный пиксел"? они при определенных цветах все неверные.

Юпросчитай значение вручную
Проверил HLStoRGB и RGBtoHLS работают правильно.

Может еще какие-то действия с L (lightness) нужно делать?


REA   (2004-07-07 10:07:00) [31]

Локализуй неверный пиксел, просчитай значение вручную и по шагам....


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо