管理员
  
- 积分
- 165371
- 金钱
- 165371
- 注册时间
- 2010-12-1
- 在线时间
- 2110 小时
|
发表于 2012-9-28 10:12:29
|
显示全部楼层
//小尺寸的bmp解码,解码filename这个BMP文件
//filename:包含路径的文件名
//x,y,width,height:开窗大小
//acolor:附加的alphablend的颜色(这个仅对32位色bmp有效!!!)
//mode:模式(除了bit5,其他的均只对32位色bmp有效!!!)
// bit[7:6]:0,仅使用图片本身和底色alphablend;
// 1,仅图片和acolor进行alphablend,并且不适用附加的透明度;
// 2,底色,acolor,图片,一起进行alphablend;
// bit5:保留
// bit4~0:0~31,使用附加alphablend的透明程度
//返回值:0,成功;
// 其他,错误码.
u8 minibmp_decode(u8 *filename,u16 x,u16 y,u16 width,u16 height,u16 acolor,u8 mode)//尺寸小于240*320的bmp图片解码.
{
FIL* f_bmp;
u16 br;
u8 color_byte;
u16 tx,ty,color;
//tx,ty的实际坐标
u8 res;
u16 i,j;
u8 *databuf; //数据读取存放地址
u16 readlen=1024; //一次从SD卡读取的字节数长度,不能小于240*3!!!
u8 *bmpbuf; //数据解码地址
u8 biCompression=0; //记录压缩方式
u16 rowcnt; //一次读取的行数
u16 rowlen; //水平方向字节数
u16 rowpix=0; //水平方向像素数
u8 rowadd; //每行填充字节数
u16 tmp_color;
u8 alphabend=0xff; //代表透明色为0,完全不透明
u8 alphamode=mode>>6; //得到模式值,0/1/2
BITMAPINFO *pbmp; //临时指针
//得到窗体尺寸
picinfo.S_Height=height;
picinfo.S_Width=width;
#if BMP_USE_MALLOC == 1 //使用malloc
databuf=(u8*)mymalloc(SRAMIN,readlen); //开辟readlen字节的内存区域
if(databuf==NULL)return  IC_MEM_ERR; //内存申请失败.
f_bmp=(FIL *)mymalloc(SRAMIN,sizeof(FIL)); //开辟FIL字节的内存区域
if(f_bmp==NULL) //内存申请失败.
{
myfree(SRAMIN,databuf);
return  IC_MEM_ERR;
}
#else
databuf=bmpreadbuf;
f_bmp=&f_bfile;
#endif
res=f_open(f_bmp,(const TCHAR*)filename,FA_READ);//打开文件
if(res==0)//打开成功.
{
f_read(f_bmp,databuf,sizeof(BITMAPINFO),(UINT*)&br);//读出BITMAPINFO信息
pbmp=(BITMAPINFO*)databuf; //得到BMP的头部信息
color_byte=pbmp->bmiHeader.biBitCount/8; //彩色位 16/24/32
biCompression=pbmp->bmiHeader.biCompression;//压缩方式
picinfo.ImgHeight=pbmp->bmiHeader.biHeight; //得到图片高度
picinfo.ImgWidth=pbmp->bmiHeader.biWidth; //得到图片宽度
//水平像素必须是4的倍数!!
if((picinfo.ImgWidth*color_byte)%4)rowlen=((picinfo.ImgWidth*color_byte)/4+1)*4;
else rowlen=picinfo.ImgWidth*color_byte;
rowadd=rowlen-picinfo.ImgWidth*color_byte; //每行填充字节数
//开始解码BMP
color=0;//颜色清空
tx=0 ;
ty=picinfo.ImgHeight-1;
if(picinfo.ImgWidth<=picinfo.S_Width&&picinfo.ImgHeight<=picinfo.S_Height)
{
rowcnt=readlen/rowlen; //一次读取的行数
readlen=rowcnt*rowlen; //一次读取的字节数
rowpix=picinfo.ImgWidth; //水平像素数就是宽度
f_lseek(f_bmp,pbmp->bmfHeader.bfOffBits); //偏移到数据起始位置
while(1)
{
res=f_read(f_bmp,databuf,readlen,(UINT *)&br); //读出readlen个字节
bmpbuf=databuf; //数据首地址
if(br!=readlen)rowcnt=br/rowlen; //最后剩下的行数
if(color_byte==3) //24位BMP图片
{
for(j=0;j<rowcnt;j++) //每次读到的行数
{
for(i=0;i<rowpix;i++)//写一行像素
{
color=(*bmpbuf++)>>3; //B
color+=((u16)(*bmpbuf++)<<3)&0X07E0; //G
color+=(((u16)*bmpbuf++)<<8)&0XF800; //R
gui_phy.draw_point(x+tx,y+ty,color);//显示图片
tx++;
}
bmpbuf+=rowadd;//跳过填充区
tx=0;
ty--;
}
}else if(color_byte==2)//16位BMP图片
{
for(j=0;j<rowcnt;j++)//每次读到的行数
{
if(biCompression==BI_RGB)//RGB:5,5,5
{
for(i=0;i<rowpix;i++)
{
color=((u16)*bmpbuf&0X1F); //R
color+=(((u16)*bmpbuf++)&0XE0)<<1; //G
color+=((u16)*bmpbuf++)<<9; //R,G
gui_phy.draw_point(x+tx,y+ty,color);//显示图片
tx++;
}
}else //RGB 565
{
for(i=0;i<rowpix;i++)
{
color=*bmpbuf++; //G,B
color+=((u16)*bmpbuf++)<<8; //R,G
gui_phy.draw_point(x+tx,y+ty,color);//显示图片
tx++;
}
}
bmpbuf+=rowadd;//跳过填充区
tx=0;
ty--;
}
}else if(color_byte==4) //32位BMP图片
{
for(j=0;j<rowcnt;j++) //每次读到的行数
{
for(i=0;i<rowpix;i++)
{
color=(*bmpbuf++)>>3; //B
color+=((u16)(*bmpbuf++)<<3)&0X07E0; //G
color+=(((u16)*bmpbuf++)<<8)&0XF800; //R
alphabend=*bmpbuf++; //ALPHA通道
if(alphamode!=1) //需要读取底色
{
tmp_color=gui_phy.read_point(x+tx,y+ty);//读取颜色
if(alphamode==2)//需要附加的alphablend
{
tmp_color=alpha_blend(tmp_color,acolor,mode&0X1F); //与指定颜色进行blend
}
color=alpha_blend(tmp_color,color,alphabend/8); //和底色进行alphablend
}else tmp_color=alpha_blend(acolor,color,alphabend/8); //与指定颜色进行blend
gui_phy.draw_point(x+tx,y+ty,color);//显示图片
tx++;//x轴增加一个像素
}
bmpbuf+=rowadd;//跳过填充区
tx=0;
ty--;
}
}
if(br!=readlen||res)break;
}
}
f_close(f_bmp);//关闭文件
}else res=PIC_SIZE_ERR;//图片尺寸错误
#if BMP_USE_MALLOC == 1 //使用malloc
myfree(SRAMIN,databuf);
myfree(SRAMIN,f_bmp);
#endif
return res;
}
//快速ALPHA BLENDING算法.
//src:源颜色
//dst:目标颜色
//alpha:透明程度(0~32)
//返回值:混合后的颜色.
u16 gui_alpha_blend565(u16 src,u16 dst,u8 alpha)
{
u32 src2;
u32 dst2;
//Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB|
src2=((src<<16)|src)&0x07E0F81F;
dst2=((dst<<16)|dst)&0x07E0F81F;
//Perform blending R:G:B with alpha in range 0..32
//Note that the reason that alpha may not exceed 32 is that there are only
//5bits of space between each R:G:B value, any higher value will overflow
//into the next component and deliver ugly result.
dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;
return (dst2>>16)|dst2;
} |
|