文件IO编程五:调试输出到文本+目录操作

一、将调试打印信息存储到文本中

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值