Canvas.TransparentColor和Canvas.Draw与不透明度的组合

 平凡我86 发布于 2022-12-13 10:57

我想在不透明的画布上绘制位图,其中位图具有透明色.

我可以创建一个透明色的位图,并将其绘制成一个

canvas我可以创建一个位图并将其绘制到具有不透明度的画布上

但我无法结合它.如果我合并它,则忽略不透明度.

这是我写的代码:

procedure TForm1.FormPaint(Sender: TObject);
var b1,b2:TBitmap;
begin
  // Example how it opacity works:
  b1 := TBitmap.Create;
  b1.SetSize(20,20);
  b1.Canvas.Brush.Color := clBlue;
  b1.Canvas.Rectangle(0,0,20,20);
  Canvas.Draw(10,10,b1,$ff);  // Works
  Canvas.Draw(40,10,b1,$66);  // Works

  // I need it in combination with TransparentColor:
  b2 := TBitmap.Create;
  // next 3 lines are different from above
  b2.Transparent := true;
  b2.TransparentColor := clFuchsia;
  b2.Canvas.Brush.Color := clFuchsia;
  b2.SetSize(20,20);
  b2.Canvas.Brush.Color := clBlue;
  b2.Canvas.Ellipse(0,0,20,20);
  Canvas.Draw(10,40,b2,$ff);  // Works (full opacity)
  Canvas.Draw(40,40,b2,$66);  // Ignores the $66 Opacity

  b1.Free;
  b2.Free;
end;

生产:
在此输入图像描述

我怎么能用透明背景绘制(一个蓝色的圆圈),只有40%的不透明度?

如果可能的话,我会优先选择没有直接winapi的解决方案(如bitblt,...).

我尝试了几个hacks,比如将alpha通道转换为TColor值,但它不起作用.

在这里我尝试了什么:

procedure TForm1.FormPaint(Sender: TObject);
var b:TBitmap;
begin
  b := TBitmap.Create;
  b.PixelFormat := pf32bit;
  b.AlphaFormat := afDefined;

  b.Canvas.Brush.Color := 0 and ($ff shl 32);  // Background Transperency
  b.SetSize(20,20);
  b.Canvas.Brush.Color := clBlue + (($ff-$66) shl 32);
  b.Canvas.Ellipse(0,0,20,20);
  Canvas.Draw(10,10,b);

  b.Free;
end;

生产:
在此输入图像描述

提前致谢!

编辑:我的系统:windows 7 64bit上的delphi xe 5(但使用32位编译器)

1 个回答
  • 可以procedure TBitmap.DrawTransparent在单位图形中看到发生的情况.
    如果图像的属性设置为透明,如示例中的b2所示,将Graphics.TransparentStretchBlt使用StretchBlt不同的蒙版绘制位图 以绘制图像,并且无法使用Alpha通道.不透明的位图,你的b1,将使用AlphaBlend绘制 .

    要达到目标,您可以使用另一个位图b2,将Alphachannel设置为0,在b3上使用不透明度$ 66绘制b2,将每个像素的Alphachannel设置为255,这是b2中的clFuchsia,然后使用所需的不透明度绘制此位图

    在此输入图像描述在此输入图像描述

    type
      pRGBQuadArray = ^TRGBQuadArray;
      TRGBQuadArray = ARRAY [0 .. 0] OF TRGBQuad;
      TRefChanel=(rcBlue,rcRed,rcGreen);
    
    procedure SetBitmapAlpha(ABitmap: TBitMap; Alpha: Byte);
    var
      pscanLine32: pRGBQuadArray;
      nScanLineCount, nPixelCount : Integer;
    begin
      with ABitmap do
      begin
        PixelFormat := pf32Bit;
        HandleType := bmDIB;
        ignorepalette := true;
        alphaformat := afDefined;
        for nScanLineCount := 0 to Height - 1 do
        begin
          pscanLine32 := Scanline[nScanLineCount];
          for nPixelCount := 0 to Width - 1 do
            with pscanLine32[nPixelCount] do
             begin
              rgbReserved := Alpha;
            end;
        end;
      end;
    end;
    
    procedure AdaptBitmapAlpha(ABitmap,TranspBitmap:TBitmap);
    var
      pscanLine32,pscanLine32_2: pRGBQuadArray;
      nScanLineCount, nPixelCount : Integer;
    begin
      with ABitmap do
      begin
        PixelFormat := pf32Bit;
        HandleType := bmDIB;
        ignorepalette := true;
        alphaformat := afDefined;
        for nScanLineCount := 0 to Height - 1 do
        begin
          pscanLine32 := Scanline[nScanLineCount];
          pscanLine32_2 := TranspBitmap.Scanline[nScanLineCount];
          for nPixelCount := 0 to Width - 1 do
            with pscanLine32[nPixelCount] do
             begin
              // all picels with are not clFuchsia in the transparent bitmap
              if NOT ((pscanLine32_2[nPixelCount].rgbBlue=255) AND (pscanLine32_2[nPixelCount].rgbRed=255) AND (pscanLine32_2[nPixelCount].rgbGreen=0)  ) then
                 begin
                 rgbReserved := 255;
                 end
              else
                 begin
                   rgbBlue := 0;
                   rgbRed := 0;
                   rgbGreen := 0;
                 end;
            end;
        end;
      end;
    end;
    
    
    
    procedure TAForm.FormPaint(Sender: TObject);
    
    var b1,b2,b3:TBitmap;
    BF: TBlendFunction;
    begin
      // Example how it opacity works:
      b1 := TBitmap.Create;
      b1.SetSize(20,20);
      b1.Canvas.Brush.Color := clBlue;
      b1.Canvas.Rectangle(0,0,20,20);
      Canvas.Draw(10,10,b1,$ff);  // Works
      Canvas.Draw(40,10,b1,$66);  // Works
    
      // I need it in combination with TransparentColor:
      b3 := TBitmap.Create;
      b3.PixelFormat := pf32Bit;
    
      b2 := TBitmap.Create;
      b2.PixelFormat := pf32Bit;
      // next 3 lines are different from above
      b2.Transparent := true;
      b2.TransparentColor := clFuchsia;
      b2.Canvas.Brush.Color := clFuchsia;
      b2.SetSize(20,20);
      b2.Canvas.Brush.Color := clBlue;
      b2.Canvas.Ellipse(0,0,20,20);
    
      Canvas.Draw(10,40,b2,$ff);  // Works (full opacity)
    
      b3.SetSize(20,20);
      SetBitmapAlpha(b3,0);
      b3.Canvas.Draw(0,0,b2,$66);
      AdaptBitmapAlpha(b3,b2);
      Canvas.Draw(40,40,b3,$66);
    
      b1.Free;
      b2.Free;
      b3.Free;
    end;
    

    2022-12-13 11:00 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有