mam sobie cztery kolory o zakresu od 0 do 255.
kazdy kolor lezy na skrajnych punktach tego obrazu. jak teraz wyliczyc kolor pozostalych punktow obrazu, aby przeciscie kolorow bylo plynne? znaczy zeby powstal taki gradient.
Huh?! Jak byś chciał żeby to wyglądało? Możesz takie coś stworzyć w photoshopie? Jeżeli Ci się uda to analogicznie to zaprogramuj.
Ja bym to widział w ten sposób: Obraz dzielisz po przekątnych na 4 części w kształcie takich kawałków tortu :P następnie robisz w każdej części wypełnienie między dwoma kolorami. Dla uproszczenia robisz coś takiego, że w środku obraz jest ciemniejszy/jaśniejszy aby ukryć brak przejść między kolorami w środku.
Obrazek robiony na szybko w GIMPie więc traktuj to jako schemat tylko, a nie efekt końcowy :P
Obraz dzielisz po przekątnych na 4 części w kształcie takich kawałków tortu
Prościej chyba będzie zrobić to scanline'ami, odpowiednio skalując kolor w poziomie i pionie.
dobra, moze inaczej. nie chce generowac obrazu. potrzebuje funkcji, ktora bedzie przyjmowac 8 parametrow:
2, to wymiary obrazu/tablicy dwuwymiarowej
kolejne 2 x,y wybranego punktu
pozostale 4, to te wartosci tych kolorow
No to robisz to analogicznie: obliczasz początkowy i końcowy kolor dla pozycji y, a później w ten sam sposób obliczasz to dla wartości x.
AB = (1-x/w)*A + (x/w)*B
CD = (1-x/w)*C + (x/w)*D
ABCD = (1-y/h)*AB + (y/h)*CD
ABCD = (1-y/h)(1-x/w)*A + (1-y/h)(x/w)*B + (y/h)(1-x/w)*C + (y/h)(x/w)*D
X = x/w
Y = y/h
ABCD = (1-Y)(1-X)*A + (1-Y)(X)*B + (Y)(1-X)*C + (Y)(X)*D
gdzie:
A - składowa koloru lewego górnego piksela
B - składowa koloru prawego górnego piksela
C - składowa koloru lewego dolnego piksela
D - składowa koloru prawego dolnego piksela
(x,y) - położenie szukanego piksela
(w,h) - wymiary obrazka
x/w = X - położenie szukanego piksela względem obrazka w osi x [0 - 1]
y/h = Y - położenie szukanego piksela względem obrazka w osi y [0 - 1]
Dopisane:
Po prostu szukany kolor jest dwuwymiarową średnią ważoną (wagami są odpowiednio X oraz Y) między pikselami narożnymi. AB to kolor średni ważony w osi X dla Y=0, CD to kolor średni ważony w osi X dla Y=1. ABCD to kolor ważony między AB a CD w osi Y. Warto zauważyć, że zamiana kolejności i tworzenie średniej ważonej w osi X między AC oraz BD da identyczny efekt.
Miałem trochę czasu i napisałem kodzik ale widzę, że już Szczawik mnie uprzedził :P
procedure TForm1.Gradient(Col1, Col2, Col3, Col4: TColor; Bmp: TBitmap);
type
PixArray = array [1..3] of Byte;
var
h, w: Integer;
X, Y: Real;
p: ^PixArray;
begin
bmp.PixelFormat := pf24Bit;
for h := 0 to bmp.Height - 1 do
begin
p := bmp.ScanLine[h];
for w := 0 to bmp.Width - 1 do
begin
X:= w / bmp.Width;
Y:= h / bmp.Height;
p^[1] := Round(GetBvalue(Col1)*(1-X)*(1-Y)) + Round(GetBvalue(Col2)*X*(1-Y)) + Round(GetBvalue(Col3)*(1-X)*Y) + Round(GetBvalue(Col4)*X*Y);
p^[2] := Round(GetGvalue(Col1)*(1-X)*(1-Y)) + Round(GetGvalue(Col2)*X*(1-Y)) + Round(GetGvalue(Col3)*(1-X)*Y) + Round(GetGvalue(Col4)*X*Y);
p^[3] := Round(GetRvalue(Col1)*(1-X)*(1-Y)) + Round(GetRvalue(Col2)*X*(1-Y)) + Round(GetRvalue(Col3)*(1-X)*Y) + Round(GetRvalue(Col4)*X*Y);
Inc(p);
end;
end;
end;
procedure TForm1.ColorValue(Col1, Col2, Col3, Col4, Wynik: TColor; X, Y, Width, Height: Integer);
var
W, H: Real;
begin
W:= X / Width;
H:= Y / Height;
Wynik:= RGB(Round(GetBvalue(Col1)*(1-W)*(1-H)) + Round(GetBvalue(Col2)*X*(1-Y)) + Round(GetBvalue(Col3)*(1-X)*Y) + Round(GetBvalue(Col4)*X*Y),
Round(GetGvalue(Col1)*(1-W)*(1-H)) + Round(GetGvalue(Col2)*X*(1-Y)) + Round(GetGvalue(Col3)*(1-X)*Y) + Round(GetGvalue(Col4)*X*Y),
Round(GetRvalue(Col1)*(1-W)*(1-H)) + Round(GetRvalue(Col2)*X*(1-Y)) + Round(GetRvalue(Col3)*(1-X)*Y) + Round(GetRvalue(Col4)*X*Y));
end;
oraz efekt działania procedury Gradient:
/edit: procedura ColorValue dla podanych kolorów ustala kolor pixela Wynik na pozycji X,Y dla bitmapy o wielkości Width, Height.
oo! dzieki bardzo. o to mi chodzilo
Tylko teraz tak patrzę i stwierdzam, że niepotrzebnie to rozbijałem na RGB ;) Można z 3 linijek zrobić jedną.