一、将调试打印信息存储到文本中
int XPRINTF(char *text)//2、调试功能 定位到文本中
{
//1、以可写的方式打开log.txt,如果文件不存在则新建,如果存在了追加
FILE * fp = fopen(LOG_FILE,"ab");
if(fp == NULL)
{
printf("fopen %s error\n",LOG_FILE);
return -1;
}
//2、将传递进来的信息写入到调试文本中 fprintf
fprintf(fp,"%s",text);
//3、关闭文件
fclose(fp);
}
想个办法: 实现 每一次打开软件时,log.txt是从头记录的
//初始化调试文本
int initLog()
{
//1、打开文本 并且 清空内容 ,如果不存在,新建
FILE * fp = fopen(LOG_FILE,"wb+");
if(fp == NULL)
{
printf("fopen %s error\n",LOG_FILE);
return -1;
}
//3、关闭文件
fclose(fp);
}
将这个初始化调试文本函数放在main函数中初始化,即可。
二、目录操作API
效果: 实现一个程序,自动将我们某个指定的目录下所有的bmp图片 加载到 程序中。
思路: 1、打开指定的目录文件
2、读取目录,将目录下的每个文件的名字 加载 到 程序中
3、关闭目录文件
1、打开目录文件(opendir)
头文件:
#include <sys/types.h>
#include <dirent.h>
函数原型:
DIR *opendir(const char *name);
函数作用:
打开一个目录
参数:
name--》你要打开的目录 路径+ 名字
返回值:
成功返回 目录指针
失败返回 NULL ,错误被标记(可以使用perror函数打印错误原因)
2、读取目录(readdir)
头文件:
#include <dirent.h>
函数原型:
struct dirent *readdir(DIR *dirp);
函数作用:
读取目录
参数:
dirp --》你要读取哪个目录,将这个目录的目录指针传递进来
返回值:
成功返回 结构体指针 struct dirent* -->这个结构体指针记录了读取目录下文件的信息
失败或者 读完了 返回 NULL
struct dirent {
ino_t d_ino; /* 索引号 */
off_t d_off; /* 偏移量 */
unsigned short d_reclen; /* 项的长度 */
unsigned char d_type; /* 文件的类型 */
char d_name[256]; /* 文件名 */
};
文件的类型:
DT_BLK This is a block device. 块设备文件
DT_CHR This is a character device.
DT_DIR This is a directory. 目录文件
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file. 普通文件
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type is unknown.
注意: 调用一次 readdir函数,只能返回 该目录下一个文件的信息,如果想要获取这个目录所有的文件信息,可以循环读取
3、关闭目录文件(closedir)
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
4、相关练习
//opendir.c
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>
#define BMP_NUMBER 100 //最大只能支持读取100张图片
#define BMPDIR "./resource"
//效果:从 指定的目录中读取 所有bmp图片的名字,存储到数组中
int main()
{
char bmpName[BMP_NUMBER][256]={0};//存储图片的名字
int bmpCount=0; //记录当前加载进来的bmp图片数量
int i;
//打开目录
DIR *dirfp = opendir(BMPDIR);
if(dirfp == NULL)
{
perror("opendir error");
return -1;
}
while(1)
{
//读取目录
struct dirent *info = readdir(dirfp);
if(info == NULL)//如果读取完了 退出
break;
printf("d_name:%s\n",info->d_name); //info->d_name ---1.bmp
//去除 . 和 .. 而且 文件 是 普通 文件
if(info->d_name[0] != '.' && info->d_type == DT_REG)
{
//bmpName[0]---> ./reource/1.bmp
//将图片的路径 和 名字 拼接起来
char pathName[256]={0};
sprintf(pathName,"%s/%s",BMPDIR,info->d_name);
strcpy(bmpName[bmpCount++],pathName); // info->d_name[256] char d_name[256] = "1.bmp"
}
}
//将存储到数组中所有的图片名字都打印出来
for(i=0; i<bmpCount; i++)
{
printf("bmpName[%d]:%s\n",i,bmpName[i]);
}
//关闭目录文件
closedir(dirfp);
return 0;
}
实现 只拷贝 bmp图片文件到数组中,也就是判断当前普通文件是否是bmp图片文件:
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>
#define BMP_NUMBER 100 //最大只能支持读取100张图片
//#define BMPDIR "./resource"
//效果:从 指定的目录中读取 所有bmp图片的名字,存储到数组中
/*
dirOpt: 在指定的目录dirName下查找后缀名为suffix的所有的文件,并且保存在str这里
参数:
dirName:你要操作哪个目录,将这个目录的路径+名字传递进来
str:读取目录之后,将该目录下所有的文件名存储到这里
suffix:后缀名 ,注意不需要传递 .进来,比如现在记录bmp图片 传递 "bmp"即可
返回值:
成功返回 加载的文件的数量
失败返回 -1
*/
int dirOpt(char *dirName,char (*str)[256],char *suffix) //char bmpName[BMP_NUMBER][256]={0};
{
int fileCount=0; //记录当前加载进来的bmp图片数量
int i;
//打开目录
DIR *dirfp = opendir(dirName);
if(dirfp == NULL)
{
perror("opendir error");
return -1;
}
while(1)
{
//读取目录
struct dirent *info = readdir(dirfp);
if(info == NULL)//如果读取完了 退出
break;
printf("d_name:%s\n",info->d_name); //info->d_name ---1.bmp
//去除 . 和 .. 而且 文件 是 普通 文件
if(info->d_name[0] != '.' && info->d_type == DT_REG)
{
//判断当前普通文件是后缀名为.bmp或者.BMP的图片文件
//1.txt 2.bmp 3.c 4.h 5.BMP
//思路:文件名字info->d_name中一定有.bmp 或者.BMP
//思考有没有一个这样子的函数:在一个字符串(1.bmp)中判断是否包含另外一个字符串(.bmp)
/* char *ret1 = strstr(info->d_name, ".bmp"); //strstr 函数在一个字符串中查找指定的字符串
char *ret2 = strstr(info->d_name, ".BMP");
if(ret1 != NULL || ret2 != NULL) //strstr 如果找到了返回一个地址,没找到返回NULL */
int ret1 = strcmp(info->d_name+strlen(info->d_name)-3,suffix);
//int ret2 = strcmp(info->d_name+strlen(info->d_name)-3,"BMP");
if(ret1 ==0) //|| ret2 == 0) //strcmp比较两个字符串,如果相同返回0
{
//bmpName[0]---> ./reource/1.bmp
//将图片的路径 和 名字 拼接起来
char pathName[256]={0};
sprintf(pathName,"%s/%s",dirName,info->d_name);
strcpy(str[fileCount++],pathName); // info->d_name[256] char d_name[256] = "1.bmp"
}
}
}
//将存储到数组中所有的图片名字都打印出来
for(i=0; i<fileCount; i++)
{
printf("str[%d]:%s\n",i,str[i]);
}
//关闭目录文件
closedir(dirfp);
return fileCount;
}
int main()
{
char bmpName[BMP_NUMBER][256]={0};//存储图片的名字
int bmpCount = dirOpt("./resource", bmpName,"bmp");
printf("bmpCount:%d\n",bmpCount);
return 0;
}
三、作业
做一个简单的 电子相册:
1、在指定的目录下自动加载所有的图片 到 程序中
2、在液晶屏上 同时显示 4张 bmp图片
3、当点击 某张图片时,放大
4、当图片放大到全屏时,还可以退出
1、新建项目
2、c_source
3、include
4、res
5、相关代码
(1)main.c
#include "showbmp.h"
#include "ts.h"
#include "debug.h"
#define BMP_NUMBER 4
//字符串拼接 sprintf
char text[1024]={0};
int main(int argc,char*argv[])
{
initLog();
int ts_x,ts_y;
char bmpName[BMP_NUMBER][256]={0};
//初始化图片
int bmpCount = dirOpt("./res",bmpName,"bmp");
if(bmpCount == -1)
{
printf("init bmpdir error\n");
return -1;
}
int bmpFlag = 0;//用来控制图片显示的标志位
XPRINTF("main start.......\n");
//printf("main start.......\n");
//初始化
if(!initLcdAndMmap()) //if(initLcdAndMmap() = false)
{
//如果初始化失败
XPRINTF("initLcdAndMmap error\n");
//printf("initLcdAndMmap error\n");
return -1;
}
XPRINTF("initLcdAndMmap success.......\n");
int indexPos=-1;//你当前点击的缩略图中的位置
while(1)
{
showBmp_solv_xy(bmpName[0],100,100);
showBmp_solv_xy(bmpName[1],500,100);
showBmp_solv_xy(bmpName[2],100,250);
showBmp_solv_xy(bmpName[3],500,250);
ts_func(&ts_x,&ts_y);//触摸屏的代码调用一次,就是表示获取一次坐标,点击一次
//判断触摸的坐标
if((ts_x>=100 && ts_x<=(100+200))&& (ts_y >=100 && ts_y<=(100+120)))//在位置0 ---全屏显示 bmpName[0]
{
indexPos = 0;
}
else if((500<=ts_x && ts_x<=(500+200))&&(100<=ts_y && ts_y<=(100+120)))//在位置1 ---显示 bmpName[1]
{
indexPos = 1;
}
else if((100<=ts_x && ts_x<=(100+200))&&(250<=ts_y && ts_y<=(250+120)))//在位置2 ---显示 bmpName[2]
{
indexPos = 2;
}
else if((500<=ts_x && ts_x<=(500+200))&&(250<=ts_y && ts_y<=(250+120)))//在位置3 ---显示 bmpName[3]
{
indexPos = 3;
}
else{//如果点击的是其他区域,回到开头又重新判断坐标
XPRINTF("你当前点击的是其他区域......................\n");
continue;
}
showBmp_effect2(bmpName[indexPos]);
bmpFlag = indexPos;
while(1)
{
ts_func(&ts_x,&ts_y);//触摸屏的代码调用一次,就是表示获取一次坐标,点击一次
if(ts_x<=400 && ts_y<=240)//左上角
{
bmpFlag--;
//如果当前图片是第一张,点击左边时, 应该让其回到最后一张
if(bmpFlag == -1){
XPRINTF("当前是第一张,点击左边,回到最后一张\n");
bmpFlag = BMP_NUMBER -1;
}
bzero(text,1024);
sprintf(text,"left bmpFlag:%d\n",bmpFlag);
XPRINTF(text);
}
else if(ts_x>400 && ts_y<=240){ //右上角
bmpFlag++; //4
//如果当前图片是最后一张,点击右边时,应该让其回到第一张
if(bmpFlag == BMP_NUMBER){
XPRINTF("当前是最后一张,点击右边边,回到第一张\n");
bmpFlag = 0;
}
bzero(text,1024);
sprintf(text,"right bmpFlag:%d\n",bmpFlag);
XPRINTF(text);
}
else if(ts_y>240) //退出
{
break;
}
//显示
int ret = showBmp_effect2(bmpName[bmpFlag]);//bmpName[bmpFlag]---->char bmp[256]
if(ret == -1)//显示失败
{
bzero(text,1024);
sprintf(text,"showBmp error %s\n",bmpName[bmpFlag]);
XPRINTF(text);
}
else
XPRINTF("-------------showBmp success---------------\n\n");
}
}
//解除初始化
uinitLcd();
return 0;
}
(2)diropt.c
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>
//效果:从 指定的目录中读取 所有bmp图片的名字,存储到数组中
/*
dirOpt: 在指定的目录dirName下查找后缀名为suffix的所有的文件,并且保存在str这里
参数:
dirName:你要操作哪个目录,将这个目录的路径+名字传递进来
str:读取目录之后,将该目录下所有的文件名存储到这里
suffix:后缀名 ,注意不需要传递 .进来,比如现在记录bmp图片 传递 "bmp"即可
返回值:
成功返回 加载的文件的数量
失败返回 -1
*/
int dirOpt(char *dirName,char (*str)[256],char *suffix) //char bmpName[BMP_NUMBER][256]={0};
{
int fileCount=0; //记录当前加载进来的bmp图片数量
int i;
//打开目录
DIR *dirfp = opendir(dirName);
if(dirfp == NULL)
{
perror("opendir error");
return -1;
}
while(1)
{
//读取目录
struct dirent *info = readdir(dirfp);
if(info == NULL)//如果读取完了 退出
break;
printf("d_name:%s\n",info->d_name); //info->d_name ---1.bmp
//去除 . 和 .. 而且 文件 是 普通 文件
if(info->d_name[0] != '.' && info->d_type == DT_REG)
{
//判断当前普通文件是后缀名为.bmp或者.BMP的图片文件
int ret1 = strcmp(info->d_name+strlen(info->d_name)-3,suffix);
if(ret1 ==0) //strcmp比较两个字符串,如果相同返回0
{
//bmpName[0]---> ./reource/1.bmp
//将图片的路径 和 名字 拼接起来
char pathName[256]={0};
sprintf(pathName,"%s/%s",dirName,info->d_name);
strcpy(str[fileCount++],pathName); // info->d_name[256] char d_name[256] = "1.bmp"
}
}
}
//将存储到数组中所有的图片名字都打印出来
/* for(i=0; i<fileCount; i++)
{
printf("str[%d]:%s\n",i,str[i]);
} */
//关闭目录文件
closedir(dirfp);
return fileCount;
}
(3)showbmp.c
#include "showbmp.h"
#include "debug.h"
int lcdfd;
int *lcd_p;
extern char text[1024];
//得到bmp图片的宽度
int getBmpWidth(BITMAPINFOHEADER *head)
{
bzero(text,1024);
sprintf(text,"Width:%d\n",head->biWidth);//图像的宽度
XPRINTF(text);
return head->biWidth;
}
//得到bmp图片的高度
int getBmpHeight(BITMAPINFOHEADER *head)
{
bzero(text,1024);
sprintf(text,"Height:%d\n",head->biHeight);//图像的高度
XPRINTF(text);
return head->biHeight;
}
//得到bmp图片的大小
int getBmpSize(BITMAPINFOHEADER *head)
{
bzero(text,1024);
sprintf(text,"fileSize:%d\n",head->biSizeImage+54);//文件的大小
XPRINTF(text);
return head->biSizeImage+54;
}
//初始化液晶屏 和 内存映射
bool initLcdAndMmap()
{
XPRINTF("initLcdAndMmap start.......\n");
//1、打开液晶屏文件
lcdfd = open("/dev/fb0",O_RDWR);
if(lcdfd == -1)
{
XPRINTF("open lcd error");//perror将错误的原因打印出来
return false;
}
//将液晶屏文件 通过内存映射mmap的方式 映射到虚拟内存空间的某一块空间上,得到这一块内存的起始地址,后续我们操作这片内存空间,就相当于直接操作液晶屏文件
lcd_p = mmap(NULL, //你要映射的内存空间的起始地址,为NULL系统自动给你分配
800*480*4,//你要映射的内存空间的大小
PROT_READ|PROT_WRITE,//映射的权限
MAP_SHARED,//1、进程共享 2、对应的文件会同步发生变化
lcdfd,//映射液晶屏文件
0//偏移量 ,默认为0
);
if(lcd_p == MAP_FAILED)
{
XPRINTF("mmap lcd error\n");
return false;
}
return true;
}
//解除初始化
void uinitLcd()
{
//解除映射
munmap(lcd_p, 800*480*4);
//5、关闭液晶屏文件、bmp图片文件
close(lcdfd);
}
/*
showBmp:在(0,0)的位置上显示一张800*480的图片
返回值:
成功返回 0
失败返回 -1
*/
int showBmp(char *bmpPath)
{
bzero(text,1024);
sprintf(text,"showBmp bmpPath:%s\n",bmpPath);
XPRINTF(text);
int i,j;
int tempbuf[800*480];
int lcdbuf[800*480];
//2、打开bmp图片文件
int bmpfd = open(bmpPath,O_RDONLY);
if(bmpfd == -1)
{
XPRINTF("open bmpfile error");//perror将错误的原因打印出来
return -1;
}
//读取bmp图片的文件头 + 信息头数据
BITMAPFILEHEADER fileHead;
BITMAPINFOHEADER infoHead;
read(bmpfd,&fileHead,14);//读取14个字节
read(bmpfd,&infoHead,40);//读取40个字节
//判断是否宽度等于 800
if(BMP_WIDTH != getBmpWidth(&infoHead))
{
XPRINTF("你要打印的图片宽度 不等于 800 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//判断是否高度等于 480
if(BMP_HEIGHT != getBmpHeight(&infoHead))
{
XPRINTF("你要打印的图片高度 不等于 480 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//3、读取bmp图片的数据
char bmpbuf[800*480*3]={0};
read(bmpfd,bmpbuf,800*480*3);
//将bmp图片每个像素点的 B G R -->A R G B
for(i=0,j=0; i<800*480;i++,j+=3)
{
tempbuf[i] = 0x00<<24 | bmpbuf[j+2]<<16 | bmpbuf[j+1]<<8 | bmpbuf[j];
}
//上下180度颠倒
for(j=0; j<480; j++)
{
for(i=0; i<800; i++)
{
lcd_p[j*800+i] = tempbuf[(479-j)*800+i];
}
}
close(bmpfd);
return 0;
}
//在(0,0)的位置上显示一张800*480切割4倍后的200*120的图片
int showBmp_solv(char *bmpPath)
{
int i,j;
int tempbuf[800*480];
int lcdbuf[800*480];
int minbuf[200*120];
//2、打开bmp图片文件
int bmpfd = open(bmpPath,O_RDONLY);
if(bmpfd == -1)
{
XPRINTF("open bmpfile error");//perror将错误的原因打印出来
return -1;
}
//读取bmp图片的文件头 + 信息头数据
BITMAPFILEHEADER fileHead;
BITMAPINFOHEADER infoHead;
read(bmpfd,&fileHead,14);//读取14个字节
read(bmpfd,&infoHead,40);//读取40个字节
//判断是否宽度等于 800
if(BMP_WIDTH != getBmpWidth(&infoHead))
{
XPRINTF("你要打印的图片宽度 不等于 800 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//判断是否高度等于 480
if(BMP_HEIGHT != getBmpHeight(&infoHead))
{
XPRINTF("你要打印的图片高度 不等于 480 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//3、读取bmp图片的数据
char bmpbuf[800*480*3]={0};
read(bmpfd,bmpbuf,800*480*3);
//将bmp图片每个像素点的 B G R -->A R G B
for(i=0,j=0; i<800*480;i++,j+=3)
{
tempbuf[i] = 0x00<<24 | bmpbuf[j+2]<<16 | bmpbuf[j+1]<<8 | bmpbuf[j];
}
//上下180度颠倒
for(j=0; j<480; j++)
{
for(i=0; i<800; i++)
{
lcdbuf[j*800+i] = tempbuf[(479-j)*800+i];
}
}
//切割算法
//思路:每隔4行取一行像素,在每一行中,每4个像素点取一个像素点
//将lcdbuf --> 800*480 切割成 200*120 存储到 minbuf
for(j=0; j<120; j++)
{
for(i=0; i<200; i++)
{
minbuf[j*200+i] = lcdbuf[j*4*800+i*4]; //i == 0 4 8 12 16
}
}
//切割之后的数据存储在 minbuf ---200*120
//显示 ,赋值到 lcd_p
for(j=0; j<120; j++)
{
for(i=0; i<200; i++)
{
lcd_p[j*800+i] = minbuf[j*200+i];
}
}
close(bmpfd);
}
//在(posX,posY)的位置上显示一张800*480切割4倍后的200*120的图片
//
int showBmp_solv_xy(char *bmpPath,int posX,int posY)
{
int i,j;
int tempbuf[800*480];
int lcdbuf[800*480];
int minbuf[200*120];
//2、打开bmp图片文件
int bmpfd = open(bmpPath,O_RDONLY);
if(bmpfd == -1)
{
XPRINTF("open bmpfile error");//perror将错误的原因打印出来
return -1;
}
//读取bmp图片的文件头 + 信息头数据
BITMAPFILEHEADER fileHead;
BITMAPINFOHEADER infoHead;
read(bmpfd,&fileHead,14);//读取14个字节
read(bmpfd,&infoHead,40);//读取40个字节
//判断是否宽度等于 800
if(BMP_WIDTH != getBmpWidth(&infoHead))
{
XPRINTF("你要打印的图片宽度 不等于 800 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//判断是否高度等于 480
if(BMP_HEIGHT != getBmpHeight(&infoHead))
{
XPRINTF("你要打印的图片高度 不等于 480 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//3、读取bmp图片的数据
char bmpbuf[800*480*3]={0};
read(bmpfd,bmpbuf,800*480*3);
//将bmp图片每个像素点的 B G R -->A R G B
for(i=0,j=0; i<800*480;i++,j+=3)
{
tempbuf[i] = 0x00<<24 | bmpbuf[j+2]<<16 | bmpbuf[j+1]<<8 | bmpbuf[j];
}
//上下180度颠倒
for(j=0; j<480; j++)
{
for(i=0; i<800; i++)
{
lcdbuf[j*800+i] = tempbuf[(479-j)*800+i];
}
}
//切割算法
//思路:每隔4行取一行像素,在每一行中,每4个像素点取一个像素点
//将lcdbuf --> 800*480 切割成 200*120 存储到 minbuf
for(j=0; j<120; j++)
{
for(i=0; i<200; i++)
{
minbuf[j*200+i] = lcdbuf[j*4*800+i*4]; //i == 0 4 8 12 16
}
}
//切割之后的数据存储在 minbuf ---200*120
//显示 ,赋值到 lcd_p
//在指定的位置(posX,posY)上显示
for(j=0; j<120; j++)
{
for(i=0; i<200; i++)
{
//lcd_p[posY*800+posX+j*800+i] = minbuf[j*200+i];
lcd_p[(posY+j)*800+i+posX] = minbuf[j*200+i];
}
}
close(bmpfd);
}
/*
showBmp_effects1:动态效果显示一张图片
*/
int showBmp_effects1(char *bmpPath)
{
bzero(text,1024);
sprintf(text,"showBmp bmpPath:%s\n",bmpPath);
XPRINTF(text);
int i,j;
int tempbuf[800*480];
int lcdbuf[800*480];
int buf[800*480];
//2、打开bmp图片文件
int bmpfd = open(bmpPath,O_RDONLY);
if(bmpfd == -1)
{
XPRINTF("open bmpfile error");//perror将错误的原因打印出来
return -1;
}
//读取bmp图片的文件头 + 信息头数据
BITMAPFILEHEADER fileHead;
BITMAPINFOHEADER infoHead;
read(bmpfd,&fileHead,14);//读取14个字节
read(bmpfd,&infoHead,40);//读取40个字节
//判断是否宽度等于 800
if(BMP_WIDTH != getBmpWidth(&infoHead))
{
XPRINTF("你要打印的图片宽度 不等于 800 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//判断是否高度等于 480
if(BMP_HEIGHT != getBmpHeight(&infoHead))
{
XPRINTF("你要打印的图片高度 不等于 480 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//3、读取bmp图片的数据
char bmpbuf[800*480*3]={0};
read(bmpfd,bmpbuf,800*480*3);
//将bmp图片每个像素点的 B G R -->A R G B
for(i=0,j=0; i<800*480;i++,j+=3)
{
tempbuf[i] = 0x00<<24 | bmpbuf[j+2]<<16 | bmpbuf[j+1]<<8 | bmpbuf[j];
}
//上下180度颠倒
for(j=0; j<480; j++)
{
for(i=0; i<800; i++)
{
buf[j*800+i] = tempbuf[(479-j)*800+i];
}
}
//动态效果 ,延时显示
for(j=0; j<480; j++)
{
usleep(1000);//通过微妙级别的延时 让数据分时显示
for(i=0; i<800; i++)
{
lcd_p[j*800+i] = buf[j*800+i];
}
}
close(bmpfd);
return 0;
}
//在(0,0)的位置上显示一张800*480的图片
int showBmp_effect2(char *bmpPath)//中间上下展开
{
int i,j,k;
int tempbuf[800*480];
//int lcdbuf[800*480];
//2、打开bmp图片文件
int bmpfd = open(bmpPath,O_RDONLY);
if(bmpfd == -1)
{
perror("open bmpfile error");//perror将错误的原因打印出来
printf("没有该图片\n");
return -1;
}
//读取bmp图片的文件头 + 信息头数据
BITMAPFILEHEADER fileHead;
BITMAPINFOHEADER infoHead;
read(bmpfd,&fileHead,14);//读取14个字节
read(bmpfd,&infoHead,40);//读取40个字节
//判断是否宽度等于 800
if(BMP_WIDTH != getBmpWidth(&infoHead))
{
printf("你要打印的图片宽度 不等于 800 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//判断是否高度等于 480
if(BMP_HEIGHT != getBmpHeight(&infoHead))
{
printf("你要打印的图片高度 不等于 480 请重新修改图片 error\n");
//5、bmp图片文件
close(bmpfd);
return -1;
}
//3、读取bmp图片的数据
char bmpbuf[800*480*3]={0};
read(bmpfd,bmpbuf,800*480*3);
//将bmp图片每个像素点的 B G R -->A R G B
for(i=0,j=0; i<800*480;i++,j+=3)
{
tempbuf[i] = 0x00<<24 | bmpbuf[j+2]<<16 | bmpbuf[j+1]<<8 | bmpbuf[j];
}
//上下180度颠倒
for(j=240,k=241; j>=0,k<480; j--,k++)
{
usleep(10000);
for(i=0; i<800; i++)
{
lcd_p[j*800+i] = tempbuf[(479-j)*800+i];
lcd_p[k*800+i] = tempbuf[(479-k)*800+i];
}
}
close(bmpfd);
}
(4)showbmp.h
#ifndef __SHOWBMP_H_
#define __SHOWBMP_H_
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdbool.h>
#define UINT unsigned short
#define DWORD unsigned int
#define LONG unsigned int
#define WORD unsigned short
#define BMP_WIDTH 800
#define BMP_HEIGHT 480
//前面14个字节 文件信息头
typedef struct tagBITMAPFILEHEADER{
UINT bfType; //2
DWORD bfSize; //DWORD 4
UINT bfReserved1; //2
UINT bfReserved2; //2
DWORD bfOffBits; //DWORD 4
}BITMAPFILEHEADER;
//40个字节 位图信息头
typedef struct tagBITMAPINFOHEADER{ /* bmih */
DWORD biSize; //DWORD 4
LONG biWidth; //4 图像的宽度
LONG biHeight;//4 图像的高度
WORD biPlanes; //2
WORD biBitCount;//2
DWORD biCompression; //DWORD 4
DWORD biSizeImage; //DWORD 4
LONG biXPelsPerMeter;//4
LONG biYPelsPerMeter;//4
DWORD biClrUsed; //DWORD 4
DWORD biClrImportant; //DWORD 4
}BITMAPINFOHEADER;
extern int lcdfd;
extern int *lcd_p;
int getBmpWidth(BITMAPINFOHEADER *head);
int getBmpHeight(BITMAPINFOHEADER *head);
int getBmpSize(BITMAPINFOHEADER *head);
bool initLcdAndMmap();
void uinitLcd();
int showBmp(char *bmpPath);
int showBmp_solv(char *bmpPath);
int showBmp_solv_xy(char *bmpPath,int posX,int posY);
#endif
(5)ts.c
#include "ts.h"
#include "debug.h"
extern char text[1024];
/*触摸屏代码*/
int ts_func(int *x,int *y)
{
XPRINTF("ts_func 请用手触摸屏幕.......\n");
//1)打开触摸屏设备文件 ---
int tsfd = open("/dev/input/event0",O_RDWR);
if(tsfd == -1)
{
XPRINTF("open /dev/input/event0 error\n");
return -1;
}
while(1)
{
//2)分析 触摸屏的数据是什么数据类型???
//输入子系统计算完结果之后会将这个结果存储在结构体中
struct input_event info;
//3)读取触摸屏数据 --如果你没有用手触摸屏幕,当前会阻塞在这里
read(tsfd,&info,sizeof(struct input_event));
//判断当前发生的是触摸屏事件,接着判断触发的是X轴事件
if(info.type == EV_ABS && info.code == ABS_X)
*x = info.value;
//判断当前发生的是触摸屏事件,接着判断触发的是Y轴事件
if(info.type == EV_ABS && info.code == ABS_Y)
*y = info.value;
//松开的时候,才进行打印 type:1 code:330 value:0
if(info.type == EV_KEY && info.code == BTN_TOUCH && info.value == 0){
//如果你的板子是黑色的,那么需要进行坐标转换(1024,600) ---(800,480)
//*x = (*x *1.0)/1024 * 800 ;
//*y = (*y *1.0)/600 * 480 ;
bzero(text,1024);
sprintf(text,"(%d,%d)\n",*x,*y);
XPRINTF(text);
break;
}
}
//5)关闭触摸屏文件
close(tsfd);
}
(6)ts.h
#ifndef __TS_H_
#define __TS_H_
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdbool.h>
#include <linux/input.h>//触摸屏头文件
extern int ts_func(int *x,int *y);
#endif
(7)debug.c
#include "debug.h"
//初始化调试文本
int initLog()
{
//1、打开文本 并且 清空内容 ,如果不存在,新建
FILE * fp = fopen(LOG_FILE,"wb+");
if(fp == NULL)
{
printf("fopen %s error\n",LOG_FILE);
return -1;
}
//3、关闭文件
fclose(fp);
}
#ifdef DEBUG //开启调试功能
#ifndef DEBUG_TEXT
int XPRINTF(char *text) //1、调试功能 定位到屏幕终端
{
printf("%s",text);
}
#else
int XPRINTF(char *text)//2、调试功能 定位到文本中
{
//1、以可写的方式打开log.txt,如果文件不存在则新建,如果存在了追加
FILE * fp = fopen(LOG_FILE,"ab");
if(fp == NULL)
{
printf("fopen %s error\n",LOG_FILE);
return -1;
}
//2、将传递进来的信息写入到调试文本中 fprintf
fprintf(fp,"%s",text);
//3、关闭文件
fclose(fp);
}
#endif
#else
int XPRINTF(char *text)
{
}
#endif
(8)debug.h
#ifndef __DEBUG_H_
#define __DEBUG_H_
#include<stdio.h>
#include <strings.h>
#define LOG_FILE "./log.txt"
#define DEBUG //是否开启调试功能 调试的总开关
//#define DEBUG_TEXT //如果定义了该宏 将调试信息输出文本中
extern int XPRINTF(char *text);
extern int initLog();
#endif
(9)Makefile
CC = arm-linux-gcc
TARGET = bin/main
C_SOURCE = $(wildcard c_source/*.c)
INCLUDE_PATH = -I ./include
$(TARGET):$(C_SOURCE)
$(CC) $^ -o $@ $(INCLUDE_PATH)
.PHONY:clean
clean:
$(RM) $(TARGET)