操作参考:
增加了滑块修改透明度
有一个bug,就是取色在绘图板上取色时,取到的颜色的透明度是0,也就是说,同样的颜色,有的是透明出来的,有的就是本身的颜色。但是不打算改了,这样的具有启发的BUG就留作纪念,如果想取色带透明度,可以在直接定位到代码里的 mesh 数组,这个数组里存着网格的32位带透明通道的颜色,获取当前像素颜色,就可以直接变成读取所在数组的颜色。
cpp
//代码来源:色环https://codebus.cn/luoyh/colorcircle
//代码来源:alpha透明贴图: https://codebus.cn/yangw/transparent-putimage
//代码来源:cur格式:https://mp.weixin.qq.com/s?__biz=MzkwNzMzMjIyNg==&mid=2247486257&idx=1&sn=1656090e498c22f391c00d0857f4b856&chksm=c0db94dcf7ac1dcacd4618240e05595b984a05b55d5f9f44d277aae41f4353b06bfa5e4294c4&cur_album_id=2474385342163419137&scene=189#wechat_redirect
//代码来源:icon格式生成文件:https://blog.csdn.net/jinzhuojun/article/details/8007586
#include <stdio.h>
#include <graphics.h>
#include<math.h>
#pragma warning(disable : 4996) // VS2022 对某些函数警告,但是为了方便移植,就无视这些警告 这样 Devc++ VC2010 VS2022 都能跑
#define PI acos(-1.0)
// 鼠标文件解析
//https://mp.weixin.qq.com/s?__biz=MzkwNzMzMjIyNg==&mid=2247486257&idx=1&sn=1656090e498c22f391c00d0857f4b856&chksm=c0db94dcf7ac1dcacd4618240e05595b984a05b55d5f9f44d277aae41f4353b06bfa5e4294c4&cur_album_id=2474385342163419137&scene=189#wechat_redirect
// 代码来源
//https://blog.csdn.net/jinzhuojun/article/details/8007586
// 中文注释添加自 @ bilibili 民用级脑的研发记录
// 结构注释来自 https://learn.microsoft.com/en-us/previous-versions/ms997538(v=msdn.10)
// 注意这个格式和下文中的 WrietByte 的对应关系
//typedef struct
//{
// WORD idReserved; // Reserved (must be 0)
// WORD idType; // Resource Type (1 for icons) // 2 指的是 cur 鼠标静态光标文件
// WORD idCount; // How many images?
// ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
//} ICONDIR, *LPICONDIR;
//typedef struct
//{
// BYTE bWidth; // Width, in pixels, of the image
// BYTE bHeight; // Height, in pixels, of the image
// BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
// BYTE bReserved; // Reserved ( must be 0)
// WORD wPlanes; // Color Planes
// WORD wBitCount; // Bits per pixel
// DWORD dwBytesInRes; // How many bytes in this resource?
// DWORD dwImageOffset; // Where in the file is this image?
//} ICONDIRENTRY, *LPICONDIRENTRY;
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
// 色环
void DrawColorCircle(int x, int y, int r, int h)
{
int H = h;
float S = 1.f;
float V = 1.f;
for (int i = 0; i < 360; i++)
{
H = int(H + 1) % 360;
setfillcolor(HSVtoRGB((float)H, S, V));
solidpie(x - r, y - r, x + r, y + r, i * (PI / 180), (i + 1) * (PI / 180));
}
}
// 数据写入
void Fwrite(FILE* f, char* data, int byte) // 一次写入 byte 个字节,且只写一次
{
if(1!=fwrite(data,byte,1,f))
{
perror("fwrite error");
exit(1);
}
}
// 数据写入
void WriteByte(FILE* f, unsigned int val,int byte) // 指定写入几个字节
{
char data[4];
assert(byte<=4); // 如果它的条件返回错误,则终止程序执行------菜鸟教程可查
memcpy((void*)data,(void*)&val,byte);
Fwrite(f,data,byte);
}
// 生成cur 格式文件 ,改写自 icon格式文件的生成,仅仅是 wPlane wBitCount 分别作为X,Y热点
void generate_ico_file(const char* filename,char * body,
int width, int height, int has_alpha,int HotX,int HotY)
{
int x,y;
int index=0;
int Size=0;
int offset = 6+ 1*16; // 6 = 2 +2 +2,这6个byte 是ico,cur通用的文件头。 16= 1+1+1+1 +2 +2,是一个图片的索引占 16 个字节, n个图片的索引占6*16个字节,,n个图片的因为在不同设备上使用不同型号分辨率的图片,这一堆图片都在一个 icon 或cur里
int bpp=32; // 32位的位图= 8位 alpha + 8 位 R, 8 位 G, 8 位 B
FILE* outfile=fopen(filename,"wb");
if(outfile==NULL)
{
perror("fopen error");
exit(1);
}
// icon文件头,类型与图片个数
WriteByte(outfile,0,2); // idReserved 保留位,一种格式,可用区分其他文件。
WriteByte(outfile,1,2); // idType 文件类型,如果是1 ,就是icon文件,如果是2 则是cur鼠标光标文件,这类文件格式一样。
WriteByte(outfile,1,2); // idCount 拥有的图片个数,icon为在不同屏幕上正常显示,会存储多个格式的图片以备选择
// 具体一个图片的索引信息
WriteByte(outfile,width,1); // bWidth
WriteByte(outfile,height,1); // bHeight
WriteByte(outfile,0,1); // bColorCount
WriteByte(outfile,0,1); // bReservered
WriteByte(outfile,HotX,2); // wPlanes // 这里是.cur热点位置 X
WriteByte(outfile,HotY,2); // wBitCount // 这里是.cur热点位置 Y
Size = 40 + height * ((width + 31) / 32 * 32 / 8 + width * 3); //Note 4 bytes alignment // 这里计算文件索引头与图像数据的总数 ,40=4+4+4+2+2+4*6 个字节。 (width+31)/32是计算int 型AND 位图个数,width / 32,但是不能确定%32 的部分,所以+31 然后再除以 32 。1个int 有4个字节,共32bit,每个bit表示一个像素是否被光栅操作 AND 覆盖,行数 * 32计算一共需要多少bit ,/8是确定有多少字节。
if (bpp == 32)
Size += height * width;
WriteByte(outfile,Size, 4); //dwBytesInRes
WriteByte(outfile,offset, 4); //dwImageOffset
WriteByte(outfile,40, 4); //biSize
WriteByte(outfile,width, 4); //biWidth
WriteByte(outfile,2 * height, 4); //biHeight
WriteByte(outfile,1, 2); //biPlanes
WriteByte(outfile,bpp, 2); //biBitCount
WriteByte(outfile,0, 4); //biCompression
WriteByte(outfile,0, 4); //biSizeImage
WriteByte(outfile,0, 4); //biXPelsPerMeter
WriteByte(outfile,0, 4); //biYPelsPerMeter
WriteByte(outfile,0, 4); //biClrUsed
WriteByte(outfile,0, 4); //biClrImportant
// XOR mask
for (y=height - 1 ; y >= 0; --y) // 调换打印高度就不会读取了 ,确定为倒置打印,windows倒着读取数据.从左往右,从下往上,所以为了图片倒着读取之后是正的,需要把原图第一行像素数据打印到倒数最后一行
{
for (x = 0; x < width; ++x)
{
index = (y * width + x) * 4;
WriteByte(outfile, body[index], 1); //Blue
WriteByte(outfile, body[index + 1], 1); //Green
WriteByte(outfile, body[index + 2], 1); //Red
WriteByte(outfile, has_alpha ? body[index + 3] : 255, 1); //Alpha
}
}
// AND mask
for (y = 0; y < (height * ((width + 31) / 32 * 32 / 8)); ++y)
{
WriteByte(outfile, 1, 1); // 1 在屏幕上显示图片,0则不显示图片,表示为整个图片没有。 三元光栅操作参考
}
fclose(outfile);
}
int main()
{
initgraph(1640, 980, 1);
setbkcolor(GREEN);
cleardevice();
int** mesh;
int drawdesklx; // 绘图板左上角坐标
int drawdeskly;
int pixnum; // 一个正方形瓦片边长像素
int mapi; // 一列有多少个小方格
int mapj; // 一行有多少个小方格
int drawmapi; // 网格坐标
int drawmapj;
int drawoldmapi; // 同一次绘制的前一个涂色的位置
int drawoldmapj;
int isdraw; // 绘制状态
int drawdeskrx; // 绘图板右下角坐标
int drawdeskry;
int drawsmallflag;
isdraw=0;
drawsmallflag=0;
drawdesklx=200;
drawdeskly=200;
mapi=32; // 默认 64*64 大小的 .cur文件 // 这里改参数只会改写分辨率,一个像素对应屏幕一个或多个像素,但不会改变图标大小。数值过大会生成失败,原因是int数值上限比较小,不够存储数据了
mapj=32; // 这里改参数只会改写分辨率,一个像素对应屏幕一个或多个像素,但不会改变图标大小。 数值过大会生成失败,原因是int数值上限比较小,不够存储数据了
drawmapi=-1;
drawmapj=-1;
pixnum = 16 ;
drawoldmapi=-1;
drawoldmapj=-1;
drawdeskrx=drawdesklx+pixnum*mapj; // 瓦片个数 * 一个瓦片的像素 = 画板总长度
drawdeskry=drawdeskly+pixnum*mapi;
int left=0; // 刷新绘图板的当前瓦片位置坐标
int top=0;
int pentake=0x8FFF0000; // 选中的 ARGB 透明度与颜色
int image[mapi * mapj]; // 分配像素内存
int i, j;
int background = 0x0000CCFF; // 背景色:天依蓝,颜色按十六进制数
int HotX=0; // 鼠标热点位置
int HotY=0;
mesh = new int* [mapi];
for(int i=0; i<mapi; i++)
mesh[i]=new int[mapj];
for(int i=0; i<mapi; i++)
{
for(int j=0; j<mapj; j++)
{
mesh[i][j]=0; // 加入默认的背景色
}
}
int h = 0;
DrawColorCircle(800+640 / 4, 480 / 2, 140, h); // 绘制色环
setfillcolor(RGB(128, 126, 129));
for (int i = 0; i < mapi ; i++)
{
left = 0;
for (int j = 0; j < mapj ; j++)
{
int pennumber = mesh[i][j]; // 读取游戏大地图数组序号
//int red =255;
//int blue =255;
//int green =255;
//green = 0x000000FF;
//
//int pixel=0x0000CCFF;
//F=1111 1111 =255;
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源
int sa = ((pennumber & 0xff000000) >> 24);
int sr = ((pennumber & 0x00ff0000) >> 16);
int sg = ((pennumber & 0xff00) >> 8);
int sb = pennumber & 0xff;
int dr = ((background& 0xff0000) >> 16);
int dg = ((background & 0xff00) >> 8);
int db = background & 0xff;
int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16) // sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优
| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)
| (sb*sa/255 + db * (255 - sa) / 255);
setfillcolor(BGR(dst)); // COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印
fillrectangle(drawdesklx+left, drawdeskly+top, drawdesklx+left + pixnum, drawdeskly+top + pixnum);
left += pixnum; // 往右移动,准备下一次绘制位置,
}
top += pixnum; // 往下移动,准备下一次绘制位置
}
char icon[200]="图标预览";
// setbkmode(TRANSPARENT); // 设置背景为透明
settextcolor(BLACK); // 设置字颜色为黑
outtextxy(40,160,icon); // 打印提示
setfillcolor(GREEN);
fillrectangle(10,100,300,140) ; // 覆盖之前的文字提示
char tips[200];
sprintf(tips,"热点位置 HotX HotY = %d,%d",HotX,HotY); // 格式化数字
// setbkmode(TRANSPARENT); // 设置背景为透明
settextcolor(BLACK); // 设置字颜色为黑
outtextxy(10,100,tips); // 打印提示
int lx; // 按钮位置,大小
int ly;
int rx;
int ry;
int width;
int height;
width=20;
height=50;
lx=1250;
ly=200;
rx=lx+width;
ry=ly+height;
int limitlx; // 边界矩形
int limitly;
int limitrx;
int limitry;
limitlx=lx;
limitly=200;
limitrx=limitlx+width;
limitry=600+height; // 因为计算透明度 255除以可移动长度然后得出平均每个像素对应几个颜色 时不能方便计算可移动大小,于是直接设定可移动长度再增加一块按钮停泊区
int ispressing; // 滑块是否按下
int drawsmallflagv2; // 绘制控制
int oldmx; // 鼠标在本次拖拽时最先按下的位置
int oldmy;
int drawx; // 当前绘制的位置
int drawy;
int drawoldx; // 比较上一次绘制的位置,如果相同就不绘制
int drawoldy;
drawx=0;
drawy=0;
oldmx=0;
oldmy=0;
ispressing=0; // 滑块未被按下
drawsmallflag=0; // 不进行绘制
char tipsv2[200]; // 滑块信息,用于透明度测试
int trans; // 透明数据,0是最透明,255是完全不透明
trans=255;
setfillcolor(BLUE);
fillrectangle(lx,ly,rx,ry); // 绘制滑块
settextcolor(BLUE); // 字体蓝色
settextstyle(19, 0, _T("黑体")); // 设置当前字体为高 16 像素的"Consolas"。(VC6 / VC2008 / VC2010 / VC2012)
sprintf(tipsv2,"当前透明度 trans 是:%d",trans);
outtextxy(limitlx-50,limitly-50,tipsv2);
ExMessage m;
while(1)
{
while(peekmessage(&m,EX_KEY|EX_MOUSE,1))
{
switch (m.message)
{
case WM_LBUTTONDOWN:
if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry) // 绘制
{
isdraw=1;
drawmapi=-1;
drawmapj=-1;
}
else if(ispressing==0&&m.x>lx&&m.y>ly&&m.x<rx&&m.y<ry)
{
ispressing=1;
drawx=0;
drawy=0;
oldmx=m.x;
oldmy=m.y;
}
break;
case WM_LBUTTONUP:
isdraw=0;
drawoldmapi=-1;
drawoldmapj=-1;
drawsmallflag=0;
// 滑块透明选则部分代码复制粘贴过来了
if(ispressing==1)
{
ly=drawy;
ry=ly+height;
ispressing=0;
drawoldx=0;
drawoldy=0;
drawsmallflagv2=0; // 清除数据,禁止重复绘制
}
break;
case WM_RBUTTONDOWN:
if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry&&m.ctrl) // 绘制
{
HotY=(m.y-drawdeskly)/pixnum;
HotX=(m.x-drawdesklx)/pixnum;
setfillcolor(GREEN);
fillrectangle(10,100,300,140) ; // 覆盖之前的文字提示
char tips[200];
sprintf(tips,"热点位置 HotX HotY = %d,%d",HotX,HotY); // 格式化数字
// setbkmode(TRANSPARENT); // 设置背景为透明
settextcolor(BLACK); // 设置字颜色为黑
outtextxy(10,100,tips); // 打印提示
}
else
{
pentake = getpixel(m.x,m.y);
setfillcolor(pentake);
fillrectangle(800,500,900,600);
pentake=pentake|0xFF000000; // 要颜色转换完毕前再补充alpha 通道,否则半透明
pentake=BGR(pentake); // 因为 getpixel 已经是 BGR了,但是在后面的上色还个BGR转换,所以还需要再转换一次BGR来抵消后面的BGR转换。
// BGR转换是因为保存数据时是 RGB 保存,但是当绘制图像时,却是蓝色红色相反,所以绘制的时候要调整蓝色红色,保存的是按RGB来
// setfillcolor(GREEN);
// fillrectangle(800,400,1240,440);
char colortips[200];
sprintf(colortips,"new alpha:%d,red:%d,green:%d,blue:%d",(pentake&0xFF000000)>>24,(pentake&0x00FF0000)>>16,(pentake&0x0000FF00)>>8,(pentake&0x000000FF));
outtextxy(800,400,colortips); // 打印颜色提示
int pennumber=pentake&0x00FFFFFF; // 清除占一个字节透明度数据
pentake=pennumber|(trans<<24);
pennumber=pentake;
setfillcolor(BGR(background));// 0000FF红色变蓝色,这样符合RGB 数据位置
fillrectangle(lx+60,limitly,lx+160,limitly+100);
int sa = ((pennumber & 0xff000000) >> 24);
int sr = ((pennumber & 0xff0000) >> 16);
int sg = ((pennumber & 0xff00) >> 8);
int sb = pennumber & 0xff;
int dr = ((background& 0xff0000) >> 16);
int dg = ((background & 0xff00) >> 8);
int db = background & 0xff;
int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16) // sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优
| ((sg*sa/255 + dg * (255 - sa) / 255) << 8) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| (sb*sa/255 + db * (255 - sa) / 255);
setfillcolor(BGR(dst)); // COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印
fillrectangle(lx+60,limitly+180,lx+160,limitly+280);
// 文字组件覆盖
int transv2=sa;
sprintf(tipsv2,"当前透明度 sa 是:%d",transv2);
outtextxy(limitlx+50,limitly+120,tipsv2);
}
break;
case WM_KEYDOWN:
switch (m.vkcode)
{
case VK_F1:
int width=mapj;
int height=mapi;
for (i = 0; i < height; ++i)
{
for (j = 0; j < width; ++j)
{
image[i * width + j] = mesh[i][j]; // 透明色 叠加 网格数据
} // Alpha 透明 0x00, red: 00, green: 00, blue: 00 各 bit 位对应 ARGB
} // 0x00000000是完全透明 0x5F000000 可以看出来不完全透明,可知透明度可调节
generate_ico_file("testv8_透明度测试.cur", (char *)image, width, height, 1,HotX,HotY);
printf("Save cur,文件名:testv8_透明度测试.cur\n");
break;
}
}
}
if(isdraw)
{
if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry)
{
drawmapi=(m.y-drawdeskly)/pixnum;
drawmapj=(m.x-drawdesklx)/pixnum;
if(drawmapi!=drawoldmapi||drawmapj!=drawoldmapj) // 检测是否是旧位置
{
mesh[drawmapi][drawmapj]=pentake;
drawoldmapi=drawmapi;
drawoldmapj=drawmapj;
drawsmallflag=1;
}
}
}
else if(ispressing==1)
{
drawy=ly+m.y-oldmy;
if(drawy<limitly)
drawy=limitly;
else if(drawy+height>limitry)
drawy=limitry-height;
if(drawy!=drawoldy)
{
drawoldy=drawy;
drawsmallflagv2=2;
}
trans=255 - 255/1.0/(limitry-height-limitly)*(drawy-limitly); // 计算多少个像素,一个像素顶0.81个透明度
// 255减去计算的像素, 得到从底向上的数据
}
if(drawsmallflag==1)
{
top=0;
left=0;
for (int i = 0; i < mapi ; i++)
{
left = 0;
for (int j = 0; j < mapj ; j++)
{
int pennumber = mesh[i][j]; // 读取游戏大地图数组序号
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源
int sa = ((pennumber & 0xff000000) >> 24);
int sr = ((pennumber & 0xff0000) >> 16); // 源值已经乘过了透明系数
int sg = ((pennumber & 0xff00) >> 8); // 源值已经乘过了透明系数
int sb = pennumber & 0xff; // 源值已经乘过了透明系数
int dr = ((background& 0xff0000) >> 16);
int dg = ((background & 0xff00) >> 8);
int db = background & 0xff;
int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| ((sg*sa/255 + dg * (255 - sa) / 255) << 8) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| (sb*sa/255 + db * (255 - sa) / 255); // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
setfillcolor(BGR(dst)); // COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印
fillrectangle(drawdesklx+left, drawdeskly+top, drawdesklx+left + pixnum, drawdeskly+top + pixnum);
left += pixnum; // 往右移动,准备下一次绘制位置,
}
top += pixnum; // 往下移动,准备下一次绘制位置
}
top=0;
for (int i = 0; i < mapi ; i++)
{
left = 0;
for (int j = 0; j < mapj ; j++)
{
int pennumber = mesh[i][j]; // 读取游戏大地图数组序号
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源
int sa = ((pennumber & 0xff000000) >> 24);
int sr = ((pennumber & 0xff0000) >> 16);
int sg = ((pennumber & 0xff00) >> 8);
int sb = pennumber & 0xff;
int dr = ((background& 0xff0000) >> 16);
int dg = ((background & 0xff00) >> 8);
int db = background & 0xff;
int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| ((sg*sa/255 + dg * (255 - sa) / 255) << 8) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| (sb*sa/255 + db * (255 - sa) / 255); // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
// 绘制预览图
putpixel(drawdesklx-64+left,drawdeskly-32+top,BGR(dst)); // COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印
left += 1; // 往右移动,准备下一次绘制位置,
}
top += 1; // 往下移动,准备下一次绘制位置
}
}
else if(drawsmallflagv2==2)
{
setfillcolor(RGB(150,150,150));
fillrectangle(limitlx,limitly,limitrx,limitry);
setfillcolor(BLUE);
fillrectangle(lx,drawy,rx,drawy+height);
setbkcolor(GREEN); // 字体背景默认采用图像的背景色
setfillcolor(GREEN);
fillrectangle(limitlx-50,limitly-50,limitlx+300,limitly);
// setbkmode(TRANSPARENT); // 字体背景透明
settextcolor(BLUE); // 字体蓝色
settextstyle(19, 0, _T("黑体")); // 设置当前字体为高 16 像素的"Consolas"。(VC6 / VC2008 / VC2010 / VC2012)
sprintf(tipsv2,"当前透明度 trans 是:%d",trans);
outtextxy(limitlx-50,limitly-50,tipsv2);
int pennumber=pentake&0x00FFFFFF; // 清除占一个字节透明度数据
pentake=pennumber|(trans<<24);
pennumber=pentake;
// int background=0x00000000;
setfillcolor(BGR(background));// 0000FF红色变蓝色,这样符合RGB 数据位置
fillrectangle(lx+60,limitly,lx+160,limitly+100);
int sa = ((pennumber & 0xff000000) >> 24);
int sr = ((pennumber & 0xff0000) >> 16); // 源值已经乘过了透明系数
int sg = ((pennumber & 0xff00) >> 8); // 源值已经乘过了透明系数
int sb = pennumber & 0xff; // 源值已经乘过了透明系数
int dr = ((background& 0xff0000) >> 16);
int dg = ((background & 0xff00) >> 8);
int db = background & 0xff;
int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16) // sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优
| ((sg*sa/255 + dg * (255 - sa) / 255) << 8) // y=kx+b; sa = sb + (sa-sb)/1.0*x (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);
| (sb*sa/255 + db * (255 - sa) / 255);
setfillcolor(BGR(dst)); // COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印
fillrectangle(lx+60,limitly+180,lx+160,limitly+280);
// 文字组件覆盖
setfillcolor(GREEN);
fillrectangle(limitlx+50,limitly+120,limitlx+300,limitly+160);
int transv2=sa;
sprintf(tipsv2,"当前透明度 sa 是:%d",transv2);
outtextxy(limitlx+50,limitly+120,tipsv2);
}
Sleep(2);
}
return 0;
}