登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> CLQ工作室开源代码 >> 主题: [32bit bmp][32位alpha bmp]一个 alpha 混合公式     [回主站]     [分站链接]
标题
[32bit bmp][32位alpha bmp]一个 alpha 混合公式
clq
浏览(465) + 2021-10-10 12:35:01 发表 编辑

关键字:

[2021-10-10 13:19:55 最后更新]
一个 alpha 混合公式

我记得 gdi 其实直接支持 32 位 bitmap 的 alpha 透明的。不知道是我记错了还是什么,相关代码一直没找到。

https://www.codeproject.com/Articles/7944/Transparent-Button-with-Region-and-Anti-Aliased-Ed

----------------------------------------------------------------
A Bit About Anti-Aliasing and Alpha-Blending

One of the trickiest parts of masking images on top of images is the rough edges, or pixelation, of the meeting places of these images when they are not straight edges. The solution to these rough edges is to blend the edges in a technique called anti-aliasing. In this demo, anti-aliasing is done using an alpha-blending technique, where the transparency of the foreground bitmap pixel determines the strength of color at any particular position on the display.

The formula for blending source and background pixels is:

displayColor = sourceColor × sourceAlpha / 255 + backgroundColor × (255 – sourceAlpha) / 255

where the alpha value range is 0 (transparent) to 255 (opaque). Therefore, any part of the button's bitmap that has an alpha value of 0 will not be seen, and areas with values greater than zero will be blended with the background at varying strengths up to 255 where the button's bitmap will be fully opaque.

// alphaBlend routine
static inline unsigned int alphaBlend(const unsigned
int bg, const unsigned int src)
{
unsigned int a = src >> 24; // sourceColor alpha

// If source pixel is transparent, just return the background
if (0 == a) return bg;

// alpha-blend the src and bg colors
unsigned int rb = (((src & 0x00ff00ff) * a) +
((bg & 0x00ff00ff) * (0xff - a))) & 0xff00ff00;
unsigned int g = (((src & 0x0000ff00) * a) +
((bg & 0x0000ff00) * (0xff - a))) & 0x00ff0000;

return (src & 0xff000000) | ((rb | g) >> 8);
}



clq
2021-10-10 12:37:13 发表 编辑

现在这样的代码并不行,供参考。
procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap:TBitmap;

Row, Col, ACol: integer;
p: PRGBQuad;
alpha, gray:Byte;
alphas:array[0..7] of Byte;

//--------
BlendFunction: TBlendFunction;
BitmapPos: TPoint;
BitmapSize: TSize;

begin
//bmp.Canvas.Handle

Bitmap := TBitmap.Create;
//try
// Bitmap.LoadFromFile('splash.bmp');
Bitmap.LoadFromFile('c:\2.bmp');

Bitmap.PixelFormat := pf32bit;//clq


for Row := 0 to Bitmap.Height-1 do
begin
Col := Bitmap.Width;
p := Bitmap.ScanLine[Row];

if Row = 0 then alpha := 100;
if Row = 1 then alpha := 80;//50;
if Row = 2 then alpha := 60;//155;
if Row = 3 then alpha := 45;//200;
if Row = 4 then alpha := 30;//255;
if Row = 5 then alpha := 20;//255;
if Row = 6 then alpha := 10;//255;
if Row = 7 then alpha := 5;//255;

if Row = 0 then gray := 1;
if Row = 1 then gray := 50;
if Row = 2 then gray := 155;
if Row = 3 then gray := 200;
if Row = 4 then gray := 255;

gray := 0;

while (Col > 0) do
begin
//p.rgbRed := 110;
//p.rgbGreen := 110;
//p.rgbBlue := 110;

p.rgbReserved := 110;

inc(p);
dec(Col);
end;
end;

Canvas.Draw(0,0, Bitmap);

BitBlt(Canvas.Handle, 0, 0, 90, 90, Bitmap.Canvas.Handle, 0, 0, SRCCOPY);

Exit;

clq
2021-10-10 13:19:55 发表 编辑

一般的做法都是用背景色和原色计算出来,除了我忘记的那种方式外。其实还可以用 AlphaBlend 的 windows api 函数来直接画透明色。不过要事先再计算 r,g,b 的值,公式是 r,g,b 分别乘 a / 255 ,即要用 alpha 值来减弱它们本来的值先。
不知道为什么 AlphaBlend 不直接做这一步,感觉很没必要啊。不过 windows 的 api 设计有时候就是很反人类的。

参考
https://stackoverflow.com/questions/307348/how-to-draw-32-bit-alpha-channel-bitmaps

实例如下。delphi 代码,纯 c 的话啰嗦一下点。
----------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap:TBitmap;

Row, Col, ACol: integer;
p: PRGBQuad;
alpha, gray:Byte;
alphas:array[0..7] of Byte;

//--------
BlendFunction: TBlendFunction;
BitmapPos: TPoint;
BitmapSize: TSize;

//----
bf:TBLENDFUNCTION;
//alpha:Byte;

begin
//bmp.Canvas.Handle

Bitmap := TBitmap.Create;
//try
// Bitmap.LoadFromFile('splash.bmp');
Bitmap.LoadFromFile('c:\2.bmp');

Bitmap.PixelFormat := pf32bit;//clq


for Row := 0 to Bitmap.Height-1 do
begin
Col := Bitmap.Width;
p := Bitmap.ScanLine[Row];

if Row = 0 then alpha := 100;
if Row = 1 then alpha := 80;//50;
if Row = 2 then alpha := 60;//155;
if Row = 3 then alpha := 45;//200;
if Row = 4 then alpha := 30;//255;
if Row = 5 then alpha := 20;//255;
if Row = 6 then alpha := 10;//255;
if Row = 7 then alpha := 5;//255;

if Row = 0 then gray := 1;
if Row = 1 then gray := 50;
if Row = 2 then gray := 155;
if Row = 3 then gray := 200;
if Row = 4 then gray := 255;

gray := 0;

while (Col > 0) do
begin
//p.rgbRed := 110;
//p.rgbGreen := 110;
//p.rgbBlue := 110;

// p.rgbRed := 0;
// p.rgbGreen := 0;
// p.rgbBlue := 0;

//AlphaBlend 确实可以透明,不过要计算下颜色值. 否则会发现透明值是不对的
//参考 https://stackoverflow.com/questions/307348/how-to-draw-32-bit-alpha-channel-bitmaps

alpha := 10;

p.rgbRed := byte(Trunc(p.rgbRed * alpha / 255));
p.rgbGreen := byte(Trunc(p.rgbGreen * alpha / 255));
p.rgbBlue := byte(Trunc(p.rgbBlue * alpha / 255));

//p.rgbReserved := 1;
p.rgbReserved := alpha;

inc(p);
dec(Col);
end;
end;

//Canvas.Draw(0,0, Bitmap);

//BitBlt(Canvas.Handle, 0, 0, 90, 90, Bitmap.Canvas.Handle, 0, 0, SRCCOPY);

//----------------------------------------------------------------
//https://stackoverflow.com/questions/307348/how-to-draw-32-bit-alpha-channel-bitmaps
//BLENDFUNCTION bf;
//bf.BlendOp = AC_SRC_OVER;
//bf.BlendFlags = 0;
//bf.SourceConstantAlpha = 255;
//bf.AlphaFormat = AC_SRC_ALPHA;
//
//HDC src_dc = m_Image.GetDC();
//::AlphaBlend(dc, rect.left, rect.top, 16, 16, src_dc, 0, 0, 16, 16, bf);

//BLENDFUNCTION bf;
bf.BlendOp := AC_SRC_OVER;
bf.BlendFlags := 0;
bf.SourceConstantAlpha := 255;
bf.AlphaFormat := AC_SRC_ALPHA;

//HDC src_dc = m_Image.GetDC();
Windows.AlphaBlend(Canvas.Handle, 0, 0, 90, 90, Bitmap.Canvas.Handle, 0, 0, 90, 90, bf);


总数:2 页次:1/1 首页 尾页  
总数:2 页次:1/1 首页 尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1