delphi 如何在像素格式为pf32bit的TBitmap中使像素透明?

7fhtutme  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(117)

我正在升级一个 Delphi 应用程序中的按钮图像。我有几个位图,其中透明度由clFushia表示。我正在尝试

procedure TForm6.MakeTransparent(bmp: TBitmap);
type
  PRGBQuadArray = ^TRGBQuadArray;
  TRGBQuadArray = array[Word] of TRGBQuad;
var
  x: Integer;
  y: Integer;
  line: PRGBQuadArray;
  Alpha : TRGBQuad;
begin
  Alpha.rgbBlue := $FF;
  Alpha.rgbGreen := $FF;
  Alpha.rgbRed := $FF;
  Alpha.rgbReserved := $00;
  bmp.PixelFormat := pf32bit;
  for x := 0 to bmp.Width-1 do
  begin
    for y := 0 to bmp.Height-1 do
    begin
      if bmp.Canvas.Pixels[x, y] = clFuchsia then
      begin
        line := bmp.ScanLine[y];
        line[x] := Alpha;
      end;
    end;
  end;
end;

字符串
但是当我执行bmp.Save时,图像缺乏透明度。我在这里做错了什么?
更多的背景,我有几个长位图由许多16x16和32x32字形,我试图转换使用:

procedure TForm6.ExtractImages(x: TBitmap);
var
  SourceRect: TRect;
  I: Integer;
  bmp: TBitmap;
  DestinationRect: TRect;
  wh: integer; //width, height
  FileName: string;
begin
  wh := x.Height;
  SourceRect := Rect(0, 0, wh, wh);
  for I := 0 to x.Width div wh do
  begin
    bmp := TBitmap.Create;
    bmp.Width := wh;
    bmp.Height := wh;
    bmp.PixelFormat := Images16bmp.PixelFormat;

    DestinationRect := Rect(i * wh, 0, (i + 1) * wh - 1, wh - 1);
    bmp.Canvas.CopyRect(SourceRect, x.Canvas, DestinationRect);

    MakeTransparent(bmp);
    FileName := Format('%d\%d.bmp', [wh, i]);
    bmp.SaveToFile('D:\Temp\SplitImages\' + FileName);
    bmp.Free;
  end;
end;


我在打电话:

ExtractImages(Images16BMP);
ExtractImages(Images32BMP);


其中Images16BMP是一个2500x16的位图,Images32BMP是5000x32的位图。我使用的是 Delphi XE 8。

vcudknz3

vcudknz31#

您需要将TBitmap.AlphaFormat属性设置为afDefined以指定正在使用的alpha通道。默认情况下,alpha通道将被忽略。
顺便说一下,不要使用slow Canvas.Pixels属性来扫描所有像素,特别是因为你已经在使用Scanline属性了。使用Scanline来扫描像素以及操作它们。

procedure TForm6.MakeTransparent(bmp: TBitmap);
type
  PRGBQuadArray = ^TRGBQuadArray;
  TRGBQuadArray = array[Word] of TRGBQuad;
var
  x: Integer;
  y: Integer;
  line: PRGBQuadArray;
  Pixel, Alpha : TRGBQuad;
  rgb: DWORD;
begin
  rgb := ColorToRGB(clFuchsia);

  Pixel.rgbBlue := GetBValue(rgb);
  Pixel.rgbGreen := GetGValue(rgb);
  Pixel.rgbRed := GetRValue(rgb);
  Pixel.rgbReserved := $00;

  Alpha.rgbBlue := $FF;
  Alpha.rgbGreen := $FF;
  Alpha.rgbRed := $FF;
  Alpha.rgbReserved := $00;

  bmp.PixelFormat := pf32bit;
  for y := 0 to bmp.Height-1 do
  begin
    line := bmp.ScanLine[y];
    for x := 0 to bmp.Width-1 do
    begin
      if line[x] = Pixel then
      begin
        line[x] := Alpha;
      end;
    end;
  end;
  bmp.AlphaFormat := afDefined;
end;

字符串

czfnxgou

czfnxgou2#

我无法让雷米的解决方案在 Delphi XE 8中工作(可能在 Delphi 的后续版本中工作,但我没有测试过)。
这就是我最后做的

procedure TForm6.CopyTransparent(Source: TBitmap; Destination: TPngImage);
var
  x, y: integer;
begin
  for y := 0 to Source.Height-1 do
  begin
    for x := 0 to Source.Width-1 do
    begin
      if Source.Canvas.Pixels[x, y] <> clFuchsia then
      begin
        Destination.Pixels[x, y] := Source.Canvas.Pixels[x, y];
        Destination.AlphaScanline[y][x] := 255; //make pixel opaque
      end;
    end;
  end;
end;

procedure TForm6.ExtractImages(MultiWide: TBitmap);
var
  SourceRect: TRect;
  I: Integer;
  bmp: TBitmap;
  DestinationRect: TRect;
  wh: integer; //width, height
  FileName: string;
  png: TPngImage;
begin
  wh := MultiWide.Height;
  SourceRect := Rect(0, 0, wh, wh);
  for I := 0 to MultiWide.Width div wh do //for every sub-image
  begin
    png := TPngImage.CreateBlank(COLOR_RGBALPHA, 8, wh, wh);

    bmp := TBitmap.Create;
    bmp.Width := wh;
    bmp.Height := wh;
    bmp.PixelFormat := Images16bmp.PixelFormat;
    DestinationRect := Rect(i * wh, 0, (i + 1) * wh - 1, wh - 1);
    bmp.Canvas.CopyRect(SourceRect, MultiWide.Canvas, DestinationRect); //copy the sub-image to bmp

    CopyTransparent(bmp, png);

    FileName := Format('%d\%d.png', [wh, i]);
    png.SaveToFile('D:\Temp\SplitImages\' + FileName);
    bmp.Assign(png);
    FileName := Format('%d\%d.bmp', [wh, i]);
    png.SaveToFile('D:\Temp\SplitImages\' + FileName);

    png.Free;
    bmp.Free;
  end;
end;

字符串
我创建了一个透明的PNG,然后将位图中的非Fuchsia像素复制到PNG中,并使其不透明。从那里我可以保存PNG,并将其分配给BMP,神奇的是,我有一个透明的位图。这给了我保存到磁盘的16 x16和32 x32透明BMP和PNG。是的,我使用的是慢速像素属性-但代码在不到一秒的时间内执行超过300张图像。

相关问题