有如下代码;
 var gd : TGpGrpahics;
     Image : TGpBitmap;
     Bmp : Tbitmap;
 begin
  Bmp := TBitmap.Create;
  Bmp.PixelFormat := pf24bit;
  Bmp.Width := 704;Bmp.Height := 440;
  Bmp.Canvas.Brush.Style := bsclear;
  Gd := TGpGraphics.create(Bmp.Canvas.Handle);
  Image := TGpBitmap.Create('a.bmp'); //背景图
  Gd.DrawImage(Image,0,0);
  Image.Free;
  Gd.Free;
  Gd := TGpGraphics.create(Bmp.Canvas.Handle);
  Image := TGpBitmap.Create('a.png'); //a.png是一个边框图,即图像中某些区域是完全透明的
  Gd.DrawImage(Image,0,0);
  Image1.Picture.Bitmap.Assign(Bmp);
  Bmp.Free;
 end;这段代码,先后将两张图画到TBITMAP上,a.png的透明区域可以看到a.bmp的图像,也就是说,后面一次画的不会完全覆盖掉前一次画的内容
但是,如果将a.bmp画至 Bmp,a.png画到另一张Tbitmap上,(假设为 FBmp )然后再将FBmp画至Bmp,那此时,FBmp就完全覆盖了 Bmp
由于程序需要将a.png画到FBmp 上,请问有什么办法,可以使得FBmp 也可以按原来的透明区域画到Bmp上,而不是被FBmp覆盖?
试了好多方法,发现只有将文件用GDI+的方式画到Bmp上时,才不会覆盖Bmp原有的图像
不知道有没有表达清楚

解决方案 »

  1.   

    TBitmap对象有几个关于透明的属性,一般用TransparentColor和Transparent就够了
    可以先把整个bmp画布用一种颜色清空一下再把png画上去,然后把之前用来清空的颜色设为TransparentColor,再设Transparent,这个bmp再往别的Canvas上画就可以了
      

  2.   

    自己合成:
    var
      Bmp, FBmp: TBitmap;
      Image: TGpBitmap;
      x, y, w, h: Integer;
      dAlpha: Integer;
      sOffset, dOffset: Integer;
      pd: PRGBTriple;
      ps: PRGBQuad;
    begin
      Bmp := TBitmap.Create;
      FBmp := TBitmap.Create;  Image := TGpBitmap.Create('D:\GdiplusC\Media\56-3.jpg');
      Bmp.Handle := Image.GetHBITMAP(0);
      Bmp.PixelFormat := pf24bit;
      Image.Free;  Image := TGpBitmap.Create('D:\xmas_011.png');
      FBmp.Handle := Image.GetHBITMAP(0);
      FBmp.PixelFormat := pf32bit;
      Image.Free;  w := FBmp.Width;
      if w > Bmp.Width then w := Bmp.Width;
      h := FBmp.Height;
      if h > Bmp.Height then h := Bmp.Height;
      // 32Bit
      ps := FBmp.ScanLine[h - 1];
      sOffset := (FBmp.Width - w) shl 2;
      // 24Bit
      pd := Bmp.ScanLine[h - 1];
      dOffset := (((24 * Bmp.Width + 31) and $ffffffe0) shr 3) - w * 3;
      for y := 1 to h do
      begin
        for x := 1 to w do
        begin
          // 目的位图Alpha = 255 - 源图Alpha(ps^.rgbReserved)
          dAlpha := 255 - ps^.rgbReserved;
          pd^.rgbtBlue := (dAlpha * pd^.rgbtBlue  + ps^.rgbReserved * ps^.rgbBlue) div 255;
          pd^.rgbtGreen := (dAlpha * pd^.rgbtGreen + ps^.rgbReserved * ps^.rgbGreen) div 255;
          pd^.rgbtRed := (dAlpha * pd^.rgbtRed + ps^.rgbReserved * ps^.rgbRed) div 255;
          Inc(LongWord(pd), 3);
          Inc(LongWord(ps), 4);
        end;
        Inc(LongWord(pd), dOffset);
        Inc(LongWord(ps), sOffset);
      end;
      Canvas.Draw(0, 0, Bmp);
      FBmp.Free;
      Bmp.Free;
      

  3.   

    谢谢 阿发伯 大哥,是可以, 由于我的两张原图的尺寸大小不一样,必须将它们画成大小一样的tbitmap,所以我改了一下画到TBitmap的方法,就好像不行了,
      Bmp := TBitmap.Create;
      FBmp := TBitmap.Create;  Image := TGpBitmap.Create('D:\GdiplusC\Media\56-3.jpg');
      Bmp.Handle := Image.GetHBITMAP(0);
      Bmp.PixelFormat := pf24bit;
      Image.Free;  Image := TGpBitmap.Create('D:\xmas_011.png');
      FBmp.Handle := Image.GetHBITMAP(0);
      FBmp.PixelFormat := pf32bit;
      Image.Free;  w := FBmp.Width;
      if w > Bmp.Width then w := Bmp.Width;
      h := FBmp.Height;
      if h > Bmp.Height then h := Bmp.Height;改为这种写法var gd : TGpGraphics;
        Image : TGpBitmap;begin
      Bmp := TBitmap.Create;
      Bmp.PixelFormat := pf24bit;
      Bmp.Width := 540;Bmp.Height := 330;
      Gd := TGpGraphics.create(Bmp.Canvas.Handle);
      Image := TGpBitmap.Create('E:\Source Code\test\a.bmp');
      Gd.DrawImage(Image,GpRect(0,0,540,330),0,0,Image.Width,Image.Height,utPixel);
      Image.Free;
      Gd.Free;  FBmp := TBitmap.Create;
      FBmp.PixelFormat := pf32bit;
      FBmp.Width := 540;FBmp.Height := 330;
      Gd := TGpGraphics.create(FBmp.Canvas.Handle);
      Image := TGpBitmap.Create('E:\Source Code\test\d.png'); //a.png是一个边框图,即图像中某些区域是完全透明的
      Gd.DrawImage(Image,GpRect(0,0,540,330),0,0,Image.Width,Image.Height,utPixel);
      Image.Free;
      Gd.Free;还麻烦您帮忙试一下,非常感谢
      

  4.   

    如果你设置TBitmap的大小,就会自动带上背景色,可以用一个临时TGpBitmap将png图像拉伸,然后:  Image := TGpBitmap.Create('D:\xmas_011.png');
      tmp := TGpBitmap.Create(Bmp.Width, Bmp.Height, pf32bppARGB);
      g := TGpGraphics.Create(tmp);
      g.DrawImage(Image, GpRect(0, 0, Bmp.Width, Bmp.Height), 0, 0, Image.Width, Image.Height, utPixel);
      g.Free;
      FBmp.Handle := tmp.GetHBITMAP(0);
      FBmp.PixelFormat := pf32bit;
      tmp.Free;
      Image.Free;
      

  5.   

    简单的说,设置TBitmap长度后,使用DrawImage会使png图像的Alpha通道损失,用GetHBITMAP方法则不会。
      

  6.   

    不过,这句实在看不懂
    dOffset := (((24 * Bmp.Width + 31) and $ffffffe0) shr 3) - w * 3;
      

  7.   

    因为Windows位图每行象素字节数(扫描线长度)必须是4的整倍数,如果不够则用0补在后面。32位位图每个象素都是4字节,不存在这个问题,而24位有可能扫描线长度大于宽度*3,
    (((24 * Bmp.Width + 31) and $ffffffe0) shr 3计算的是24位像素的扫描线长度。