在 Lazarus 中将图像转换为灰度的问题
Issue converting an image to gray scale in Lazarus
我写了一个叫做gray_scale
的procedure
,假设有一个输入TImage组件,将它包含的图像变成灰度,然后在同一个TImage组件中打印它。它的问题是它打印出黑色图像。我的代码如下,请注意,我创建了一个名为 img2: TPicture
的局部变量,其目的是作为过程输入和输出之间的中间阶段。
procedure gray(var img1: TImage);
var
i,j: Integer;
y: integer;
color: TColor;
img2: TPicture;
begin
i := 0; j := 0;
img2 := TPicture.create;
img2.Bitmap.Width:= img1.width;
img2.Bitmap.Height:= img1.height;
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
img1.Picture.Assign(img2);
end;
end;
看看这段代码,其中有两个嵌套循环。
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
img1.Picture.Assign(img2);
end;
在内部循环之后,您将 img2
分配给 img1.Picture
,您将在访问外部循环后继续阅读。结果,在外循环进入第二次迭代时,img1
变为空(除了最左边的像素列)。
修改代码如下:
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
end;
img1.Picture.Assign(img2);
将 TPicture
命名为 img2
也会产生误导,尤其是当 img1
指代 TImage
.
时
此外,为了使您的代码更有效率,您应该考虑几点。最重要的是在扫描线的帮助下一次扫描一行位图图像。
Look at this SO post
unit rhsBitmapGrayscale;
interface
uses
SysUtils, Classes, Graphics, IntfGraphics, FPImage;
procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
implementation
// BitmapGrayscale(Bitmap, 0.30, 0.59, 0.11); // ISO-Neutral-Gray
procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
var
IntfImg: TLazIntfImage = nil;
x, y, w, h: Integer;
TempColor: TFPColor;
Gray: Word;
begin
try
IntfImg := BM.CreateIntfImage;
w := IntfImg.Width - 1;
h := IntfImg.Height - 1;
IntfImg.BeginUpdate;
for y := 0 to h do
for x := 0 to w do
begin
TempColor := IntfImg.Colors[x, y];
Gray := Round(TempColor.Red * R + TempColor.Green * G + TempColor.Blue * B);
TempColor.Red := Gray;
TempColor.Green := Gray;
TempColor.Blue := Gray;
IntfImg.Colors[x, y] := TempColor;
end;
IntfImg.EndUpdate;
BM.LoadFromIntfImage(IntfImg);
finally
IntfImg.Free;
end;
end;
end.
使用 TLazIntfImage 可以提高处理速度。
使用红色、绿色和蓝色的参数,可以单独影响结果。
这里有一些例子:
BitmapGrayscale(Image1.Picture.Bitmap, 0.30, 0.59, 0.11); // Neutral filter
BitmapGrayscale(Image1.Picture.Bitmap, 1.00, 0.00, 0.00); // Red filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 1.00, 0.00); // Green filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.00, 1.00); // Blue filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.50, 0.50); // Cyan filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.00, 0.50); // Magenta filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.50, 0.00); // Yellow filter
我写了一个叫做gray_scale
的procedure
,假设有一个输入TImage组件,将它包含的图像变成灰度,然后在同一个TImage组件中打印它。它的问题是它打印出黑色图像。我的代码如下,请注意,我创建了一个名为 img2: TPicture
的局部变量,其目的是作为过程输入和输出之间的中间阶段。
procedure gray(var img1: TImage);
var
i,j: Integer;
y: integer;
color: TColor;
img2: TPicture;
begin
i := 0; j := 0;
img2 := TPicture.create;
img2.Bitmap.Width:= img1.width;
img2.Bitmap.Height:= img1.height;
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
img1.Picture.Assign(img2);
end;
end;
看看这段代码,其中有两个嵌套循环。
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
img1.Picture.Assign(img2);
end;
在内部循环之后,您将 img2
分配给 img1.Picture
,您将在访问外部循环后继续阅读。结果,在外循环进入第二次迭代时,img1
变为空(除了最左边的像素列)。
修改代码如下:
for i := 0 to img1.width do begin
for j := 0 to img1.height do begin
y:= trunc((255 * luminance(img1,i,j)));
color := RGBToColor(byte(y), byte(y), byte(y));
img2.Bitmap.Canvas.DrawPixel(i,j, TColorToFPColor(color));
end;
end;
img1.Picture.Assign(img2);
将 TPicture
命名为 img2
也会产生误导,尤其是当 img1
指代 TImage
.
此外,为了使您的代码更有效率,您应该考虑几点。最重要的是在扫描线的帮助下一次扫描一行位图图像。
Look at this SO post
unit rhsBitmapGrayscale;
interface
uses
SysUtils, Classes, Graphics, IntfGraphics, FPImage;
procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
implementation
// BitmapGrayscale(Bitmap, 0.30, 0.59, 0.11); // ISO-Neutral-Gray
procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
var
IntfImg: TLazIntfImage = nil;
x, y, w, h: Integer;
TempColor: TFPColor;
Gray: Word;
begin
try
IntfImg := BM.CreateIntfImage;
w := IntfImg.Width - 1;
h := IntfImg.Height - 1;
IntfImg.BeginUpdate;
for y := 0 to h do
for x := 0 to w do
begin
TempColor := IntfImg.Colors[x, y];
Gray := Round(TempColor.Red * R + TempColor.Green * G + TempColor.Blue * B);
TempColor.Red := Gray;
TempColor.Green := Gray;
TempColor.Blue := Gray;
IntfImg.Colors[x, y] := TempColor;
end;
IntfImg.EndUpdate;
BM.LoadFromIntfImage(IntfImg);
finally
IntfImg.Free;
end;
end;
end.
使用 TLazIntfImage 可以提高处理速度。 使用红色、绿色和蓝色的参数,可以单独影响结果。
这里有一些例子:
BitmapGrayscale(Image1.Picture.Bitmap, 0.30, 0.59, 0.11); // Neutral filter
BitmapGrayscale(Image1.Picture.Bitmap, 1.00, 0.00, 0.00); // Red filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 1.00, 0.00); // Green filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.00, 1.00); // Blue filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.50, 0.50); // Cyan filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.00, 0.50); // Magenta filter
BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.50, 0.00); // Yellow filter