使用delphi将PNGImage转换为灰度

Jav*_*vid 4 delphi image bitmap grayscale scanline

嗨,这里是我的代码:

procedure TForm4.Button1Click(Sender: TObject);
var
  png: TPNGImage;
  data: PRGBQarray;
  p: ^tagRGBQuad;
  i, o: integer;
begin
  png := TPNGImage.Create;
  try
    png.LoadFromFile('C:\Untitled.png');
    for o := 1 to 100 do
    begin
      data:=png.Scanline[o];
      for I := 1 to 400 do
      begin
        p := @data^[i];
        p.rgbGreen := p.rgbBlue;
        p.rgbRed := p.rgbGreen;
      end;
    end;
    img.picture.Assign(png);
  finally
    png.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

它不起作用,它使pic杂乱,我确定这是因为rgbReserved.我该怎么办?

And*_*and 8

这是如何灰化位图.(并且,是的,如果你想要对PNG进行灰化,你首先需要从中获取位图数据.我认为VCL会为你做这个.)

type
  PRGB32Array = ^TRGB32Array;
  TRGB32Array = packed array[0..MaxInt div SizeOf(TRGBQuad)-1] of TRGBQuad;

procedure MakeGrey(Bitmap: TBitmap);
var
  w, h: integer;
  y: Integer;
  sl: PRGB32Array;
  x: Integer;
  grey: byte;
begin
  Bitmap.PixelFormat := pf32bit;
  w := Bitmap.Width;
  h := Bitmap.Height;
  for y := 0 to h - 1 do
  begin
    sl := Bitmap.ScanLine[y];
    for x := 0 to w - 1 do
      with sl[x] do
      begin
        grey := (rgbBlue + rgbGreen + rgbRed) div 3;
        rgbBlue := grey;
        rgbGreen := grey;
        rgbRed := grey;
      end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

样品用法:

procedure TForm4.Button1Click(Sender: TObject);
var
  bm: TBitmap;
begin
  bm := TBitmap.Create;
  try
    bm.LoadFromFile('C:\Users\Andreas Rejbrand\Pictures\Porträtt, litet, kvadratiskt.bmp');
    MakeGrey(bm);
    Canvas.Draw(0, 0, bm);
  finally
    bm.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • 注意,行'gray:=(rgbBlue + rgbGreen + rgbRed)div 3;`表示`[0,255]中的`灰色`. (2认同)

Mas*_*ler 8

安德烈亚斯的答案会给你一个好的,快速的近似值,但你会失去一些质量,因为红色,绿色和蓝色不会在人眼中以相同的强度混合.如果你想"正确",而不是

grey := (rgbBlue + rgbGreen + rgbRed) div 3;

试试这个:

grey := round(rgbRed * .3) + round(rgbGreen * .59) + round(rgbBlue * .11);

你可以在简单的平均值上获得一点性能,但除非你的图像非常大,否则它可能不会引人注意.

  • 值得注意的是,这是NTSC公式,还有其他公式. (4认同)
  • 梅森,你不会通过一次舍入操作获得几乎相同的结果(更快),即"灰色:=圆形(rgbRed*.3 + rgbGreen*.59 + rgbBlue*.11);"? (2认同)