![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Цвета... [D5, Win95/98]
ThomasXIII © (2004-08-27 00:07:00)Мастера! Напишите, плиз, процедуру, "усредняющую" цвета (например:красный+желтый=оранжевый или белый+черный=серый). Очень надо.
GuAV (2004-08-28 15:19:00) [1]
> Классные и быстрые алгоритмы сложения двух цветов НО . .
> .
> Ты их сам то проверял?
То есть я проверял что даёт средний - GetMixedColorThursday даёт.
А средний между clYellow и clBlue в RGB Green -ом не будет.
По поводу быстрые. Не думай тока, что то что на asm быстрее :)
function GetMixedColorFriday(C1, C2: TColor): TColor;
asm
MOV ECX, EAX
PUSH EDX
AND ECX, 0FF00FFh
AND EDX, 0FF00FFh
ADD ECX, EDX
SHR ECX, 1
AND ECX, 0FF00FFh
POP EDX
AND EAX, 000FF00h
AND EDX, 000FF00h
ADD EAX, EDX
SHR EAX, 1
AND EAX, 000FF00h
OR EAX, ECX
end;
function GetMixedColorThursday(C1, C2: TColor): TColor;
begin
Result:=C1 shr 1 and $7F7F7F + C2 shr 1 and $7F7F7F +
C1 and C2 and $010101;
end;
function GetMixedColorThursday1(C1, C2: TColor): TColor;
begin
Result:=C1 shr 1 and $7F7F7F + C2 shr 1 and $7F7F7F;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Color := GetMixedColorThursday(clYellow,clRed);
end;
procedure TForm1.Button1Click(Sender: TObject);
const
TestCount = 100000000;
var
A, A1, B: Cardinal;
i: Integer; i1, i2 : tcolor;
begin
Randomize;
i1:=Random(Succ(clWhite));
i2:=Random(Succ(clWhite));
Assert(
GetMixedColorThursday(i1,i2) =
GetMixedColorFriday(i1,i2)
);
A := GetTickCount;
for i := 0 to TestCount do GetMixedColorThursday(i1,i2);
A := GetTickCount - A;
A1 := GetTickCount;
for i := 0 to TestCount do GetMixedColorThursday1(i1,i2);
A1 := GetTickCount - A1;
B := GetTickCount;
for i := 0 to TestCount do GetMixedColorFriday(i1,i2);
B := GetTickCount - B;
Caption := Format('Thursday = %d (%d), Friday = %d', [A, A1, B]);
// Thursday = 708 (504), Friday = 810
end;
GuAV (2004-08-28 14:48:00) [2]
> clBlue + clYellow НЕ равняется clGreen :-(
И не должно !!
в RGB
clGreen = 00FFFF
clBlue = FF0000
Это что я и говорил.
> GuAV © (27.08.04 00:27) [4]
> jack128 © (27.08.04 00:10) [1]
> Тот же результа, алгоримт оптимизирован.
> Color:=((Color1 shr 1) and $7F7F7F + (Color2 shr 1) and
> $7F7F7F);
>
> Хотя не уверен , что эта идея (твоя) правильная.
>jack128 © (27.08.04 00:10) [1]
>3APA3A © (27.08.04 11:53) [11]
>Rem (27.08.04 12:00) [12]
>
> Это может и так, но представь в CMYK, в ещё каком представлении,
> может будет другой результат, если нет, то вперёд.
2GrayFace
> ColorToRGB
Да, конечно, забыл сказать, но делать лучше вне этих процедур, т.к. может на входе быть уже RGB чтоб лишний раз не делать.
Sectey (2004-08-28 12:24:00) [3]GuAV ©
Ты конечно молодец :-)
Классные и быстрые алгоритмы сложения двух цветов НО . . .
Ты их сам то проверял?
clBlue + clYellow НЕ равняется clGreen :-(
А так все хорошо начиналось . . .
GrayFace (2004-08-28 08:20:00) [4]Вначале надо делать ColorToRGB.
GuAV (2004-08-28 03:27:00) [5]
function Gray(C: TColor): TColor; assembler;
asm
MOV EDX, EAX
AND EAX, 0000FF00h
AND EDX, 00FF00FFh
SHR EAX, 8
ADD EAX, EDX
SHR EDX, 16
ADD EAX, EDX
AND EAX, 0000FFFFh
XOR EDX, EDX
MOV CX, 3
DIV CX
MOV AH, AL
SHL EAX, 8
MOV AL, AH
end;
> Rnew=Gnew=Bnew=R/4+G/2+B/4
Это мне на завтра :)
GuAV (2004-08-27 22:48:00) [6]
> Rnew=Gnew=Bnew=(R+G+B)/3
Ничё лучше этого не могу:
function StupidGray(C: TColor): TColor; assembler;
asm
MOV EDX, EAX
AND EAX, 0000FF00h
AND EDX, 00FF00FFh
SHL EDX, 8
ADD EAX, EDX
SHR EDX, 16
ADD EAX, EDX // Сумма в AH и следующем байте
SHR EAX, 8
AND EAX, 0000FFFFh
XOR EDX, EDX
MOV CX, 3
DIV CX
MOV AH, AL
SHL EAX, 8
MOV AL, AH
end;
И всё таки TColorDialog считает по другому.
Яркость(красный)=Яркость(желтый)=Яркость(серый)=(Яркость(белый)/2)
nikkie (2004-08-27 20:49:00) [7]или только с делением на 2 и чуть ближе к яркостному варианту:
Rnew=Gnew=Bnew=R/4+G/2+B/4
nikkie (2004-08-27 20:38:00) [8]ну по-правильному надо через яркость - там каждая составляющая дает разный вклад.
http://vagrant.dp.ua/Photoshop/7/5.htm
для трюков с битами я имел ввиду прямолинейный способ
Rnew=Gnew=Bnew=(R+G+B)/3
GuAV (2004-08-27 20:11:00) [9]
> ну давай тогда самый быстрый и элегантный способ перевода
> цвета в grayscale :)
А что под этим понимать? в смысле как в grayscale переводят? в каждую компоненту среднее? или максимум? или находят якрость как Paint? сорее всего как Paint - тогда ща просеку логику и напишу...
nikkie (2004-08-27 19:22:00) [10]>Это просто, как биты в байте менять :)
ну давай тогда самый быстрый и элегантный способ перевода цвета в grayscale :)
GuAV (2004-08-27 19:08:00) [11]
> красиво, мне понравилось.
Это просто, как биты в байте менять :)
GuAV (2004-08-27 18:06:00) [12]А вот и исправил - теперь точно:
function GetMixedColorThursday(C1, C2: TColor): TColor;
begin
Result:=((C1 shr 1) and $7F7F7F + (C2 shr 1) and $7F7F7F) +
(C1 and C2) and $010101;
end;
И другая идея:
function GetMixedColorFriday(C1, C2: TColor): TColor;
asm
MOV ECX, EAX
PUSH EDX
AND ECX, 0FF00FFh
AND EDX, 0FF00FFh
ADD ECX, EDX
SHR ECX, 1
AND ECX, 0FF00FFh
POP EDX
AND EAX, 000FF00h
AND EDX, 000FF00h
ADD EAX, EDX
SHR EAX, 1
AND EAX, 000FF00h
OR EAX, ECX
end;
nikkie (2004-08-27 15:26:00) [13]>Небольшая погрешность, зато самый быстрый алгоритм.
красиво, мне понравилось.
GuAV (2004-08-27 14:22:00) [14]
> А как это должно рабоатать. shr передвинет разряды из одного
> цвета в другой, а надо-то с каждым цветом отдельно работать.
Да, именно поэтому провалившиеся в чужой разряд биты я игнорирую. Небольшая погрешность, зато самый быстрый алгоритм.
GuAV (2004-08-27 14:20:00) [15]jack128 © (27.08.04 00:10) [1]
3APA3A © (27.08.04 11:53) [11]
Rem (27.08.04 12:00) [12]
Это может и так, но представь в CMYK, в ещё каком представлении, может будет другой результат, если нет, то вперёд.
Rem (2004-08-27 12:00:00) [16]
function MixColors(a_Color1, a_Color2: TColor): TColor;
begin
Result := RGB((GetRValue(a_Color1) + GetRValue(a_Color2)) div 2,
(GetGValue(a_Color1) + GetGValue(a_Color2)) div 2,
(GetBValue(a_Color1) + GetBValue(a_Color2)) div 2);
end;
3APA3A (2004-08-27 11:53:00) [17]Млин, я только сейчас сообразил, что ерунда все это -сложение, усреднение, проверка на переполнение...
По теории - RGB цвет это координаты точки в кубе с главным диагональным вектором (255,255,255) - следовательно, если есть два цвета, то это просто две точки в этом кубе и "средний цвет" это координаты середины отрезка, соединяющего эти две точки ...
А уж координаты середины отрезка это
v = ((red1 + red2) div 2, (green1 + green2) div 2 , (blue1 + blue2) div 2)... Вот и "средний цвет"...
TUser (2004-08-27 07:35:00) [18]
> GuAV © (27.08.04 00:27) [4]
> jack128 © (27.08.04 00:10) [1]
> Тот же результа, алгоримт оптимизирован.
> Color:=((Color1 shr 1) and $7F7F7F + (Color2 shr 1) and
> $7F7F7F);
А как это должно рабоатать. shr передвинет разряды из одного цвета в другой, а надо-то с каждым цветом отдельно работать. И почему надо определенные биты игнорировать - я тоже не понял. Объясните, plz.
GuAV (2004-08-27 00:56:00) [19]
> Я имел в виду RGB...
// "тупое" сложение
procedure TForm1.Button1Click(Sender: TObject);
begin
Color:=clRed+clYellow; // Почти красный.
end;
// "умное" сложение
procedure TForm1.Button2Click(Sender: TObject);
const color1:tcolor=clred;
const color2:tcolor=clYellow;
var ResultColor:tcolor; I, tmp: integer;
begin
for I:=0 to 2 do
begin
tmp:=
longrec(Color1).Bytes[i]+
longrec(Color2).Bytes[i];
if tmp>high(byte) then tmp:=high(byte);
longrec(ResultColor).Bytes[i]:=tmp;
end;
Color:=ResultColor; // как я и обещал желтый.
end;
GuAV (2004-08-27 00:44:00) [20]
> ну я увидел слово "усредняющую" и ответил в меру своего
> скудоумия ;-) решать правильно или нет - автору..
Я о том, что лулше это имхо делать в координатах оттенок-контраст-яркость.
Кстати "отптимизорванный" мной алгоритм врёт. но чуть-чуть. на единичку каждого из трёх основных цветов. и то иногда.