Код:
var
Bi : TBitMap;
//загрузка картинки
procedure TForm1.Button1Click(Sender: TObject);
begin
IF not OpenPictureDialog1.Execute then Exit;
if bi = nil then bi:=TBitmap.Create;
bi.LoadFromFile(OpenPictureDialog1.FileName);
end;
//преобразование цветной картинки в картинку с градацией серого
procedure TForm1.Button2Click(Sender: TObject);
var
C : TColor;
X, Y, M : Integer;
R, G, B : Byte;
begin
//1. в двойном цикле получаем цвет каждой точки изображения - C: TColor
//2. разбиваем полученный цвет точки С на R, G, B: byte - составляющие цвета,
//используя фун-ции R := GetRValue(C) и т.д.
//3. находим M - максимум из R, G, B
//4. устанавливаем новый цвет точки bm.Canvas.Pixels[x, y] := RGB(M, M, M)
for X := 0 to Bi.Width-1 do
for Y := 0 to Bi.Height-1 do begin
C := Bi.Canvas.Pixels[x, y];
R := GetRValue(C);
G := GetGValue(C);
B := GetBValue(C);
M := Max(R, G);
Bi.Canvas.Pixels[x, y] := RGB(M, M, M)
end;
//вывод полученного изображения на форму
Form1.Canvas.Draw(10,10,Bi);
end;
Для другого оттенка можно поиграться полученным значением "М" (в .RGB(M, M, M)), изменяя это значение для всех или некоторых компонентов цвета.
Для небольших картинок обращение к пикселям (Bi.Canvas.Pixels[x, y]) работает приемлемо быстро, если картинка большая, то к пикселям надо добираться через Bi.ScanLine.
P.S. Не забыть освободить память от "Bi" (Bi.Free), например при выходе из программы.