使TImage中的每个像素变暗

时间:2018-12-11 12:38:46

标签: delphi

我在窗体上放置了一个TImage并在其中设置了PNG图像。

是否可以在运行时更改PNG图像每个像素的不透明度?我想根据应用程序中的特定操作更改不透明度。

我正在使用以下代码使像素变暗,其想法是将该功能应用于TImage中的每个像素:

function DarkerColor(thisColor: TColor; thePercent: Byte): TColor;
var
  (* a TColor is made out of Red, Green and blue *)
  cRed,
  cGreen,
  cBlue: Byte;
begin
  (* get them individually *)
  cRed := GetRValue(thisColor);
  cGreen := GetGValue(thisColor);
  cBlue := GetBValue(thisColor);
  (* make them darker thePercent *)
  (* we need a byte value but the "/" operator
     returns a float value so we use Round function
     because type mismatch *)
  cRed := Round(cRed * thePercent / 100);
  cGreen := Round(cGreen * thePercent / 100);
  cBlue := Round(cBlue * thePercent / 100);
  (* return them as TColor *)
  Result := RGB(cRed, cGreen, cBlue);
end;

我发现了如何访问BMP图像中的每个像素。事实是,我正在使用加载了PNG的TImage。

谢谢!

1 个答案:

答案 0 :(得分:4)

只需使用ScanLine图像中的PNG使其变暗,然后再将其分配给TImage组件。然后应该更快,然后将TBitmapTImage转换为PNG,执行操作并将其转换回TBitmap,然后再次将其分配给TImage组件。另外,将PNG分配给TBitmap后,将无法收回PNG的部分透明度。至少,我过去的所有尝试都没有成功,这就是为什么我更喜欢将PNG文件存储在我的小程序中并在运行期间更改(调整大小,混合等)其副本 -时间。

我更改了源代码,以排除带浮点的操作。它已被MulDiv函数取代。

function DarkerColor(thisColor: TColor; thePercent: Byte): TColor;
var
  (* a TColor is made out of Red, Green and blue *)
  cRed,
  cGreen,
  cBlue: Byte;
begin
  (* get them individually *)
  cRed := GetRValue(thisColor);
  cGreen := GetGValue(thisColor);
  cBlue := GetBValue(thisColor);

  (* make them darker thePercent *)
  cRed := MulDiv(cRed, thePercent, 100);
  cGreen := MulDiv(cGreen, thePercent, 100);
  cBlue := MulDiv(cBlue, thePercent, 100);

  (* return them as TColor *)
  Result := RGB(cRed, cGreen, cBlue);
end;  

现在,您可以进一步使用ScanLine图像中的PNG

procedure MakePNGDarker(APNGInOut: TPNGImage; AValue: Integer);
type
  TRGBArray = Array [0..65535 - 1] of WinAPI.Windows.tagRGBTRIPLE;
  PRGBArray = ^TRGBArray;
var
  RowInOut: PRGBArray;
  SourceColor: TColor;
  ResultColor: TColor;
  X: Integer;
  Y: Integer;
begin
  if not Assigned(APNGInOut) or (AValue < 0) then
    Exit;

  for Y:=0 to APNGInOut.Height - 1 do
    begin
      RowInOut := APNGInOut.ScanLine[Y];
      for X:=0 to APNGInOut.Width - 1 do
        begin
          SourceColor := RGB(RowInOut[X].rgbtRed, RowInOut[X].rgbtGreen, RowInOut[X].rgbtBlue);
          ResultColor := DarkerColor(SourceColor, AValue);

          RowInOut[X].rgbtRed := GetRValue(ResultColor);
          RowInOut[X].rgbtGreen := GetGValue(ResultColor);
          RowInOut[X].rgbtBlue := GetBValue(ResultColor);
        end;
    end;
end;  

这是功能完成的工作的结果。
图A 代表原始图片; 从B到F的数字是的修改图像的灰度,其暗度设置为25到0到100。

注意
彩色图像的边缘模糊不清,因为这些图像的边缘模糊不清。这不是功能工作的结果!

example

有用的资源