在此处下载源代码:http://www.eyeClaxton.com/download/delphi/ColorSwap.zip
是的,我想将“大多数是蓝色”的东西转换成“大多数是绿色”的东西。
我想采用原始位图(浅蓝色)并将颜色(Pixel by Pixel)更改为红色,绿色,蓝色和灰色等效关系。为了了解我的意思,我已经包含了源代码和屏幕截图。任何帮助将不胜感激。如果需要更多信息,请随时询问。
如果您可以查看下面的代码,我有三个功能,我正在寻求帮助。功能“RGBToRed,RGBToGreen和RGBToRed”我似乎无法提出正确的公式。
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TMainFrm = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Panel2: TPanel;
Label2: TLabel;
Button1: TButton;
BeforeImage1: TImage;
AfterImage1: TImage;
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainFrm: TMainFrm;
implementation
{$R *.DFM}
function RGBToGray(RGBColor: TColor): TColor;
var
Gray: Byte;
begin
Gray := Round(
(0.90 * GetRValue(RGBColor)) +
(0.88 * GetGValue(RGBColor)) +
(0.33 * GetBValue(RGBColor)));
Result := RGB(Gray, Gray, Gray);
end;
function RGBToRed(RGBColor: TColor): TColor;
var
Red: Byte;
begin
// Not sure of the algorithm for this color
Result := RGB(Red, Red, Red);
end;
function RGBToGreen(RGBColor: TColor): TColor;
var
Green: Byte;
begin
// Not sure of the algorithm for this color
Result := RGB(Green, Green, Green);
end;
function RGBToBlue(RGBColor: TColor): TColor;
var
Blue: Byte;
begin
// Not sure of the algorithm for this color
Result := RGB(Blue, Blue, Blue);
end;
procedure TMainFrm.FormCreate(Sender: TObject);
begin
BeforeImage1.Picture.LoadFromFile('Images\RightCenter.bmp');
end;
procedure TMainFrm.Button1Click(Sender: TObject);
var
Bitmap: TBitmap;
I, X: Integer;
Color: Integer;
begin
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile('Images\RightCenter.bmp');
for X := 0 to Bitmap.Height do
begin
for I := 0 to Bitmap.Width do
begin
Color := ColorToRGB(Bitmap.Canvas.Pixels[I, X]);
case Color of
$00000000: ; // Skip any Color Here!
else
case RadioGroup1.ItemIndex of
0: Bitmap.Canvas.Pixels[I, X] := RGBToBlue(Color);
1: Bitmap.Canvas.Pixels[I, X] := RGBToRed(Color);
2: Bitmap.Canvas.Pixels[I, X] := RGBToGreen(Color);
3: Bitmap.Canvas.Pixels[I, X] := RGBToGray(Color);
end;
end;
end;
end;
AfterImage1.Picture.Graphic := Bitmap;
finally
Bitmap.Free;
end;
end;
end.
好的,我为没有让它更清楚而道歉。我正在尝试采用位图(蓝色)并将蓝色像素换成另一种颜色。就像下面的镜头一样。
答案 0 :(得分:13)
我不知道你想要达到的目标。首先,问题与equivalence relations有什么关系?
其次,代码
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。
我使用以下rutines在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;
在绿色案例中,最终结果将类似于
Hue fixed to 120 http://english.rejbrand.se/algosim/manual/pmproc/fixHue120.jpg
在第一种情况下(色调固定为120)和
在后一种情况下(色调固定为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 and G channels swapped http://english.rejbrand.se/algosim/manual/pmproc/swapRG.jpg
红色和绿色通道已交换。请注意,红色的棍子现在是绿色的,绿色的草现在是红色的。什么是白色仍然是白色。
<强>最后强>
欢迎来到pixmap操作的世界!有很多简单而有趣的事情要做。我的一些例子:http://english.rejbrand.se/algosim/manual/pmproc/pmproc.html
答案 1 :(得分:2)
通过“像素”属性访问颜色信息非常慢。您应该考虑使用“Scanline”属性来获得大约2个数量级的代码。 http://blogs.embarcadero.com/pawelglowacki/2010/04/15/39051包含代码示例如何操作。
成功!