Rozjaśnianie i Przyciemnianie
Adam Boduch
Pragnę na początku zaznaczyć, że poniższe procedury nie są mojego autorstwa (nie wiem też kogo :)). Oto dwie procedury które rozjaśnią/przyciemnią kolor:
function Darker(Col: TColor; Percent: Byte): TColor;
var
R, G, B: Byte;
begin
R := GetRValue(Col);
G := GetGValue(Col);
B := GetBValue(Col);
R := Round(R*Percent/100);
G := Round(G*Percent/100);
B := Round(B*Percent/100);
Result := RGB(R, G, B);
end;
function Lighter(Col: TColor; Percent: Byte): TColor;
var
R, G, B: Byte;
begin
R := GetRValue(Col);
G := GetGValue(Col);
B := GetBValue(Col);
R := Round(R*Percent/100) + Round(255 - Percent/100*255);
G := Round(G*Percent/100) + Round(255 - Percent/100*255);
B := Round(B*Percent/100) + Round(255 - Percent/100*255);
Result := RGB(R, G, B);
end;
Jak łatwo się domyśleć pierwsza z nich przyciemnia druga rozjaśnia podany w parametrze kolor o "Percent" procent.
Oto sposób na wykorzystanie któregoś z tych sposobów:
procedure TForm1.Button1Click(Sender: TObject);
var
Pic : TBitmap;
I, J : Integer;
begin
Pic := TBitmap.Create;
try
Pic.Assign(Image1.Picture.Graphic);
for I := 0 to Pic.Width do
for J := 0 to Pic.Height do
Pic.Canvas.Pixels[i, j] := Darker(Pic.Canvas.Pixels[i, j], 50);
Image1.Picture.Graphic := Pic;
finally
Pic.Free;
end;
end;
Szybkość tego algorytmu zależy od prędkości Twojego procesora oraz od rozmiarów bitmapy. Ten kod wczytuje najpierw obrazek do pamięci, a później edytuje każdy piksel obrazka w pamięci, aby na końcu przypisać zmodyfikowany już obrazek do komponentu Image.
Jednakże Dryobates przesłał mi szybszy algorytm (dzięki!) - oto on:
interface
type
TTriple = record
B,G,R:byte;
end;
function Lighter(Col: TTriple; Percent: Byte): TTriple;
function Darker(Col: TTriple; Percent: Byte): TTriple;
var
Form1: TForm1;
Pic : TBitmap;
implementation
{$R *.DFM}
function Darker(Col: TTriple; Percent: Byte): TTriple;
begin
Col.B:=Trunc(Col.B*percent/100);
Col.G:=Trunc(Col.G*percent/100);
Col.R:=Trunc(Col.R*percent/100);
Result:=col;
end;
function Lighter(Col: TTriple; Percent: Byte): TTriple;
begin
Col.R := Round(Col.R*(Percent-1)/100) + Round(255 - Percent/100*255);
Col.G := Round(Col.G*(Percent-1)/100) + Round(255 - Percent/100*255);
Col.B := Round(Col.B*(Percent-1)/100) + Round(255 - Percent/100*255);
Result := Col;
end;
procedure TForm1.Button1Click(Sender: TObject);
type
TTablica=array [0..$FFFFFF] of TTriple;
PTablica=^TTablica;
var
I, J : Integer;
P:PTablica;
paleta:array[0..255]of TPaletteEntry;
pal:PLogPalette;
hpal:HPALETTE;
kolor:TTriple;
begin
Pic := TBitmap.Create;
try
Pic.Assign(Image1.Picture.Graphic);
if Pic.PixelFormat=pf24bit then //jeżeli bez palety
for I := 0 to Pic.Height-1 do begin
P:=Pic.ScanLine[i];
for J := 0 to Pic.Width-1 do
P[j] := Darker(P[j], 50);
end
else begin //jeżeli z paletą
GetPaletteEntries(Pic.Palette,0,255,paleta);
GetMem(pal, sizeof(TLogPalette) + sizeof(TPaletteEntry) * 255);
pal.palVersion := $300;
pal.palNumEntries := 256;
for i := 0 to 255 do
begin
kolor.R:=paleta[i].peRed;
kolor.G:=paleta[i].peGreen;
kolor.B:=paleta[i].peBlue;
kolor:=Darker(kolor,50);
pal.palPalEntry[i].peRed := kolor.R;
pal.palPalEntry[i].peGreen :=kolor.G;
pal.palPalEntry[i].peBlue :=kolor.B;
end;
hpal := CreatePalette(pal^);
if hpal <> 0 then
Pic.Palette := hpal;
FreeMem(pal);
end;
Image1.Picture.Graphic := Pic;
finally
Pic.Free;
end;
end;
end.
To właściwie wszystko :)
Na to samo wychodzi... :)
Ciekawe, ciekawe...
Pochwalony! Adam, zdaje mi się iż w pierwszym przykładzie (nie sprawdzałem drugiego :P ), dokładniej w funkcji Darker jest błąd. Powinna ona tak wyglądać:
function TForm1.Darker(kol: TColor; Cot: Integer): TColor;
var
R, G, B: Byte;
begin
R := GetRValue(kol);
G := GetGValue(kol);
B := GetBValue(kol);
R := R - Round(R * (Cot / 100));
G := G - Round(G * (Cot / 100));
B := B - Round(B * (Cot / 100));
Result := RGB(R, G, B);
end;
(sorki za inne parametry :) ). Jeżeli chcemy przyciemniać O DANY PROCENT, trzeba od aktualnego koloru odjąć ten procent. :)
Fajny Art :) ale w przypadku rozjasniania wychodziły mi dziwne kolory (w przypadku jasnych)
I dodalem taki warnek na końcu funkcji:
if r>255 then r:=255;
if g>255 then g:=255;
if b>255 then b:=255;
Wg mnie tak jest lepiej.
Pozdro :)