Jump to content

[delphi]Szybkie wypełnianie bitmapy odcieniami S,V koloru H


sybic

Recommended Posts

Postanowiłem sobie zrobić swoje narzędzie do ustawiania koloru w aplikacji, dokładnie takie same jak jest w Photoshopie, czy innych programach graficznych. Mianowicie zmieniam sobie kolor H, a w drugim obrazku rysuje mi się cała paleta odcieni saturacji i jasności.

O takie :

http://img838.imageshack.us/img838/298/przyklad.png

 

wszystko super, ale jest jeden problem, gdy zmieniam kolorem H, obrazek (359x359) z odcieniami zmienia się bardzo wolno.

Może trwa to 0.5 s, ale to wystarczy by narzędzie jako mało komfortowe i całkowiece nie do użytku.

 

W Photoshopie dzieje się to bezzwłocznie...

 

Pytanie :

Jak to należy zrobić że tak powiem profesjonalnie?

Ja to robię ScanLine

 
procedure Rysuj_Odcienie(rysunek:TImage; seH_value:double);
var
 x,y : integer;
 P : PByteArray;
 H,S,V:double;
 rgb: results;
begin
H:=seH_value;
 rysunek.Picture.BitMap.PixelFormat:=pf24Bit;
 with rysunek.Picture.Bitmap do
   for y:=0 to Height-1 do
     begin
       V:=(height-y)/height*255;
       P:=ScanLine[y];
       x:=0;
       repeat
          S:=(x/3)/width;
          rgb:=hsv2rgb_(H,S,V);
          p[x]:=trunc(rgb[3]);
          p[x+1]:=trunc(rgb[2]);
          p[x+2]:=trunc(rgb[1]);
         x:=x+3;
       until x>(Width-1)*3;
     end;
 rysunek.Invalidate;
end;
^rjvŁ),)zgŚ-źgjqnkbs6ŁqĄVvkkZui' 
function hsv2rgb_(hue: double; sat: double; val: double): results;
var
       red, grn, blu :double;
       i, f, p, q, t: double;
       rgb: results;
begin
       red := 0;
       grn := 0;
       blu := 0;
       if val=0 then
               begin
                       red := 0;
                       grn := 0;
                       blu := 0;
               end
       else
               begin
                       hue := hue/60;
                       i := floor(hue);
                       f := hue-i;
                       p := val*(1-sat);
                       q := val*(1-(sat*f));
                       t := val*(1-(sat*(1-f)));
                       if i=0 then begin red:=val; grn:=t; blu:=p; end
                       else if i=1 then begin red:=q; grn:=val; blu:=p; end
                       else if i=2 then begin red:=p; grn:=val; blu:=t; end
                       else if i=3 then begin red:=p; grn:=q; blu:=val; end
                       else if i=4 then begin red:=t; grn:=p; blu:=val; end
                       else if i=5 then begin red:=val; grn:=p; blu:=q; end;
               end;
       rgb[1] := red;
       rgb[2] := grn;
       rgb[3] := blu;
       result := rgb;
end;

Tylko, czy z tym można coś jeszcze zrobić, jakoś zoptymalizować?

Jestem niezwykle ciekaw jak to robią profesjonaliści, bo ja pisząc sobie takie narzędzie odniosłem małą porażkę.

Link to comment
Share on other sites

Witam!

 

Ja mogę dodać, że nie używają tak zagnieżdżonych instrukcji IF THEN ELSE !!!

 

Zamień ten fragment kodu, na:

 

case wyrażenie of

wybór 1: (kod);

...

wybór n: (kod);

else

(kod)

end;

 

Nie podoba mi się również, w jaki sposób funkcja zwraca wartości:

 

KOD

rgb[1] := red;

rgb[2] := grn;

rgb[3] := blu;

result := rgb;

 

 

Głębiej nie wnikam, ponieważ już mnie sen łapie.

 

Pozdrawiam!

Link to comment
Share on other sites

Zrobiłem parę poprawek, eliminując w pętli i samej procedury zbędne operacje umieszczając je przed wywołaniem pętli.

Udało mi się to wszystko przyspieszyć co najmniej 3-krotnie.

Przy szybkich komputerach może to być do przyjęcia, ale daleko jeszcze do szybkości procedur jakie są w PS ;)

 

 

procedure hsv2rgb_(i:byte; f : double; sat: double; val: double; var red, grn, blu:Byte);
var
       p, q, t: double;
begin
       if val=0 then
               begin
                       red := 0;
                       grn := 0;
                       blu := 0;
               end
       else
               begin
                       p := val*(1-sat);
                       q := val*(1-(sat*f));
                       t := val*(1-(sat*(1-f)));
                       case i of
                       0:begin red:=round(val); grn:=round(t); blu:=round(p); end;
                       1:begin red:=round(q); grn:=round(val); blu:=round(p); end;
                       2:begin red:=round(p); grn:=round(val); blu:=round(t); end;
                       3:begin red:=round(p); grn:=round(q); blu:=round(val); end;
                       4:begin red:=round(t); grn:=round(p); blu:=round(val); end;
                       5:begin red:=round(val); grn:=round(p); blu:=round(q); end;
                       end;
               end;
end;

procedure Paint_Odcienie(rysunek:TImage; seH_value:double);
var
 x,y : integer;
 P : PByteArray;
 H,S,V:double;
 hue60,f:double;
 i:integer;
begin
H:=seH_value;
hue60 := H/60;
i := trunc(floor(hue60));
f := hue60-i;

rysunek.Picture.BitMap.PixelFormat:=pf24Bit;
 with rysunek.Picture.Bitmap do
   for y:=0 to Height-1 do
     begin
       V:=(height-y)/height*255;
       P:=ScanLine[y];
       x:=0;
       repeat
          S:=x/(3*width);
          hsv2rgb_(i,f,S,V, p[x+2], p[x+1], p[x]);
         inc(x,3);
       until x>(Width-1)*3;
     end;
 rysunek.Invalidate;
end;

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...