delphiimagebitmapgrayscalescanline

converting a PNGImage to grayscale using delphi


hi there here it is my code:

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;

it doesn't work and it makes the pic messy, I'm sure it's because of the rgbReserved. what should i do?


Solution

  • This is how to greyify a bitmap. (And, yes, if you want to greyify a PNG, you first need to get the bitmap data out of it. I think the VCL will do this for you.)

    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;
    

    Sample usage:

    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;