Idea jest taka:
var min,max,temp:byte;
i,j:integer;
begin
//Za najmniejszy i największy uznaj pierwszy piksel
min:=byte(Image1.Canvas.Pixels[0,0] and $FF);
max:=byte(Image1.Canvas.Pixels[0,0] and $FF);
//Jesli na obrazku znajdziesz mniejszy od najmniejszego, niech ten nowy bedzie
// najmniejszym. Analogicznie najwiekszy.
for j:=Image1.Height-1 downto 0 do
for i:=Image1.Width-1 downto 0 do
begin
temp:=byte(Image1.Canvas.Pixels[i,j] and $FF);
if temp<min then min:=temp;
if temp>max then max:=temp;
Application.ProcessMessages;
end;
//Przechodzac przez wszystkie piksele obrazka, przeskaluj je z zakresu
// (min-max) na (0-255)
for j:=Image1.Height-1 downto 0 do
for i:=Image1.Width-1 downto 0 do
begin
if max-min=0 then
temp:=0
else
temp:=byte(MulDiv((Image1.Canvas.Pixels[i,j] and $FF)-min, 255, max-min ));
Image1.Canvas.Pixels[i,j]:=RGB(temp,temp,temp);
Application.ProcessMessages;
end;
end;
Powyższe jest dobre dla obrazów skali szarości. Jak chcesz mieć ustawianie nasycenia obrazów kolorowych, to dla każdej składowej RGB robisz to osobno.
Ważne jest przy skalowaniu sprawdzenie: jaki kolor pokazać, gdy (min=max) [cały obraz w jednym odcieniu].
Powyższy przekład jest ideowy - dobrze chyba wyjaśnia, ale jak chcesz analizować duże obrazki, to ze względu na szybkość zapomnij o Canvas.Pixels[x,y], tylko rozejrzyj się za ScanLine.