![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
(Y:=0.3*R+0.59*G+0.11*B)
анонимус © (2011-08-21 20:42:00)Преобразование к оттенкам серого заключается в получении яркости каждой точки по известной формуле (Y:=0.3*R+0.59*G+0.11*B) и последующем копировании полученного значения по все три канала (R=G=B:=Y).
Пытаясь воспользоваться данным утверждением, на выходе получаю черный экран. Что же на самом деле делать с этой формулой? )
procedure ConvertBmpToGray(tBmp: TBitmap);
var
QP: TQuickPixels;
Pixel1: Cardinal;
Pixel2: Cardinal;
r1: byte;
g1: byte;
b1: byte;
r2: byte;
g2: byte;
b2: byte;
Intensity:byte;
br2:byte;
x:integer;
y:integer;
begin
QP := TQuickPixels.Create;
QP.Attach(tBmp);
//num:=0;
for y := 0 to QP.Height-1 do
begin
for x := 0 to QP.Width-1 do
begin
Pixel1 := QP.GetPixels24(x,y);
// Y (in YIQ) = 0.299R + 0.587G + 0.114B, which can be performed in
// integer arithmetic as Y = (77R + 150G + 29B) DIV 256
// See [Foley96, pp. 589-590]
// r1 := (Pixel1 shr 23);
// g1 := (Pixel1 shr 15);
// b1 := (Pixel1 shr 7);
r1 := (Pixel1 and $000000FF);
g1 := (Pixel1 and $0000FF00) shr 8;
b1 := (Pixel1 and $00FF0000) shr 16;
Intensity:=byte(77*r1 + 150*g1 + 29*b1) SHR 8;
//Intensity:= g1;
IF Intensity < 0
THEN Intensity := 0
ELSE
IF Intensity > 255
THEN Intensity := 255;
//br2:=r1+g1+b1;
//br1:=FloatToDecimal(br2);
r1:=Intensity;
g1:=Intensity;
b1:=Intensity;
QP.SetPixels24(X, Y, RGB(r1,g1,b1));
end;
end;
tBmp.SavetoFile('E:\test.bmp');
qp.Free;
end;
Sha (2011-08-26 19:42:00) [1]> Что же на самом деле делать с этой формулой? )
Вот тут подробно все расписал
http://guildalfa.ru/alsha/node/14
Sha (2011-08-23 09:37:00) [2]> анонимус (23.08.11 05:43) [9]
Попробуй заменить нутро своего цикла на
Pixel := QP.GetPixels24(x,y);
Pixel:=(( Pixel * (150 * 256)
+ (Pixel and $00FF00FF) * (77 * 256 * 256 - 150 * 256 + 29)
) shr 24
) * (65536 + 256 + 1);
QP.SetPixels24(X, Y, Pixel);
Омлет (2011-08-23 07:21:00) [3]> анонимус (23.08.11 05:43) [9]
> нифига себе упростил.
А ты посчитай количество операций. И сравни скорость.
анонимус (2011-08-23 06:05:00) [4]мдя все таки лучше проверку оставить, а Intensity определить как Integer
анонимус (2011-08-23 05:43:00) [5]нифига себе упростил.
выше же уже написали, что правильно не так
Intensity:=byte((77*r1 + 150*g1 + 29*b1) SHR 8)
а вот так
Intensity:=Integer(77*r1 + 150*g1 + 29*b1) SHR 8
Тогда работает.
проверка на 255 думаю лишняя, т.к. Intensity:byte и оно полюбому не выскочит за диапазон.
Sha (2011-08-22 20:57:00) [6]Или еще короче (но не быстрее) в 6 команд:
3 умножения, 1 сдвиг, 1 сложение, 1 'and'
function ShaRGBToGray(Pixel: integer): integer;
begin;
Result:=(( Pixel * (150 * 256)
+ (Pixel and $00FF00FF) * (77 * 256 * 256 - 150 * 256 + 29)
) shr 24
) * (65536 + 256 + 1);
end;
Sha (2011-08-22 15:16:00) [7]По идее немного упростить и ускорить можно,
если списать преобразование цвета отсюда
function ShaColorToGray(Pixel: cardinal): cardinal;
begin;
Result:=(Pixel and $0000FF00) * (150 * 256)
+ (Pixel and $00FF00FF) * (77 * 256 * 256 + 29);
Result:=(Result shr 24) * (65536 + 256 + 1);
end;
Dimka Maslov (2011-08-22 11:33:00) [8]Intensity:=byte((77*r1 + 150*g1 + 29*b1) SHR 8)
Юрий Зотов (2011-08-22 11:02:00) [9]
Intensity: byte;
Intensity := byte(77*r1 + 150*g1 + 29*b1) SHR 8; // Всегда 0
IF Intensity < 0 // Никогда не выполнится
THEN Intensity := 0
ELSE
IF Intensity > 255 // Никогда не выполнится
THEN Intensity := 255;
анонимус (2011-08-21 21:43:00) [10]да, в оригинале было integer теперь стало лучше ))
Anatoly Podgoretsky (2011-08-21 21:15:00) [11]> анонимус (21.08.2011 20:42:00) [0]
Убери byte(
анонимус (2011-08-21 20:46:00) [12]Формула в коде выглядит так странно, ибо если умножать ее на коэффициэнты будет проблемма с преобразованием типов, поэтому нашел такой способ...
анонимус (2011-08-21 20:43:00) [13]ах и да, если просто присвоить значение одного канала всем остальным, то на выходе как раз и получается серый цвет. Причем пофиг значение какого канала присваивать.