饿得快是什么原因| 二十七岁属什么生肖| 白衬衫配什么裤子好看| 空调制冷效果差是什么原因| 女人脾虚吃什么最好| 8月27日什么星座| 什么样的蝴蝶| 今天是什么日子 农历| 浑身酸疼是什么原因| 手抖头抖是什么病| 7月9日是什么星座| 推是什么意思| 胃部间质瘤是什么性质的瘤| 三月份是什么星座的| 小腿肚抽筋是什么原因| 手上长小水泡很痒是什么原因| 吃醋是什么意思| 喜欢紫色代表什么| ao是什么| 实时播报什么意思| 匪夷所思什么意思| 冷宫是什么意思| 西洋参可以和什么一起泡水喝| 结婚55周年是什么婚| 什么人不能念阿弥陀佛| 经常吃秋葵有什么好处| 车间管理人员工资计入什么科目| 9月12日是什么星座| 画龙点睛指什么生肖| 经期头疼吃什么药效果最好| 荭是什么意思| 口臭是什么原因造成的| 中药吃多了对人体有什么伤害| 为什么喝水血糖也会高| 孕晚期感冒可以吃什么药| 尿潴留是什么症状| 后中长是什么意思| 减震器坏了有什么症状| 身上痒什么原因| 不走寻常路是什么品牌| 梦见杀鸡见血什么征兆| 什么是有限公司| 8月23日是什么星座| 肚子痛去药店买什么药| 香港身份证有什么好处| 含羞草长什么样| 梦见盖房子是什么预兆| 72岁属什么| 猪八戒叫什么名字| 我们为什么会笑| 车船税是什么意思每年都交吗| 手肿是什么病的前兆| 身上皮肤痒是什么原因| 小孩便秘吃什么食物好| 兆后面是什么单位| 亦或是什么意思| 肾结石要注意什么| 李荣浩什么学历| 颠鸾倒凤什么意思| 针灸要注意什么| 不耐受和过敏有什么区别| 猪身上红疙瘩用什么药| 坏血病的症状是什么| 肺部有问题一般会出现什么症状| 菊花配枸杞什么功效| 喜筵和喜宴是什么意思| 早上十点是什么时辰| 为什么会得艾滋病| gjb2基因杂合突变是什么意思| 划船是什么意思| 太阳什么的什么的| 祖马龙香水什么档次| 寒冷性荨麻疹是什么原因引起的| 眼睛的晶体是什么| 吃饭咬到舌头什么原因| 胃有灼热感是什么原因| 什么口红好| 低血糖吃什么最快缓解| 智商120是什么水平| 什么是cnc| 儿保做些什么检查项目| 爬山有什么好处| 足踝外科主要看什么| 难于上青天是什么意思| 眉中间有竖纹代表什么| 耳鸣是什么原因引起的| 征兆是什么意思| 曹仁和曹操什么关系| 数不胜数的胜是什么意思| mz是什么意思| 立春是什么生肖| 事无巨细什么意思| 心电图诊断窦性心律什么意思| 出差什么意思| 处女座男和什么座最配对| 切莫是什么意思| 11月29日什么星座| 秦始皇的原名叫什么| 吃软饭是什么意思| 早孕三项检查什么| 强直性脊柱炎是什么| 来月经可以吃什么水果好| green是什么颜色| 十月二十七是什么星座| 属狗是什么命| 海参头数是什么意思| 劈腿什么意思| 肝异常一般是什么情况| 宝石蓝配什么颜色好看| 湖北人喜欢吃什么菜| 什么网名好听又有内涵| 贵州有什么好吃的| 现在最火的歌是什么| 乳头变大是什么原因| 什么是红斑狼疮| 骨折吃什么水果好| ysl属于什么档次| 腰疼做什么检查| bp是什么意思| 男子精少吃什么药可以生精| 燕麦长什么样子图片| 谷丙转氨酶偏高吃什么药| 刺五加配什么药治失眠| 昱这个字念什么| 老公的弟弟叫什么| 腹水是什么病| 董事总经理是什么职位| 什么枕头好| 左上腹是什么器官| 创面是什么意思| 脾胃不好吃什么调理| 什么是暗网| 口坐读什么| 枭神夺食会发生什么| 非萎缩性胃窦炎是什么意思| 健身吃什么水果| 强劲的动物是什么生肖| 杠杠滴是什么意思| 人生格言是什么| 胎儿没有胎心是什么原因| 什么是巧克力囊肿| 双氢克尿噻又叫什么| 接吻要注意什么| 送荷花的寓意是什么| 步步高升是什么意思| 罗马棉是什么面料| 狮子住在什么地方| 五月十六日是什么星座| 新生儿什么时候吃ad| 黄帝姓什么| 养鱼为什么养单不养双| 打了麻药有什么副作用| 眼睛模糊流泪用什么药| 新生儿喝什么奶粉好| 安徽什么阳| 肝脾肿大是什么症状| 蛇为什么有毒| 白蛋白是什么意思| 唇周围长痘痘是什么原因| 红薯什么季节成熟| 耕田是什么意思| 观音坐莲是什么姿势| 小心眼什么意思| 尿道口红肿用什么药| 跳蚤为什么只咬一个人| 三七粉有什么作用| 1984年属什么生肖| abo溶血是什么意思| 男生第一次是什么感觉| 为什么姨妈会推迟| 拔牙前需要做什么检查| 肾积水有什么症状表现| 黑今读什么| 木耳和什么不能一起吃| 义齿是什么| iu什么意思| 化学性肝损伤是指什么| 酸菜鱼放什么配菜好吃| 阴道润滑剂什么牌子好| 反物质是什么东西| 中指戴戒指什么意思| 苍耳是什么东西| 备孕喝苏打水什么作用| 梦见好多衣服是什么意思| 动脉抽血是做什么检查| 空调变频和定频有什么区别| i.t品牌什么档次| 月经推迟挂什么科| 什么眼霜比较好用| 欧巴是什么意思| 淘宝什么时候成立的| dw手表属于什么档次| 最高位是什么位| 西柚不能和什么一起吃| 女生右手中指戴戒指什么意思| 龘读什么| 发烧38度吃什么药| 女性阴道长什么样| 乙肝五项135阳性是什么意思| 67岁属什么生肖| 双氢克尿噻又叫什么| 昭是什么意思| 看书有什么好处| 树根有什么作用| 6月8号是什么星座| 辩解是什么意思| 间质性改变是什么意思| 外阴溃烂用什么药| 喝什么解酒最快最有效| 心脏彩超挂什么科| 木字旁的字与什么有关| 甲醛什么味| 11月27是什么星座| 食色性也什么意思| 疤痕子宫什么意思| 为什么延迟退休| 五花肉炖什么好吃| 淋漓不尽是什么意思| 体检挂什么科| 闺房是什么意思| 梗塞灶是什么意思| 89是什么意思| 氯雷他定片什么时候吃| 尿酸高吃什么能降| 一个日一个安念什么字| 64年出生属什么| 乌龟代表什么数字| 咽喉疱疹是什么症状| 什么树最值钱| 阴历7月22是什么日子| 羲字五行属什么| 正觉是什么意思| AFP医学上是什么意思| 百里挑一是什么生肖| 茶话会是什么意思| 日语莫西莫西什么意思| 炖鸡块放什么调料| 小儿疳积是什么症状| 1964年属什么| 做馒头用什么面粉| 推手是什么意思| 爱马仕是什么意思| 晚8点是什么时辰| 打嗝吃什么药| 什么是地包天牙齿图片| 老是发烧是什么原因| 煮方便面什么时候放鸡蛋| 拔罐后要注意什么| 闰六月是什么意思| 付之东流是什么意思| 莞式服务是什么| 角色扮演是什么意思| 牙龈出血用什么药| 血常规是什么意思| 他达拉非是什么药| 水煮鱼用什么鱼做好吃| 胃胀反酸吃什么药效果好| 琪五行属性是什么| 吃什么尿酸降得快| 早睡有什么好处| 大土土什么字| 公众号是什么意思| 来事头疼什么原因| 胃食管反流吃什么中成药| 百度
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

丝瓜可以炒什么

DS小龙哥-嵌入式技术 ? 来源:DS小龙哥-嵌入式技术 ? 作者:DS小龙哥-嵌入式技 ? 2025-08-05 21:14 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、项目介绍

项目是基于STM32设计的数码相册,能够通过LCD显示屏解码显示主流的图片,支持bmp、jpg、gif等格式。用户可以通过按键或者触摸屏来切换图片,同时还可以旋转显示,并能够自适应居中显示,小尺寸图片居中显示,大尺寸图片自动缩小显示(超出屏幕范围)。图片从SD卡中获取。

image-20230618135436038

二、设计思路

2.1 硬件设计

本项目所需的主要硬件:

  • STM32F103ZET6
  • LCD屏幕
  • SD卡模块
  • 按键和触摸屏

2.2 软件设计

(1)解码图片

在STM32芯片中,解码图片需要将读取到的数据存入图形缓冲区中,以便进行图画显示。常用的解码算法有JPEG解码和BMP解码。

(2)图片显示

为了更好的实现图片旋转和缩放功能,在显示图片时需对其进行矩阵运算。通过左右翻转和上下翻转,可实现图片的旋转功能。通过计算图片与显示屏幕之间的比例关系并进行缩放,实现自适应居中和图片的缩放功能。

(3)SD卡

SD卡模块可通过SPI接口与STM32芯片进行通信,读取SD卡中的图片数据,实现对图片的加载和显示。

(4)按键和触摸屏

在使用过程中,用户可以通过按键和触摸屏对图片进行切换、旋转和缩放等操作。通过设置中断处理函数,响应用户的操作并及时更新显示屏幕上的图片。

2.3 图片播放流程图

image-20230618135212377

2.4 显示效果

image-20230618135401101

image-20230618135409530

image-20230618135417655

image-20230618135426430

image-20230618135436038

三、代码设计

3.1 主函数

#include "stm32f10x.h"
 #include "led.h"
 #include "delay.h"
 #include "key.h"
 #include "usart.h"
 #include < string.h >
 #include < stdio.h >
 #include "sd.h" //SD卡
 #include "ff.h" //文件系统
 #include "bmp.h" //文件系统
 #include "iic.h"
 #include "at24c02.h"
 #include "xpt2046.h"
 #include "lcd.h"
 ?
 ?
 FATFS fs;  // 用户定义的文件系统结构体
 int main()
 {
     DIR  dir_dp;
     FILINFO file_info;
     u32 sd_size;    //存放SD卡返回的容量
     BeepInit();       //蜂鸣器初始化
     LedInit();      //LED灯初始化 
     UsartInit(USART1,72,115200);
     KeyInit();     //按键初始化
     IICInit();
     LcdInit();
     TOUCH_Init(); 
     //TOUCH_ADJUST(); //触摸屏校准
     
     printf("串口工作正常!\\r\\n");
     if(SDCardDeviceInit()) 
     {
        printf("SD卡初始化失败!\\r\\n");
     }
     
     sd_size=GetSDCardSectorCount(); //检测SD卡大小,返回值右移11位得到以M为单位的容量
     printf("SD卡Sizeof:%d\\r\\n",sd_size >>11);
     
   f_mount(&fs,"0:",1);  // 注册文件系统工作区,驱动器号 0,初始化后其他函数可使用里面的参数
     LcdClear(0xFFFF);
     
     //f_mkdir("0:/目录创建测试!"); //测试OK
     //f_unlink("0:/123"); //删除目录,注意只能删除空目录
     //f_unlink("0:/1.bmp");//删除文件
     //printf("%d\\r\\n",Show_BMP("1.bmp"));
     
     if(f_opendir(&dir_dp,"0:/bmp")!=FR_OK)printf("目录打开失败!\\r\\n");
     
     //循环读取目录
     while(f_readdir(&dir_dp,&file_info)==FR_OK)
     {
             if(file_info.fname[0]==0)break;    //判断目录跳出条件,表示目录已经读取完毕
             if(strstr(file_info.fname,".bmp")) //过滤目录
             {
                     printf("文件名称: %s,文件大小: %ld 字节\\r\\n",file_info.fname,file_info.fsize);
             }else   printf("文件名称: %s,文件大小: %ld 字节\\r\\n",file_info.fname,file_info.fsize);
     }
     if(f_closedir(&dir_dp)!=FR_OK)printf("目录关闭失败!\\r\\n");
     while(1)
     {   
          LED1=!LED1;
          DelayMs(100);
     }
 }
 ?

3.2 BMP图片解码

#include "bmp.h"
 unsigned short RGB888ToRGB565(unsigned int n888Color)  
 {  
     unsigned short n565Color = 0;  
   
     // 获取RGB单色,并截取高位  
     unsigned char cRed   = (n888Color & RGB888_RED)   > > 19;  
     unsigned char cGreen = (n888Color & RGB888_GREEN) > > 10;  
     unsigned char cBlue  = (n888Color & RGB888_BLUE)  > > 3;  
   
     // 连接  
     n565Color = (cRed < < 11) + (cGreen < < 5) + (cBlue < < 0);  
     return n565Color;  
 }  
 ?
 unsigned int RGB565ToRGB888(unsigned short n565Color)  
 {  
     unsigned int n888Color = 0;  
   
     // 获取RGB单色,并填充低位  
     unsigned char cRed   = (n565Color & RGB565_RED)    > > 8;  
     unsigned char cGreen = (n565Color & RGB565_GREEN)  > > 3;  
     unsigned char cBlue  = (n565Color & RGB565_BLUE)   < < 3;  
   
     // 连接  
     n888Color = (cRed < < 16) + (cGreen < < 8) + (cBlue < < 0);  
     return n888Color;  
 }  
 ?
 ?
 ?
 /*
 函数功能:实现截图功能
 参    数:
                 char filename:文件名称
 返 回 值:0表示成功,1表示失败
 */
 u8 C_BMP(const char *filename,u32 Width,u32 Height)
 {
     FIL  file; // 用户定义的文件系统结构体
     u8   res;  // 保存文件操作的返回值
     BITMAPFILEHEADER BmpHead; //保存图片文件头的信息
   BITMAPINFOHEADER BmpInfo; //图片参数信息
     char *p;
     u32 cnt,c_32;
     int x,y;
     u16 c_16; //存放16位的颜色
     
     /*1. 创建一张BMP图片*/
     res = f_open(&file,filename, FA_OPEN_ALWAYS | FA_WRITE);
     if(res!=0)return 1;
     
     /*2. 创建BMP的图片头参数*/
     memset(&BmpHead,0,sizeof(BITMAPFILEHEADER)); //将指定空间赋值为指定的值
     p=(char*)&BmpHead.bfType; //填充BMP图片的类型
     *p='B';
     *(p+1)='M';
 ?
     //BmpHead.bfType=0x4d42;//'B''M'   //0x4d42
     BmpHead.bfSize=Width*Height*3+54;  //图片的总大小
     BmpHead.bfOffBits=54;              //图片数据的偏移量
   res =f_write(&file,&BmpHead,sizeof(BITMAPFILEHEADER),&cnt);
     if(res!=0)return 1;
     
     /*3. 创建BMP图片的参数*/
     memset(&BmpInfo,0,sizeof(BITMAPINFOHEADER));
     BmpInfo.biSize=sizeof(BITMAPINFOHEADER); //当前结构体大小
     BmpInfo.biWidth=Width;
     BmpInfo.biHeight=Height;
     BmpInfo.biPlanes=1;
     BmpInfo.biBitCount=24;
     res =f_write(&file,&BmpInfo,sizeof(BITMAPINFOHEADER),&cnt);
     if(res!=0)return 1;
         
     /*4. 读取LCD屏的颜色数据,用于创建BMP图片*/
     for(y=Height-1;y >=0;y--)
     {
           for(x=0;x< Width;x++)
           {
                 c_16=LcdReadPoint(x,y); //读取LCD屏上一个点的颜色
                   c_32=RGB565ToRGB888(c_16); //颜色的转换
                   res =f_write(&file,&c_32,3,&cnt);
                   if(res!=0)return 1;
             }
     }
     
     /*5. 关闭文件*/
     f_close(&file);
 }
 ?
 ?
 /*
 函数功能:BMP图片显示功能
 参    数:
                 char filename:文件名称
 返 回 值:0表示成功,1表示失败
 */
 u8 Show_BMP(const char *filename)
 {
     FIL  file; // 用户定义的文件系统结构体
     u8   res;  // 保存文件操作的返回值
     BITMAPFILEHEADER BmpHead; //保存图片文件头的信息
   BITMAPINFOHEADER BmpInfo; //图片参数信息
     char *p;
     u32 cnt,c_24;
     int x,y;
     u16 c_16; //存放16位的颜色
     
     /*1. 打开一张BMP图片*/
     res = f_open(&file,filename,FA_READ);
     if(res!=0)return 1;
     
     /*2. 读取BMP的图片头参数*/
   res =f_read(&file,&BmpHead,sizeof(BITMAPFILEHEADER),&cnt);
     if(res!=0)return 1;
     
     /*3. 读取BMP图片的参数*/
     res =f_read(&file,&BmpInfo,sizeof(BITMAPINFOHEADER),&cnt);
     if(res!=0)return 1;
     
     /*4.显示BMP图片*/
     f_lseek(&file,BmpHead.bfOffBits); //移动到RGB数据的存放位置
     
     //后期的优化:读取一行的数据,再显示一行。
    for(y=0;y< BmpInfo.biHeight;y++)
      {
             for(x=0;x< BmpInfo.biWidth;x++)
          {
                 res =f_read(&file,&c_24,3,&cnt);
                     if(res!=0)return 1;
                 c_16=RGB888ToRGB565(c_24); //转换颜色
                 LcdDrawPoint(x,y,c_16);
          }
      }
     /*5. 关闭文件*/
     f_close(&file);
 }
 ?
 ?

3.3 jpeg图片解码

#include "piclib.h"
 #include "nt35310_lcd.h"
 _pic_info picinfo;      //图片信息
 _pic_phy pic_phy;         //图片显示物理接口    
 ?
 /*
 函数功能: 划横线函数,需要自己实现
 */
 void Picture_DrawLine(u16 x0,u16 y0,u16 len,u16 color)
 {
     NT35310_Fill(x0,y0,x0+len-1,y0,color);  
 }
 ?
 /*
 函数功能: 矩形填充颜色
 函数参数:
         x,y:起始坐标
         width,height:宽度和高度。
         color:颜色数组
 */
 void Picture_FillColor(u16 x,u16 y,u16 width,u16 height,u16 *color)
 {  
     NT35310_DrawRectangle(x,y,x+width-1,y+height-1,*color); 
 }
 ?
 /*
 函数功能: 画图初始化,在画图之前,必须先调用此函数
 函数参数: 指定画点/读点
 */
 void Picture_DisplayInit(void)
 {
     pic_phy.draw_point=NT35310_DrawPoint;    //画点函数实现
     pic_phy.fill=NT35310_Fill;                       //填充函数实现,仅GIF需要
     pic_phy.draw_hline=Picture_DrawLine;     //画线函数实现,仅GIF需要
     pic_phy.fillcolor=Picture_FillColor;     //颜色填充函数实现,仅TJPGD需要 
     picinfo.lcdwidth=Lcd_Width;                          //得到LCD的宽度像素
     picinfo.lcdheight=Lcd_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
 }
 ?
 ?
 /*
 函数功能: 初始化智能画点
 说明: 内部调用
 */
 void Picture_PointInit(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;//放到一个不可能的值上面                                                        
 }  
 ?
 /*
 函数功能: 判断这个像素是否可以显示
 函数参数:
             (x,y) :像素原始坐标
             chg   :功能变量.
 返回值:0,不需要显示.1,需要显示
 */
 u8 Picture_is_Pixel(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;
 }
 ?
 extern u8 jpg_decode(const u8 *filename);
 ?
 /*
 函数功能: 绘制图片
 函数参数:
                 FileName:要显示的图片文件  BMP/JPG/JPEG/GIF
                 x,y,width,height:坐标及显示区域尺寸
                 fast:使能jpeg/jpg小图片(图片尺寸小于等于液晶分辨率)快速解码,0,不使能;1,使能.
                 函数说明: 图片在开始和结束的坐标点范围内显示
 */
 u8 Picture_DisplayJPG(const u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 fast)
 {   
     u8  res;//返回值
     
     //显示的图片高度、宽度
     picinfo.S_Height=height;
     picinfo.S_Width=width;
 ?
     //显示的开始坐标点
     picinfo.S_YOFF=y;
     picinfo.S_XOFF=x;
     
     //解码JPG/JPEG         
   res=jpg_decode(filename);             //解码JPG/JPEG                                                   
     return res;
 }
 ?

3.4 gif图片解码

#include "piclib.h"
 #include < stm32f10x.h >
 #include "gif.h"     
 #include "ff.h" 
 #include "delay.h"      
 #include < string.h >
 ?
 const u16 _aMaskTbl[16] =
 {
     0x0000, 0x0001, 0x0003, 0x0007,
     0x000f, 0x001f, 0x003f, 0x007f,
     0x00ff, 0x01ff, 0x03ff, 0x07ff,
     0x0fff, 0x1fff, 0x3fff, 0x7fff,
 };    
 const u8 _aInterlaceOffset[]={8,8,4,2};
 const u8 _aInterlaceYPos  []={0,4,2,1};
  
 u8 gifdecoding=0;//标记GIF正在解码.
 ?
 //检测GIF头
 //返回值:0,是GIF89a/87a;非零,非GIF89a/87a
 u8 gif_check_head(FIL *file)
 {
     u8 gifversion[6];
     u32 readed;
     u8 res;
     res=f_read(file,gifversion,6,(UINT*)&readed);
     if(res)return 1;       
     if((gifversion[0]!='G')||(gifversion[1]!='I')||(gifversion[2]!='F')||
     (gifversion[3]!='8')||((gifversion[4]!='7')&&(gifversion[4]!='9'))||
     (gifversion[5]!='a'))return 2;
     else return 0;  
 }
 ?
 //将RGB888转为RGB565
 //ctb:RGB888颜色数组首地址.
 //返回值:RGB565颜色.
 u16 gif_getrgb565(u8 *ctb) 
 {
     u16 r,g,b;
     r=(ctb[0] >>3)&0X1F;
     g=(ctb[1] >>2)&0X3F;
     b=(ctb[2] >>3)&0X1F;
     return b+(g< 5)+(r< 11);
 }
 ?
 //读取颜色表
 //file:文件;
 //gif:gif信息;
 //num:tbl大小.
 //返回值:0,OK;其他,失败;
 u8 gif_readcolortbl(FIL *file,gif89a * gif,u16 num)
 {
     u8 rgb[3];
     u16 t;
     u8 res;
     u32 readed;
     for(t=0;t< num;t++)
     {
         res=f_read(file,rgb,3,(UINT*)&readed);
         if(res)return 1;//读错误
         gif- >colortbl[t]=gif_getrgb565(rgb);
     }
     return 0;
 } 
 //得到逻辑屏幕描述,图像尺寸等
 //file:文件;
 //gif:gif信息;
 //返回值:0,OK;其他,失败;
 u8 gif_getinfo(FIL *file,gif89a * gif)
 {
     u32 readed;  
     u8 res;   
     res=f_read(file,(u8*)&gif- >gifLSD,7,(UINT*)&readed);
     if(res)return 1;
     if(gif- >gifLSD.flag&0x80)//存在全局颜色表
     {
         gif- >numcolors=2< gifLSD.flag&0x07);//得到颜色表大小
         if(gif_readcolortbl(file,gif,gif- >numcolors))return 1;//读错误 
     }      
     return 0;
 }
 //保存全局颜色表    
 //gif:gif信息;
 void gif_savegctbl(gif89a* gif)
 {
     u16 i=0;
     for(i=0;i< 256;i++)gif- >bkpcolortbl[i]=gif- >colortbl[i];//保存全局颜色.
 }
 //恢复全局颜色表    
 //gif:gif信息;
 void gif_recovergctbl(gif89a* gif)
 {
     u16 i=0;
     for(i=0;i< 256;i++)gif- >colortbl[i]=gif- >bkpcolortbl[i];//恢复全局颜色.
 }
 ?
 //初始化LZW相关参数       
 //gif:gif信息;
 //codesize:lzw码长度
 void gif_initlzw(gif89a* gif,u8 codesize) 
 {
     memset((u8 *)gif- >lzw, 0, sizeof(LZW_INFO));
     gif- >lzw- >SetCodeSize  = codesize;
     gif- >lzw- >CodeSize     = codesize + 1;
     gif- >lzw- >ClearCode    = (1 < < codesize);
     gif- >lzw- >EndCode      = (1 < < codesize) + 1;
     gif- >lzw- >MaxCode      = (1 < < codesize) + 2;
     gif- >lzw- >MaxCodeSize  = (1 < < codesize) < < 1;
     gif- >lzw- >ReturnClear  = 1;
     gif- >lzw- >LastByte     = 2;
     gif- >lzw- >sp           = gif- >lzw- >aDecompBuffer;
 }
 ?
 //读取一个数据块
 //gfile:gif文件;
 //buf:数据缓存区
 //maxnum:最大读写数据限制
 u16 gif_getdatablock(FIL *gfile,u8 *buf,u16 maxnum) 
 {
     u8 cnt;
     u32 readed;
     u32 fpos;
     f_read(gfile,&cnt,1,(UINT*)&readed);//得到LZW长度            
     if(cnt) 
     {
         if (buf)//需要读取 
         {
             if(cnt >maxnum)
             {
                 fpos=f_tell(gfile);
                 f_lseek(gfile,fpos+cnt);//跳过
                 return cnt;//直接不读
             }
             f_read(gfile,buf,cnt,(UINT*)&readed);//得到LZW长度  
         }else   //直接跳过
         {
             fpos=f_tell(gfile);
             f_lseek(gfile,fpos+cnt);//跳过
         }
     }
     return cnt;
 }
 ?
 //ReadExtension      
 //Purpose:
 //Reads an extension block. One extension block can consist of several data blocks.
 //If an unknown extension block occures, the routine failes.
 //返回值:0,成功;
 //       其他,失败
 u8 gif_readextension(FIL *gfile,gif89a* gif, int *pTransIndex,u8 *pDisposal)
 {
     u8 temp;
     u32 readed;  
     u8 buf[4];  
     f_read(gfile,&temp,1,(UINT*)&readed);//得到长度      
     switch(temp)
     {
         case GIF_PLAINTEXT:
         case GIF_APPLICATION:
         case GIF_COMMENT:
             while(gif_getdatablock(gfile,0,256) >0);         //获取数据块
             return 0;
         case GIF_GRAPHICCTL://图形控制扩展块
             if(gif_getdatablock(gfile,buf,4)!=4)return 1;   //图形控制扩展块的长度必须为4 
             gif- >delay=(buf[2]< 8)|buf[1];                  //得到延时 
             *pDisposal=(buf[0] >>2)&0x7;                     //得到处理方法
             if((buf[0]&0x1)!=0)*pTransIndex=buf[3];         //透明色表 
             f_read(gfile,&temp,1,(UINT*)&readed);           //得到LZW长度   
             if(temp!=0)return 1;                            //读取数据块结束符错误.
             return 0;
     }
     return 1;//错误的数据
 }
 ?
 //从LZW缓存中得到下一个LZW码,每个码包含12位
 //返回值:< 0,错误.
 //       其他,正常.
 int gif_getnextcode(FIL *gfile,gif89a* gif) 
 {
     int i,j,End;
     long Result;
     if(gif- >lzw- >ReturnClear)
     {
         //The first code should be a clearcode.
         gif- >lzw- >ReturnClear=0;
         return gif- >lzw- >ClearCode;
     }
     End=gif- >lzw- >CurBit+gif- >lzw- >CodeSize;
     if(End >=gif- >lzw- >LastBit)
     {
         int Count;
         if(gif- >lzw- >GetDone)return-1;//Error 
         gif- >lzw- >aBuffer[0]=gif- >lzw- >aBuffer[gif- >lzw- >LastByte-2];
         gif- >lzw- >aBuffer[1]=gif- >lzw- >aBuffer[gif- >lzw- >LastByte-1];
         if((Count=gif_getdatablock(gfile,&gif- >lzw- >aBuffer[2],300))==0)gif- >lzw- >GetDone=1;
         if(Count< 0)return -1;//Error 
         gif- >lzw- >LastByte=2+Count;
         gif- >lzw- >CurBit=(gif- >lzw- >CurBit-gif- >lzw- >LastBit)+16;
         gif- >lzw- >LastBit=(2+Count)*8;
         End=gif- >lzw- >CurBit+gif- >lzw- >CodeSize;
     }
     j=End >>3;
     i=gif- >lzw- >CurBit >>3;
     if(i==j)Result=(long)gif- >lzw- >aBuffer[i];
     else if(i+1==j)Result=(long)gif- >lzw- >aBuffer[i]|((long)gif- >lzw- >aBuffer[i+1]< 8);
     else Result=(long)gif- >lzw- >aBuffer[i]|((long)gif- >lzw- >aBuffer[i+1]< 8)|((long)gif- >lzw- >aBuffer[i+2]< 16);
     Result=(Result >>(gif- >lzw- >CurBit&0x7))&_aMaskTbl[gif- >lzw- >CodeSize];
     gif- >lzw- >CurBit+=gif- >lzw- >CodeSize;
     return(int)Result;
 }
 ?
 ?
 //得到LZW的下一个码
 //返回值:< 0,错误(-1,不成功;-2,读到结束符了)
 //       >=0,OK.(LZW的第一个码)
 int gif_getnextbyte(FIL *gfile,gif89a* gif) 
 {
     int i,Code,Incode;
     while((Code=gif_getnextcode(gfile,gif)) >=0)
     {
         if(Code==gif- >lzw- >ClearCode)
         {
             //Corrupt GIFs can make this happen  
             if(gif- >lzw- >ClearCode >=(1<
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • lcd
    lcd
    +关注

    关注

    34

    文章

    4522

    浏览量

    171920
  • STM32
    +关注

    关注

    2295

    文章

    11035

    浏览量

    366003
  • 编解码
    +关注

    关注

    1

    文章

    146

    浏览量

    20164
  • STM32F103ZET6
    +关注

    关注

    9

    文章

    67

    浏览量

    21781
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STM32应用案例 基于STM32F103ZE开发的数码相册

    1.硬件平台 CPU:STM32F103ZE 屏幕:3.5寸TFTLCD屏 触控:电阻式触摸屏xpt2046 SD卡、外扩Sram
    的头像 发表于 06-02 09:09 ?8026次阅读
    <b class='flag-5'>STM32</b>应用案例 基于<b class='flag-5'>STM32</b>F103ZE开发的<b class='flag-5'>数码相册</b>

    Linux驱动开发_数码相册项目、360WIFI驱动移植介绍

    这篇文章介绍两个知识点: 数码相册要求介绍、贴出案例代码、介绍360随身WIFI的驱动移植注意事项。
    的头像 发表于 09-17 15:51 ?2351次阅读
    Linux驱动开发_<b class='flag-5'>数码相册</b>项目、360WIFI驱动移植介绍

    基于STM32L431低功耗芯片制作的电子墨水屏相册

    为解决传统相册及桌面照片摆台只能展示固定图片这一问题,本次设计的基于STM32L431RCT6低功耗芯片制作的电子墨水屏相册,可以显示电子图片
    的头像 发表于 11-08 11:39 ?4626次阅读
    基于<b class='flag-5'>STM32</b>L431低功耗芯片制作的电子墨水屏<b class='flag-5'>相册</b>

    基于STM32F103RC的电子相册(原理图、PCB源文件、程序源码及制作)

    基于STM32F103RC的电子相册(原理图、PCB源文件、程序源码及制作)推荐下载!
    发表于 05-28 21:58

    高清晰影楼相册制作系统 绿色特别版

    高清晰影楼相册制作系统 2008 V3.5 绿色特别版软件语言: 简体中文 运行环境: Win9X/2000/XP/2003/Vista/ 软件简介: 高清晰影楼相册制作系统是一款专业的影楼相册制作
    发表于 03-02 11:44

    单片机控制的DIY数码相册显示

    本帖最后由 eehome 于 2013-1-5 09:52 编辑 单片机控制的DIY数码相册显示
    发表于 08-15 23:05

    【Aworks申请】基于ARM9的电子相册

    申请理由:本人是一名嵌入式开发从业者,对嵌入式开发有着浓厚的兴趣,本套开发板具有极其丰富的学习资源,非常希望能够获得此次机会,对ARM9嵌入式系统开发有很大的帮助。项目描述:通过开发板的学习之后,制作一个简单的可以控制的电子数码相册,简单,美观。为今后的工作学习打下良好的基础。
    发表于 07-15 08:58

    相册

    一幅画面,于是您的所有喜爱的图片都到这里了。但这也是有点限制的,因为存储卡的空间毕竟是有限的,而且我们有很多图片常常就是放在网上的相册里的,如果可以把网上相册里的图片直接放到我桌上的数码相册上就好
    发表于 02-22 10:27

    阿甘老师DREAMER开发板零基础51单片机AVR单片机视频教程全集

    了TFT彩屏(ILI9325驱动),SD卡(SC+HC)的视频教学而且还有数码相册的联合实际应用,还算是比较不错,分享到这里有需要的朋友下载吧。
    发表于 03-23 08:19

    stm32控制4位数码管_stm32控制共阴数码

    本文主要介绍了stm32控制4位共阳数码管输出计数程序设计和stm32控制共阴数码管程序设计。首先我们来了解一下数码管的原理图。用
    发表于 01-16 17:07 ?7.7w次阅读
    用<b class='flag-5'>stm32</b>控制4位<b class='flag-5'>数码</b>管_<b class='flag-5'>stm32</b>控制共阴<b class='flag-5'>数码</b>管

    小米电视5共享相册功能上线 可通过MIUI共享相册

    11月25日消息,小米电视部总经理李肖爽今天宣布,小米电视5共享相册功能已上线,没有收到应用更新的用户可以在电视应用商店里搜索相册应用,手动更新,电视相册App版本号1.1.0,手机相册
    的头像 发表于 11-26 08:47 ?3972次阅读

    Linux小项目-数码相册设计

    这是基于Linux系统开发板设计一个小项目-数码相册,在LCD屏上可以显示完成常见的图片显示,翻页、旋转、缩放等功能。
    的头像 发表于 08-14 09:15 ?2408次阅读

    FPGA增强了数码相册功能

    随着我们不断以像素为单位捕获生活快照,我们正在积累一系列软件工具和设备来查看,编辑,存储,个性化和共享我们的数码照片。一个能够可靠地提供所有这些功能的单一、易于使用的系统将简化和增强照片制作过程。
    的头像 发表于 10-25 11:25 ?1185次阅读
    FPGA增强了<b class='flag-5'>数码相册</b>功能

    通过ESP32制作数码相册

    电子发烧友网站提供《通过ESP32制作数码相册.zip》资料免费下载
    发表于 06-16 11:30 ?3次下载
    通过ESP32制作<b class='flag-5'>数码相册</b>

    基于Java Web电子相册

    基于Java web的电子相册系统
    发表于 06-26 15:25 ?0次下载
    用什么洗脸可以美白 什么样的小溪 啤酒加味精有什么作用 pisen是什么牌子 肛门瘙痒用什么药膏好
    石棉是什么东西 火头鱼是什么鱼 什么海没有鱼 妥协是什么意思 一什么桥
    支气管炎咳嗽吃什么药 包虫病是什么症状 六十六大寿有什么讲究 什么是癫痫 为什么会长麦粒肿
    喝白茶有什么好处 梦见移坟墓是什么预兆 男占258女占369什么意思 惊喜的英文是什么 小孩说话不清楚挂什么科
    mg是什么元素creativexi.com 萎缩性胃炎伴糜烂吃什么药youbangsi.com 明天属什么生肖hcv7jop9ns3r.cn 养神经吃什么食物最好hcv8jop2ns2r.cn 蛇盘疮吃什么药好得快hcv9jop2ns0r.cn
    来姨妈不能吃什么水果xianpinbao.com 韭黄是什么hcv9jop1ns0r.cn 日本桑是什么意思hcv7jop4ns7r.cn otg线是什么hcv8jop8ns7r.cn 随性是什么意思hcv7jop6ns9r.cn
    脂肪肝用什么药物治疗hcv8jop6ns5r.cn 雌激素过高是什么原因造成的hcv9jop5ns5r.cn 山洪是什么意思hcv9jop1ns4r.cn 胸痛是什么病的前兆hcv9jop1ns0r.cn 载脂蛋白a1偏高是什么原因1949doufunao.com
    前囟门什么时候闭合hcv9jop5ns5r.cn 怕冷的女人是什么原因hcv9jop0ns6r.cn 岁寒三友指什么hcv8jop0ns7r.cn 女性的排卵期是什么时候hcv8jop7ns8r.cn 什么是创业板股票hcv8jop3ns7r.cn
    百度