FIL ICON_FIL; /* 图标文件结构体 */
UINT RestBytes; /* 文件剩余的字节数 */
u8 ICON_Buf[512]; /* 缓冲区 */
u16 alpha_blend565(u16 src,u16 dst,u8 alpha)
{
u32 src2;
u32 dst2;
src2=((src<<16)|src)&0x07E0F81F;
dst2=((dst<<16)|dst)&0x07E0F81F;
dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;
return (dst2>>16)|dst2;
}
void BmpIconDecode(u16 startx, u16 starty,const char *filename)
{
BMP_FILEHEADER *p;
u16 i,x,color,tmp ;
u16 read = 512;
u8 alpha;
u16 ICON_Height,ICON_Width;
f_read(&ICON_FIL,ICON_Buf,read,&RestBytes);/* 预读 512 字节 */
p = (BMP_FILEHEADER*)ICON_Buf; /* 获取 bmp 文件头 */
ICON_Height = p->biHeight; /* 获取 bmp 高度 */
ICON_Width = p->biWidth; /* 获取 bmp 宽度 */
f_lseek(&ICON_FIL,p->bfOffBits);/* 移动数据指针至 bmp真实数据存储区 */
f_read(&ICON_FIL,ICON_Buf,read,&RestBytes);//读取512字节
while(1)
{
for(i=0;i<read;i+=4)/* bmp 为32 bit, 一定可以被 4 整除 */
{
color = 0;/* 清除上次留下的颜色 */
tmp = ICON_Buf; color |= tmp>>3; /* 获取 B 通道 */
tmp = ICON_Buf[i+1]; tmp >>= 2; color |= tmp<<5; /* 获取 G 通道 */
tmp = ICON_Buf[i+2]; tmp >>= 3; color |= tmp<<11; /* 获取 R 通道 */
alpha = ICON_Buf[i+3]; /* 获取 Alpha 通道 */
if(alpha!=0xff) /* 如果是完全不透明则跳过读点过程 */
{
tmp = LCD_ReadPixel(startx+x,starty+ICON_Height);
color = alpha_blend565(tmp,color,alpha/8);
}
if(x<ICON_Width)/* 在图标宽度内则画点 */
LCD_WritePixel(startx+x,starty+ICON_Height,color);
else
{
ICON_Height--;
if(ICON_Height<=0)break;
x = 0;
}
x++;/* 横坐标加 1 */
}
if((RestBytes<read)&&(RestBytes!=0))read = RestBytes;
else if(RestBytes==0)break; /* 文件读取完毕 */
if(f_read(&ICON_FIL,ICON_Buf,read,&RestBytes)!=FR_OK)break;/* 读取 512 字节 */
}
}
void GUI_DrawICON(u16 startx,u16 starty,const TCHAR *filename)
{
RestBytes = 0; /* 文件剩余字节数置 0 */
if(f_open(&ICON_FIL,filename,FA_READ) == FR_OK)
BmpIconDecode(startx,starty,filename);
f_close(&ICON_FIL);/* 关闭打开的文件 */
}
核心部分在黄色区域。
如图,上效果:
原理: 32位 bmp 图片第四字节保存的是alpha通道,也就是搞透明的,这个值就是这个点透明度吧,与底色按照这个比例进行混合,看到的就是透明效果。
|