请教各位大虾,如何让一个位图让他背影全透明,前景半透明??希望各位提一下实现的原理,不一定要代码,我一样给分

pmjsmallworm 2007-10-29 09:33:43
最近做东西,遇到一个问题,也翻了很多资料,就是在C++中,单独的做透明很简单,就是绘图时让透明色不绘出来就是了,半透明也很简单,微软有个函数完全解决问题.
可是如何让一个位图,背影全透明,而前景半透明呢?比如说我有一个位图,放在一个窗体上,位图背景色是蓝色,上面用红色写了个字,然后要实现的效果是,蓝色在绘图时被扣掉了,透明.而红色显示半透明,可以透过显示窗体上的东西.
现在我只能实现透明背景,或者是半透明图片,而怎么让他前景半透明,而背景透明呢?
忘各位大虾,指点一二.
...全文
398 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
quentinliu 2007-11-02
  • 打赏
  • 举报
回复
点管理帖子
pmjsmallworm 2007-11-02
  • 打赏
  • 举报
回复
怎么给不了分?点那个?
贴子加分,怎么一直说还未到5天
pmjsmallworm 2007-11-02
  • 打赏
  • 举报
回复
有问题再请教大家...
pmjsmallworm 2007-11-02
  • 打赏
  • 举报
回复
看来我为了解决背景问题还要在拖动控件的结束位置,在绘控件之前,取出屏幕背景,和控件要绘的图形进行一个ALPHA.呵呵有挑战...
结贴啦!
xugang_2001 2007-10-31
  • 打赏
  • 举报
回复
漫漫来了,一个一个解决,呵呵
pmjsmallworm 2007-10-31
  • 打赏
  • 举报
回复
谢谢幽明天竹!
嗯,我对这块真的很陌生,我还要仔细研究一下.其实真正难的还有很多问题,比如说就算实现了上述所有功能.控件拖动时的刷新问题(因为背景是透明的,所以拖动之后,透明区域还是拖动前区域的东西),放在容器底层的选中问题等等.难呀!

星羽 2007-10-30
  • 打赏
  • 举报
回复
最笨的办法就是自己生成这张图片

把当前背景图读出来,和你的图做混合

这个混合要你自己做

pmjsmallworm 2007-10-30
  • 打赏
  • 举报
回复
谢谢幽明天竹,学到了不少东西,半透明微软有函数ALPHABLEND()可以直接实现,只要设几个参数,绘屏的时候就透明了.当然透明也有相应的算法也能实现.
因为我做的OCX的控件,等于说是在ONDRAW函数里把想写的东西绘在屏幕上的,单独的透明,和单独的半透明都能实现,但是怎么样能让透明和半透明一起实现呢?
有可能在绘图时,让读出来的位图一种颜色透明,而另一种颜色半透明吗?
背景是纯色的,比如说是一个蓝色背景的图,上面用红色写了个字,然后在绘屏时,蓝色就扣掉,为透明色.而红色为半透明,而显示下面的文字或面板.
xugang_2001 2007-10-30
  • 打赏
  • 举报
回复

D.带关键色的图片合成
图片中用一种特殊的颜色来代表图片透明的部分,这个关键色一般会选择图片中实际没
有用到的颜色;程序在显示图片的时候跳过这些特殊像素,从而形成透明效果;
GIF的透明、很多游戏中的透明贴图都应用了这种原理;
比如一幅带有透明关键色的图片:


该图片中的关键色颜色为纯红色,R=255;G=0;B=0;

函数实现:
void PicBlend_KeyColor(const TPicRegion& picDst,const TPicRegion& picSrc,const TARGB32& KeyColor)
{
long width =min(picDst.width ,picSrc.width );
long height=min(picDst.height,picSrc.height);
unsigned long KeyColorValue=(*(unsigned long*)&KeyColor) & 0x00FFFFFF;
for (long y=0;y<height;++y)
{
for (long x=0;x<width;++x)
{
TARGB32 SrcColor=Pixels(picSrc,x,y);
if ( ( (*(unsigned long*)&SrcColor) & 0x00FFFFFF )!=KeyColorValue )
Pixels(picDst,x,y)=SrcColor;
}
}
}

E.带Alpha通道的图片的混合
PicBlend_KeyColor的实现方式有一些缺点,比如美工做图片的时候需要"抠边"
(将透明区域和不透明区域分离),增加了工作量;合成的图片在“精灵”的边界区域
有锯齿感(如果有缩放的话,锯齿感会更强);我们需要一种更加自由的定义方式,
每个颜色增加一个专门的通道Alpha通道来描述该像素的透明信息;
Alpha属于[0..255],
带Alpha通道的颜色混合公式:Dst=( Dst*(255-Src.Alpha) + Src*Src.Alpha ) / 255;
(提示: 当Alpha==0时, 公式化简为: Dst=Dst; //Src完全透明
当Alpha==255时,公式化简为: Dst=Src; //Src完全不透明 )
void PicBlend(const TPicRegion& picDst,const TPicRegion& picSrc)
{
long width =min(picDst.width ,picSrc.width );
long height=min(picDst.height,picSrc.height);
for (long y=0;y<height;++y)
{
for (long x=0;x<width;++x)
{
TARGB32& DstColor=Pixels(picDst,x,y);
TARGB32 SrcColor=Pixels(picSrc,x,y);
unsigned long Alpha=SrcColor.a;

DstColor.b=(DstColor.b*(255-Alpha) + SrcColor.b*Alpha)/255;
DstColor.g=(DstColor.g*(255-Alpha) + SrcColor.g*Alpha)/255;
DstColor.r=(DstColor.r*(255-Alpha) + SrcColor.r*Alpha)/255;
DstColor.a=(DstColor.a*(255-Alpha) + SrcColor.a*Alpha)/255;
}
}
}
xugang_2001 2007-10-30
  • 打赏
  • 举报
回复
   我以前做游戏的时候经常用到,lz所说的其实就是图片的各种透明效果,可以用到带Alpha通道的图片,然后再程序中对Alpha通道的图片进行融合,就可以实现出各式各样的效果来,所以很多2D游戏中的动画效果都是这样实现的,比如QQ游戏中的对对碰中的爆炸效果,就是把一组不同Alpha通道的图片顺序播放就OK了。至于Alpha融合具体怎么弄,我贴个文章你看看:

正文:
为了便于讨论,这里只处理32bit的ARGB颜色;
代码使用C++,编译器:VC2005


A: 一些颜色和图片的数据定义:
#define asm __asm

typedef unsigned char TUInt8; // [0..255]
struct TARGB32 //32 bit color
{
TUInt8 b,g,r,a; //a is alpha
};

struct TPicRegion //一块颜色数据区的描述,便于参数传递
{
TARGB32* pdata; //颜色数据首地址
long byte_width; //一行数据的物理宽度(字节宽度);
//abs(byte_width)有可能大于等于width*sizeof(TARGB32);
long width; //像素宽度
long height; //像素高度
};

//那么访问一个点的函数可以写为:
inline TARGB32& Pixels(const TPicRegion& pic,const long x,const long y)
{http://blog.csdn.net/yangdelong/archive/2007/08/14/1742392.aspx
Alpha颜色混合的魔法 上篇 “法术篇” - 杨德龙的专栏 - CSDNBlog
return ( (TARGB32*)((TUInt8*)pic.pdata+pic.byte_width*y) )[x];
}

B: 混合两幅图片
这里简单的按照50%的比例混合两幅图片;算法也很简单,就是将颜色分量直接
相加,然后取平均值;函数如下:
void PicBlend_half(const TPicRegion& picDst,const TPicRegion& picSrc)
{
long width =min(picDst.width ,picSrc.width );
long height=min(picDst.height,picSrc.height);
for (long y=0;y<height;++y)
{
for (long x=0;x<width;++x)
{
TARGB32& DstColor=Pixels(picDst,x,y);
TARGB32 SrcColor=Pixels(picSrc,x,y);

DstColor.b=(DstColor.b + SrcColor.b)/2;
DstColor.g=(DstColor.g + SrcColor.g)/2;
DstColor.r=(DstColor.r + SrcColor.r)/2;
DstColor.a=(DstColor.a + SrcColor.a)/2;
}
}
}

C.按比例混合两幅图片
我们来增强PicBlend_half的混合能力,允许指定两幅图片的混合比例(参数Alpha);
Alpha属于[0..255],当Alpha=127的时候与PicBlend_half等价(小的误差不算:)
Alpha颜色混合公式:Dst=( Src0*(255-Alpha) + Src1*Alpha ) / 255;
void PicBlend_Alpha(const TPicRegion& picDst,const TPicRegion& picSrc,TUInt8 Alpha)
{
long width =min(picDst.width ,picSrc.width );
long height=min(picDst.height,picSrc.height);
for (long y=0;y<height;++y)
{
for (long x=0;x<width;++x)
{
TARGB32& DstColor=Pixels(picDst,x,y);
TARGB32 SrcColor=Pixels(picSrc,x,y);

DstColor.b=(DstColor.b*(255-Alpha) + SrcColor.b*Alpha)/255;
DstColor.g=(DstColor.g*(255-Alpha) + SrcColor.g*Alpha)/255;
DstColor.r=(DstColor.r*(255-Alpha) + SrcColor.r*Alpha)/255;
DstColor.a=(DstColor.a*(255-Alpha) + SrcColor.a*Alpha)/255;
}
}
}


提示: 利用两幅图片然后不断的调整Alpha混合参数就可以得到漂亮的
动画效果(过渡\切换屏幕等);
Wolf0403 2007-10-30
  • 打赏
  • 举报
回复
背景是纯色的?设置成 color key
印象中许多图形图象库都有这个功能的,通过 color key 实现透明
pmjsmallworm 2007-10-30
  • 打赏
  • 举报
回复
呵呵,我也想二个图片放上去.但是我这个是做到OCX控件里的,他是直接绘到屏上的,我只能操控绘制屏幕的过程,只能在绘制过程中去掉背景,和半透明效果.....
quentinliu 2007-10-30
  • 打赏
  • 举报
回复
当成两个图片显示,最简单的实现,不用考虑那么复杂
xugang_2001 2007-10-30
  • 打赏
  • 举报
回复
 因为我做的OCX的控件,等于说是在ONDRAW函数里把想写的东西绘在屏幕上的,单独的透明,和单独的半透明都能实现,但是怎么样能让透明和半透明一起实现呢?
有可能在绘图时,让读出来的位图一种颜色透明,而另一种颜色半透明吗?
 
 完全是可行的,就是按我说的办发,可能你还没有理解Alpha的实质作用。我们实现一张图片的全透明或者半透明的确很容易,假如我们要实现一种效果,就是一张图片在另外一张背景图片上如何实现某些区域透明某些半透明或者不同百分比透明呢?为了解决这种问题,常规的方法都不可行,所以才会有带Alpha通道的图片产生。也就是说带Alpha通道的图片每个单独像素都可以进行Alpha融合,达到你想要的任何效果。注意这里的算法已经有了,就是我上面贴的带Alpha通道的图片的混合,至于每个象素的Alpha值如何这个需要Photoshop制图的时候就考虑好。往往美工在设计图片的时候都会合程序员商量,制作出需要的特殊效果。也就是不同的Alpha通道。你可以找一个有经验的美工设计问问就知道了。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧