一、常见图片格式:
1、BMP
2、JPEG(JPG)
3、GIF:动态
BMP:
1、全称BitMap,是Windows中的标准图像文件格式,后缀名为:“.bmp”。
2、采用位映射存储方式,除图像深度可选外,不做任何压缩。
3、图像深度可选:1、4、8、16、24、32bit。
4、BMP文件存储数据时,图像的扫描方式是按照从左到右、从上到小的顺序。
5、优缺点:图片占用空间大,但是没有任何失真,图片保存完好。
典型的BMP图像文件由四部分组成:
1、位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息;
2、位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3、调色板,这个部分可选,有些位图需要调色板,有些位图不需要调色板(比如:24位的BMP);
4、位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
JPG:
1、JPG是Joint Photographic Experts Group(联合图像专家小组)的缩写,是第一个国际图像压缩标准。后缀名为:“.JPEG”
2、JPEG图像压缩算法能够在提供良好的压缩性能的同时,具有比较好的重建质量,被广泛应用于图像处理领域。
3、采用有损压缩格式,能够将图像压缩在很小的存储空间。压缩技术先进,允许用不同的压缩比例对文件进行压缩,支持多种压缩级别。压缩比越大品质越低。
4、在图像质量和存储空间之间选择一个平衡点
GIF:
1、GIF(Graphics Interchange Format)的原义是“图像互换格式”,是CompusServe公司在1987年开发的图像文件格式。GIF文件的数据,是一种基于LZW算法的连续色调的无损压缩格式。其压缩率一般在50%左右,它不属于任何应用程序。
2、GIF主要分为两个版本:GIF89a和GIF87a
GIF 87a:是在1987年制定的版本;GIF 89a:是在1989年制定的版本;
二、实验代码
软件设计部分:PICTURE部分解码图片(包含四个文件:bmp.c gif.c piclib.c tjpgd.c)
bmp.c对应BMP格式图片的解码
gif.c对应GIF格式图片的解码
tjpgd.c对应JPEG(JPG)格式图片的解码
piclib.c为图片解码函数入口,里面有一个很重要的函数来提供图片解码的入口(ai_load_picfile函数)
根据不同的图片格式,进入相应的解码函数:
temp=f_typetell((u8*)filename);//得到文件类型
switch(temp)
{
case T_BMP:
res=stdbmp_decode(filename);//解码BMP
case T_JPG:
case T_JPEG:
res=jpg_decode(filename,fast);//解码JPG/JPEG
case T_GIF:
res=gif_decode(filename,x,y,width,height);//解码GIF
default:
res=PIC_FORMAT_ERR;//非图片格式
break;
}
piclib函数的详细作用:
1、函数内部含有公共函数,供GIF、JPEG、BMP函数解码图片的时候调用
2、函数内部含有一个区分图片格式的函数,用来区分图片格式从而使不同格式的图片进入不同的解码函数
3、图片解析后还需要显示在LCD上面,piclib函数中还包含将解码后的图片显示在LCD上面的函数。
piclib.h中的结构体函数:
typedef struct
{
u16(*read_point)(u16,u16); //u16 read_point(u16 x,u16 y)读点函数
void(*draw_point)(u16,u16,u16); //void draw_point(u16 x,u16 y,u16 color)画点函数
void(*fill)(u16,u16,u16,u16,u16); ///void fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)单色填充函数
void(*draw_hline)(u16,u16,u16,u16); //void draw_hline(u16 x0,u16 y0,u16 len,u16 color)画水平线函数
void(*fillcolor)(u16,u16,u16,u16,u16*); //void piclib_fill_color(u16 x,u16 y,u16 width,u16 height,u16 *color)颜色填充函数
}_pic_phy;
extern _pic_phy pic_phy;
typedef struct
{
u16 lcdwidth; //LCD的宽度
u16 lcdheight; //LCD的高度
u32 ImgWidth; //图像实际的宽度和高度
u32 ImgHeight;
u32 Div_Fac; //缩放系数(扩大了8192倍的)
u32 S_Height; //设定的宽度和高度
u32 S_Width;
u32 S_XOFF; //X、Y轴的偏移量
u32 S_YOFF;
u32 staticx; //当前显示的x和y轴的坐标
u32 staticy;
}_pic_info;
extern _pic_info picinfo;//图像信息
piclib.c中的函数:
1、piclib_init函数
//画图初始化,在画图之前必须先调用此函数
//指定画点/读点
void piclib_init(void)
{
pic_phy.read_point=LCD_ReadPoint; //读点函数实现
pic_phy.draw_point=LCD_Fast_DrawPoint; //画点函数实现
pic_phy.fill=LCD_Fill; //填充函数实现
pic_phy.draw_hline=piclib_draw_hline; //画线函数实现
pic_phy.fillcolor=piclib_fill_color; //颜色填充函数实现
picinfo.lcdwidth=lcddev.width; //得到LCD的宽度像素
picinfo.lcdheight=lcddev.height;//得到LCD的高度像素
picinfo.ImgWidth=0; //初始化宽度为0
picinfo.ImgHeight=0;//初始化高度为0
picinfo.Div_Fac=0; //初始化缩放系数为0
picinfo.S_Height=0; //初始化设定高度为0
picinfo.S_Width=0; //初始化设定宽度为0
picinfo.S_XOFF=0; //初始化X轴的偏移量为0
picinfo.S_YOFF=0; //初始化Y轴的偏移量为0
picinfo.staticx=0; //初始化当前显示到的x坐标为0
picinfo.staticy=0; //初始化当前显示到的y坐标为0
}
2、piclib_alpha_blend函数
//快速ALPHA BLENDING算法.
//src:源颜色
//dst:目标颜色
//alpha:透明程度(0~32)
//返回值:混合后的颜色.
u16 piclib_alpha_blend(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;
}
3、ai_draw_init函数
//初始化智能画点
//内部调用
void ai_draw_init(void)
{
float temp,temp1;
temp=(float)picinfo.S_Width/picinfo.ImgWidth;
temp1=(float)picinfo.S_Height/picinfo.ImgHeight;
if(temp<temp1)temp1=temp;//取较小的那个
if(temp1>1)temp1=1;
//使图片处于所给区域的中间
picinfo.S_XOFF+=(picinfo.S_Width-temp1*picinfo.ImgWidth)/2;
picinfo.S_YOFF+=(picinfo.S_Height-temp1*picinfo.ImgHeight)/2;
temp1*=8192;//扩大8192倍
picinfo.Div_Fac=temp1;
picinfo.staticx=0xffff;
picinfo.staticy=0xffff;//放到一个不可能的值上面
}
4、is_element_ok函数
//判断这个像素是否可以显示
//(x,y) :像素原始坐标
//chg :功能变量.
//返回值:0,不需要显示.1,需要显示
u8 is_element_ok(u16 x,u16 y,u8 chg)
{
if(x!=picinfo.staticx||y!=picinfo.staticy)
{
if(chg==1)
{
picinfo.staticx=x;
picinfo.staticy=y;
}
return 1;
}else return 0;
}
5、ai_load_picfile函数
//智能画图
//FileName:要显示的图片文件 BMP/JPG/JPEG/GIF
//x,y,width,height:坐标及显示区域尺寸
//fast:使能jpeg/jpg小图片(图片尺寸小于等于液晶分辨率)快速解码,0,不使能;1,使能.
//图片在开始和结束的坐标点范围内显示
u8 ai_load_picfile(const u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 fast)
{
u8 res;//返回值
u8 temp;
if((x+width)>picinfo.lcdwidth)return PIC_WINDOW_ERR; //x坐标超范围了.
if((y+height)>picinfo.lcdheight)return PIC_WINDOW_ERR; //y坐标超范围了.
//得到显示方框大小
if(width==0||height==0)return PIC_WINDOW_ERR; //窗口设定错误
picinfo.S_Height=height;
picinfo.S_Width=width;
//显示区域无效
if(picinfo.S_Height==0||picinfo.S_Width==0)
{
picinfo.S_Height=lcddev.height;
picinfo.S_Width=lcddev.width;
return FALSE;
}
if(pic_phy.fillcolor==NULL)fast=0;//颜色填充函数未实现,不能快速显示
//显示的开始坐标点
picinfo.S_YOFF=y;
picinfo.S_XOFF=x;
//文件名传递
temp=f_typetell((u8*)filename); //得到文件的类型
switch(temp)
{
case T_BMP:
res=stdbmp_decode(filename); //解码bmp
break;
case T_JPG:
case T_JPEG:
res=jpg_decode(filename,fast); //解码JPG/JPEG
break;
case T_GIF:
res=gif_decode(filename,x,y,width,height); //解码gif
break;
default:
res=PIC_FORMAT_ERR; //非图片格式!!!
break;
}
return res;
}