Понятия не имею, чего вы пытаетесь достичь. Во-первых, какое отношение этот вопрос имеет к отношениям эквивалентности ?
Во-вторых, код
function RGBToRed(RGBColor: TColor): TColor;
var
Red: Byte;
begin
// Not sure of the algorithm for this color
Result := RGB(Red, Red, Red);
end;
бессмысленно. Возвращаемое значение не определено. Функции RGB
принимают интенсивность красного, зеленого и синего в диапазоне от 0 до 255 и возвращают TColor
с этими компонентами. Например, RGB(255, 0, 0)
- это чисто красный, то есть 255 красных, 0 зеленых и 0 синих. В приведенном выше коде, однако, Red
не инициализируется, поэтому Result
может быть любого серого цвета (в зависимости от того, что происходит с Red
). [И, как вы, вероятно, знаете, если вы смешиваете равное количество красного, зеленого и синего, как вы делаете, вы получаете серый цвет.] Например, Red
может оказаться 45 раз при запуске приложения, а затем результатом будет серый цвет RGB(45, 45, 45)
. В следующий раз это может быть 163.
Может быть, вам нужна функция, которая принимает TColor
и возвращает ее красный компонент? Тогда подойдет GetRValue
, и, конечно же, есть GetGValue
и GetBValue
.
Или, может быть, вы хотите создать серый цвет из заданного TColor
, как вы это делаете, когда используете Photoshop для создания полутонового изображения из цветного изображения. Затем, если Color
является TColor
, соответствующее значение серого будет
grey := (GetRValue(Color) + GetGValue(Color) + GetBValue(Color)) div 3;
Есть и другие способы сделать это (в результате получаются слегка отличающиеся изображения в оттенках серого, но это самый простой (и самый быстрый)). (Например, вы можете преобразовать цвет из RGB в HSV или HSL, а затем установить насыщенность равной нулю.)
Обновление
Я думаю, что вижу, что вы хотите сделать. Может быть, вы хотите извлечь красный, зеленый и синий каналы. То есть вы хотите преобразовать каждый пиксель RGB(R, G, B)
в RGB(R, 0, 0)
в красном корпусе. Если это то, что вы хотите сделать, то вы должны сделать
function RGBToRed(RGBColor: TColor): TColor;
begin
Result := RGB(GetRValue(RGBColor), 0, 0);
end;
и аналогично для других компонентов, то есть
function RGBToGreen(RGBColor: TColor): TColor;
begin
Result := RGB(0, GetGValue(RGBColor), 0);
end;
и
function RGBToBlue(RGBColor: TColor): TColor;
begin
Result := RGB(0, 0, GetBValue(RGBColor));
end;
Или, может быть
Или, может быть, вы просто хотите сделать изображение серым, а затем «покрасить» его красным (или зеленым, или синим). Тогда вам нужна тяжелая техника. Теоретически вы хотите заменить каждый пиксель с HSV(h, s, v)
на HSV(0, s, v)
в красном корпусе, HSV(120, s, v)
в зеленом корпусе и HSV(240, s, v)
в синем корпусе. Или, может быть, вы также хотите установить насыщенность s
в 1.
Я использую следующие процедуры для преобразования между RGB и HSV:
function RGBToHSV(const Color: TRGB): THSV;
var
cmax, cmin, cdiff: real;
begin
cmax := MaxComponent(Color);
cmin := MinComponent(Color);
cdiff := cmax - cmin;
with Color, result do
begin
// Hue
if cmax = cmin then
hsvHue := 0
else if cmax = rgbRed then
hsvHue := (60 * (rgbGreen - rgbBlue) / cdiff)
else if cmax = rgbGreen then
hsvHue := (60 * (rgbBlue - rgbRed) / cdiff) + 120
else
hsvHue := (60 * (rgbRed - rgbGreen) / cdiff) + 240;
hsvHue := Fix360(hsvHue);
// Saturation
if cmax = 0 then
hsvSaturation := 0
else
hsvSaturation := 1 - cmin / cmax;
// Value
hsvValue := cmax;
end;
end;
и
function HSVToRGB(const Color: THSV): TRGB;
var
hi: integer;
f, q, p, t: real;
begin
with Color do
begin
hi := floor(hsvHue / 60) mod 6;
f := hsvHue / 60 - floor(hsvHue / 60);
p := hsvValue * (1 - hsvSaturation);
q := hsvValue * (1 - f * hsvSaturation);
t := hsvValue * (1 - (1 - f) * hsvSaturation);
case hi of
0: result := RGB(hsvValue, t, p);
1: result := RGB(q, hsvValue, p);
2: result := RGB(p, hsvValue, t);
3: result := RGB(p, q, hsvValue);
4: result := RGB(t, p, hsvValue);
5: result := RGB(hsvValue, p, q);
end;
end;
end;
, где
type
TRGB = record
rgbRed, // red intensity between 0 and 1
rgbGreen, // green intensity between 0 and 1
rgbBlue: double; // blue intensity between 0 and 1
end;
THSV = record
hsvHue, // hue angle between 0 and 360
hsvSaturation, // saturation between 0 (grey) and 1 (full colour)
hsvValue: double; // value between 0 (dark) and 1 ("normal")
end;
Конечный результат в зеленом случае будет выглядеть как
Цветовой тон зафиксирован на 120 http://english.rejbrand.se/algosim/manual/pmproc/fixHue120.jpg
в первом случае (оттенок установлен на 120) и
Оттенки зафиксированы на 120, а насыщенность - на 1 http://english.rejbrand.se/algosim/manual/pmproc/monochromatic120.jpg
в последнем случае (оттенок установлен на 120, насыщенность установлена на 1).
Или, возможно
Ваш вопрос очень смелый, даже с правкой. Вы хотите преобразовать что-то «в основном синее» во что-то «в основном зеленое». Но есть тысячи способов сделать это! Конечно, очень простой способ - просто поменять синий и зеленый каналы, то есть заменить RGB(r, g, b)
на RGB(r, b, g)
или, явно,
function SwapBlueGreen(Color: TColor): TColor;
begin
result := RGB(GetRValue(Color), GetBValue(Color), GetGValue(Color));
end;
Тогда вы получите что-то вроде
Смена каналов R и G http://english.rejbrand.se/algosim/manual/pmproc/swapRG.jpg
где красный и зеленый каналы поменялись местами. Обратите внимание, что красная палочка теперь зеленая, а зеленая трава теперь красная. Что белое остается белым.
Наконец
Добро пожаловать в мир растровых манипуляций! Есть много простых и забавных вещей. Еще несколько моих примеров: http://english.rejbrand.se/algosim/manual/pmproc/pmproc.html