Linux驱动.之framebufer,lcd,应用层按触摸进行翻页,画图显示bmp,jpeg,png图片(二)

Linux驱动.之framebufer,lcd,应用层按触摸进行翻页,画图显示bmp,jpeg,png图片

项目名称:基于ARM和linux API的数码相册
硬件平台:S5PV210(Cortex-A8内核)
软件平台:linux2.6.35.7,直接基于linux API操作
项目描述:
本项目主要涉及LCD、电容触摸屏等硬件,项目开发包括驱动开发与应用程序编写两部分。驱动开发重点在于触摸屏(LCD,根据应聘公司需求调整),应用程序直接基于linux API编写,未使用QT等框架库。
本项目实现的主要功能有:LCD设备主要参数、图片文件库文件列表及参数的自动获取;支持JPG、BMP、PNG等不同格式图片显示;支持触摸屏、按键等方式进行翻页显示;支持渐进、漂移等翻页动画;
本项目的重难点在于(此处根据公司职位需求,自己理解的深度挑选部分内容来讲解。可以考虑的点包括:JPG、PNG等编解码;触摸事件处理;驱动与应用的对应关系、接口等;其他细节(譬如BPP的适配,动画的实现方法等))
在这里插入图片描述

第一部分、章节目录
6.1.项目展示与整体规划
6.2.环境搭建和基础确认
6.3.开始动手写代码
6.4.framebuffer基本操作代码
6.5.图片显示原理和实践
6.6.图片数据提取和显示
6.7.图片显示的高级话题
6.8.其他显示细节问题
6.9.任意起点位置图片显示1
6.10.任意起点位置图片显示2
6.11.BMP图片的显示1
6.12.BMP图片的显示2
6.13.BMP图片的显示3
6.14.BMP图片的显示4
6.15.BMP图片的显示5
6.16.及时规整才能写出好项目1
6.17.及时规整才能写出好项目2
6.18.及时规整才能写出好项目3
6.19.jpg图片的显示原理分析1
6.20.jpg图片的显示原理分析2
6.21.libjpeg介绍及开源库的使用方法
6.22.libjpeg的移植实战1
6.23.libjpeg的移植实战2
6.24.使用libjpeg解码显示jpg图片1
6.25.使用libjpeg解码显示jpg图片2
6.26.使用libjpeg解码显示jpg图片3
6.27.使用libjpeg解码显示jpg图片4
6.28.使用libjpeg解码显示jpg图片5
6.29.解决解码显示中的问题1
6.30.解决解码显示中的问题2
6.31.结束jpg图片部分
6.32.解码显示png图片1
6.33.解码显示png图片2
6.34.解码显示png图片3
6.35.解码显示png图片4
6.36.解码显示png图片5
6.37.图片文件的管理和检索1
6.38.图片文件的管理和检索2
6.39.图片文件的管理和检索3
6.40.添加触摸翻页功能

1、该项目的最终形态
1.1、平台方面:本项目中会考虑平台可移植性,即可通过简单配置方便移植到各种开发板上(指不同大小尺寸的LCD,不同类型的触摸屏)
1.2、图片支持方面,会考虑支持以下图片格式:
* bmp 直接读取图片文件显示,如果图片大于LCD尺寸则使用插值缩放
* jpg libjpeg解码jpg->rgb888->rgb565
* png libpng解码
* gif libgif解码
1.3、操作支持方面,考虑做如下操作效果:
* 设定时间自动播放(通过串口操作,实现顺序播放、随机播放等)
* 点击屏幕两侧实现播放换页(上翻下翻)
* 划屏实现图片翻页(上翻下翻)
* 实现简单屏幕按钮控件,点击“上一页”、“下一页”等button进行换页显示

扩展功能:
* 在多点电容触摸屏上实现两指触摸放大缩小图片
* 图片播放同时增加背景音乐播放

2、项目执行计划
2.1、原则:项目采用分期逐步推进的方式执行,分数个版本来逐渐实现所有功能。
2.2、各版本初步规划

(1)版本1:
* 实现bmp、jpg、png、gif等图片的显示,移植各种解码库
* 实现播放列表组织,自动识别并显示各种格式的混杂图片库文件
* 实现自动定时切换顺序播放
(2)版本2:
* 添加触摸屏支持,实现侧边点击上下翻

3.通过读取文件内容来判断。
  所有的图片文件都包括:文件识别头和图象数据两部分,其中文件识别头用来让计算机判断是哪种文件 格式。
  JPEG
  所有的JPEG文件以字符串“0xFFD8”开头,并以字符串“0xFFD9”结束。依此便可判别是否是JPEG文件。
  BMP
  BMP文件以字符串“0x4D42”开头
  GIF
  gif头六个是 GIF89a或 GIF87a

第一部分:libjpeg & libpng & libgif库的移植
1、 libjpeg库移植
1.1、下载源码(http://www.photopost.com/jpegsrc.v6b.tar.gz)与准备交叉工具链
1.2、解压源码并进入解压后的目录。

1.3、配置。 ./configure --prefix=/opt/libdecode --exec-prefix=/opt/libdecode --enable-shared --enable-static -build=i386 -host=arm 
1.4、修改 Makefile
	CC=gcc 		改为 	CC=arm-linux-gcc
	AR=ar rc 	改为 	AR=arm-linux-ar rc
	AR2=ranlib 	改为 	AR2=arm-linux-ranlib
1.5、确认是否存在/opt/libdecode /include与/opt/libdecode/lib两个目录,若不存在则创建。
1.6、make && make install-lib	

安装完成后,可以在 /opt/libdecode/include 目录中找到libjpeg的头文件,
以后在编译包含了libjpeg的工程时,必须指定 -I /opt/libdecode/include,
同时在链接时需指定 -L /opt/libdecode/lib,若为动态链接,则必须将
/opt/libdecode/lib 中的so文件拷贝到运行时环境,且使用export LD_LIBRARY_PATH 将之导出到环境变量。

注:移植jpegsrc.v9.tar.gz时,使用以下的配置
./configure --prefix=/opt/libdecode --host=arm-none-linux-gnueabi

2、 zlib库移植
2.1、源码下载,这里下载了最新版1.2.8,网址为: http://www.zlib.net/
2.2、解压并进入目录 # tar -xvf zlib-1.2.8.tar.gz
2.3、导出CC以确定配置时为arm-linux-, # export CC=arm-linux-gcc
配置zlib库,得到Makefile, # ./configure -shared --prefix=/opt/libdecode
2.4、make && make install
指定库安装目录为/opt/libdecode,交叉编译后得到的zlib共享库文件放到了/opt/libdecode/lib中,头文件放到了/opt/libdecode/include中,man手册放到了/opt/libdecode/share/man下

3、 libpng库移植
3.1、libpng源码下载,目前最新的是1.6.6,下载地址为ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng16/。
3.2、解压并进入目录,# tar -xvf libpng-1.6.6.tar.gz
3.3、配置

# export LDFLAGS="-L/opt/libdecode/lib"
# export CFLAGS="-I/opt/libdecode/include"
# export CPPFLAGS="-I/opt/libdecode/include"
# ./configure --host=arm-linux --enable-shared --enable-static --prefix=/opt/libdecode
# make && make install

如果在进行配置前并未按照2中所述安装zlib,则配置运行了一部分后,会报错:
configure: error: zlib not installed
错误提示zlib库未安装,原因是libpng库依赖于zlib库。因此在编译libpng前必须先安装zlib(注意安装的是交叉编译的zlib,而不是给x86平台下使用的zlib)。
指定库安装目录为/opt/libdecode,交叉编译后得到的libpng共享库文件放到了/opt/libdecode/lib中,头文件放到了/opt/libdecode/include中,man手册放到了/opt/libdecode/share/man下
3.4、头文件拷贝
进入/opt/libdecode/include中可以看到,默认安装时已经拷贝了png.h pnglibconf.h pngconf.h三个头文件。但是实际做png解码显示图片时发现,只有上述三个头文件(实际上只有png.h有用到)是不够的,还需要另外两个头文件pngstruct.h和pnginfo.h。
在libpng源码目录下执行以下两条指令,将两个头文件人为拷贝过去以备使用即可。
# cp pnginfo.h /opt/libdecode/include/
# cp pngstruct.h /opt/libdecode/include/

4、 libgif库移植
1.1、下载源码与准备交叉工具链
1.2、解压源码并进入解压后的目录。
1.3、使能交叉编译, # export CC=arm-linux-gcc
配置, ./configure --prefix=/opt/libdecode --exec-prefix=/opt/libdecode --enable-shared --enable-static -build=i386 -host=arm
1.4、确认是否存在/opt/libdecode /bin目录,若不存在则创建。
1.5、make && make install

在这里插入图片描述
库文件,下载开源代码,编译生出的文件,将lib放进开发板lib下
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

bmp.h

#ifndef __BMP_H__
#define __BMP_H__

// BMP 文件头
typedef struct  
{  
//    unsigned short    bfType;  			// 2
    unsigned long    	bfSize; 			// 4 
    unsigned short    	bfReserved1;  
    unsigned short    	bfReserved2;  
    unsigned long    	bfOffBits;  
} ClBitMapFileHeader;

// BMP 信息头
typedef struct  
{  
    unsigned long  		biSize;   
    long   				biWidth;   
    long   				biHeight;   
    unsigned short   	biPlanes;   
    unsigned short   	biBitCount;  
    unsigned long 	 	biCompression;   
    unsigned long  		biSizeImage;   
    long   				biXPelsPerMeter;   
    long   				biYPelsPerMeter;   
    unsigned long  	 	biClrUsed;   
    unsigned long   	biClrImportant;   
} ClBitMapInfoHeader;  

#endif

fb.c

/*
 * fb.c 操作framebuffer的基础代码,包括fb的打开、ioctl获取信息
 *      基本的测试fb显示代码
 * *******************************************************/


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>


#include <fb.h>

 
 // 全局变量
 unsigned int *pfb = NULL;			// pfb指向framebuffer内存地址首地址
 int fbfd = -1;						// 打开fb后得到的fd
 
 
 
int fb_open(void)
{
	 int ret = -1;
	 
	 struct fb_fix_screeninfo finfo;
	 struct fb_var_screeninfo vinfo;
	 
	 // 第1步:打开设备
	 fbfd = open(FBDEVICE, O_RDWR);
	 if (fbfd < 0)
	 {
		 perror("open error");
		 return -1;
	 }
	 debug("open %s success.\n", FBDEVICE);
	 
	 // 第2步:获取设备的硬件信息
	 ret = ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);
	 if (ret < 0)
	 {
		 perror("ioctl");
		 return -1;
	 }
	 debug("smem_start = 0x%lx, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
	 
	 ret = ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
	 if (ret < 0)
	 {
		 perror("ioctl");
		 return -1;
	 }
	 debug("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	 debug("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	 debug("bpp = %u.\n", vinfo.bits_per_pixel);
 
	 
	 // 第3步:进行mmap
	 unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
	 debug("len = %ld\n", len);
	 pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
	 if (NULL == pfb)
	 {
		 perror("mmap error");
		 return -1;
	 }
	 debug("pfb = %p.\n", pfb);

	 return 0;
	 
}


void fb_close(void)
{	
	close(fbfd);
}
 
 
// 绘制屏幕背景色
void fb_draw_back(unsigned int width, unsigned int height, unsigned int color)
{
	 unsigned int x, y;
	 
	 for (y=0; y<height; y++)
	 {
		 for (x=0; x<width; x++)
		 {
			 *(pfb + y * WIDTH + x) = color;
		 }
	 }
}

// 画线测试函数
void fb_draw_line(unsigned int color)
{
	 unsigned int x;
	 
	 for (x=50; x<600; x++)
	 {
		 *(pfb + 200 * WIDTH + x) = color;
	 }
}
 
#if 0

// 测试显示1024*600分辨率的图片
void fb_draw_picutre(void)
{
	const unsigned char *pData = gImage_1024600;		// 指针指向图像数组
	unsigned int *p = pfb;
	unsigned int cnt;
	
	unsigned int i, j;

	for (i=0; i<HEIGHT; i++)
	{
		for (j=0; j<WIDTH; j++)
		{ 
			//cnt = WIDTH * i + j;		// 当前像素点的编号
			//cnt *= 3;					// 当前像素点的数据在数组中的下标
			cnt = 3 * (WIDTH * i + j);
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*p = ((pData[cnt+2]<<0) | (pData[cnt+1]<<8)| (pData[cnt+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			p++;
		}
	}
}


void fb_draw_picutre2(void)
{
	const unsigned char *pData = gImage_1024600;		// 指针指向图像数组
	unsigned int cnt;
	
	unsigned int x, y;

	for (y=0; y<HEIGHT; y++)
	{
		for (x=0; x<WIDTH; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[3*cnt+2]<<0) | (pData[3*cnt+1]<<8)| (pData[3*cnt+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			
		}
	}
}


void fb_draw_picutre3(void)
{
	const unsigned char *pData = gImage_1024600;		// 指针指向图像数组
	unsigned int cnt;
	unsigned int a = 0;
	
	unsigned int x, y;

	for (y=0; y<HEIGHT; y++)
	{
		for (x=0; x<WIDTH; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a += 3;
		}
	}
}

// 测试显示比屏幕小的图片的显示函数
void fb_draw_picutre4(void)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt;
	unsigned int a = 0;
	
	unsigned int x, y;

	// 图片大小分辨率是500*281
	for (y=0; y<281; y++)
	{
		for (x=0; x<500; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a += 3;
		}
	}
}

// 测试显示比屏幕小的图片的显示函数2
void fb_draw_picutre5(void)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt1, cnt2;
	
	unsigned int x, y;

	for (y=0; y<281; y++)
	{
		for (x=0; x<500; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt1 = WIDTH * y + x;
			cnt2 = 500 * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt1) = ((pData[3*cnt2+2]<<0) | (pData[3*cnt2+1]<<8)| (pData[3*cnt2+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			
		}
	}
}


// 函数完成功能: 将图片显示到起点坐标(x0, y0)处
void fb_draw_picutre6(unsigned int x0, unsigned int y0)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt1, cnt2;
	
	unsigned int x, y;

	for (y=y0; y<y0+281; y++)
	{
		for (x=x0; x<x0+500; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt1 = WIDTH * y + x;
			cnt2 = 500 * (y - y0) + (x - x0);


			// 算式的左值和右值分别要去考虑,
			// 左值考虑当前像素点在fb内存中的偏移量
			// 右值考虑当前像素点在图像数据数组中的下标
			*(pfb + cnt1) = ((pData[3*cnt2+2]<<0) | (pData[3*cnt2+1]<<8)| (pData[3*cnt2+0]<<16)); 
		}
	}
}

// 功能同6,不一样的算法
void fb_draw_picutre7(unsigned int x0, unsigned int y0)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt;
	unsigned int a = 0;
	
	unsigned int x, y;

	// 图片大小分辨率是500*281
	for (y=y0; y<y0+281; y++)
	{
		for (x=x0; x<x0+500; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a += 3;
		}
	}
}

// x和y两个方向超出屏幕外的部分都不显示
void fb_draw_picutre8(unsigned int x0, unsigned int y0)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt;
	unsigned int a = 0;
	
	unsigned int x, y;

	// 图片大小分辨率是500*281
	for (y=y0; y<y0+281; y++)
	{
		if (y >= HEIGHT)
		{
			// y方向超出了
			break;
		}
		
		for (x=x0; x<x0+500; x++)
		{ 
			if (x >= WIDTH)
			{
				// x方向超出屏幕外了
				a += 3;
				continue;
			}
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a += 3;
		}
	}
}

// 功能同8,算法不一样
void fb_draw_picutre9(unsigned int x0, unsigned int y0)
{
	const unsigned char *pData = gImage_picture;		// 指针指向图像数组
	unsigned int cnt1, cnt2;
	
	unsigned int x, y;

	for (y=y0; y<y0+281; y++)
	{
		for (x=x0; x<x0+500; x++)
		{ 
			if (x >= WIDTH)
			{
				// x方向超出屏幕外了
				continue;
			}
			
			//cnt表示当前像素点的编号
			cnt1 = WIDTH * y + x;
			cnt2 = 500 * (y - y0) + (x - x0);


			// 算式的左值和右值分别要去考虑,
			// 左值考虑当前像素点在fb内存中的偏移量
			// 右值考虑当前像素点在图像数据数组中的下标
			*(pfb + cnt1) = ((pData[3*cnt2+2]<<0) | (pData[3*cnt2+1]<<8)| (pData[3*cnt2+0]<<16)); 
		}
	}
}

#endif




void fb_draw(const struct pic_info *pPic)
{
	const char *pData = (const char *)pPic->pData;		// 指针指向图像数组
	unsigned int cnt = 0, a = 0;
	unsigned int x, y;

	debug("image resolution: %d * %d, bpp=%d.\n", 
		pPic->width, pPic->height, pPic->bpp);

	if ((pPic->bpp != 32) && (pPic->bpp != 24))
	{
		fprintf(stderr, "BPP %d is not support.\n", pPic->bpp);
		return;
	}

	a = pPic->height * pPic->width * 3 - 3;
	for (y=0; y<pPic->height; y++)
	{
		for (x=0; x<pPic->width; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+0]<<0) | (pData[a+1]<<8)| (pData[a+2]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a -= 3;
		}
	}
}


void fb_draw2(const struct pic_info *pPic)
{
	const char *pData = (const char *)pPic->pData;		// 指针指向图像数组
	unsigned int cnt = 0, a = 0;
	unsigned int x, y;

	if ((pPic->bpp != 32) && (pPic->bpp != 24))
	{
		fprintf(stderr, "BPP %d is not support.\n", pPic->bpp);
		return;
	}

	a = 0;
	for (y=0; y<pPic->height; y++)
	{
		for (x=0; x<pPic->width; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = WIDTH * y + x;
			// 当前像素点对应的图像数据的RGB就应该分别是:
			// pData[cnt+0]  pData[cnt+1]  pData[cnt+2]  
			// 当前像素点的数据
			*(pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			//*p = ((pData[cnt+0]<<16) | (pData[cnt+1]<<8)| (pData[cnt+2]<<0)); 
			a += 3;
		}
	}
}

fb_bmp.c

// 本文件用来解析BMP图片,并且显示到fb中
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#include "bmp.h"
#include <fb.h>
#include <config.h>


// 判断一个图片文件是不是一个合法的bmp文件
// 返回值: 如果是则返回0,不是则返回-1
int is_bmp(const char *path)
{
	int fd = -1;
	unsigned char buf[2] = {0};
	ssize_t ret = 0;
	
	// 第一步: 打开bmp图片
	fd = open(path, O_RDONLY);
	if (fd < 0)
	{
		fprintf(stderr, "open %s error.\n", path);
		return -1;
	}
	
	// 第二步: 读取文件头信息
	ret = read(fd, buf, 2);
	if (ret !=	2)
	{
		fprintf(stderr, "read file header error.\n");
		ret = -1;
		goto close;
	}
	
	// 解析头
	// 第三步: 判断是不是BMP图片
	if ((buf[0] != 'B') || (buf[1] != 'M'))
	{
		//fprintf(stderr, "file %s is not a bmp picture.\n", path);
		ret = -1;
		goto close;
	}
	else
	{
		ret = 0;
	}

close:
	close(fd);
	return ret;
}




// 参数列表: path: 要解析的bmp图片的pathname
// 函数功能: 该函数解析path这个bmp图片,并且将解析出来的图片数据丢到邋rgb_buf中去
// 返回值  : 错误时返回-1,解析正确返回0
static int bmp_analyze(struct pic_info *pPic)
{
	int fd = -1;
	ClBitMapFileHeader fHeader;
	ClBitMapInfoHeader info;
	unsigned short tmp;
	unsigned long len;

	// 第一步: 打开bmp图片
	fd = open(pPic->pathname, O_RDONLY);
	if (fd < 0)
	{
		fprintf(stderr, "open %s error.\n", pPic->pathname);
		return -1;
	}

	// 第二步: 读取文件头信息
	read(fd, &tmp, 2);
	read(fd, &fHeader, sizeof(fHeader));
	debug("bfSize = %ld.\n", fHeader.bfSize);
	debug("bfOffBits = %ld.\n", fHeader.bfOffBits);

	read(fd, &info, sizeof(info));
	debug("picutre resolution: %ld x %ld.\n", info.biWidth, info.biHeight);
	debug("picture bpp: %d.\n", info.biBitCount);
	pPic->width = info.biWidth;
	pPic->height = info.biHeight;
	pPic->bpp = info.biBitCount;			// 利用输出型参数

	// 第三步: 读取图片有效信息
	// 先把文件指针移动到有效信息的偏移量处
	lseek(fd, fHeader.bfOffBits, SEEK_SET);
	// 然后读出info.biWidth * info.biHeight * info.biBitCount / 3 这么多字节即可
	len = info.biWidth * info.biHeight * info.biBitCount / 3;
	read(fd, rgb_buf, len);
	//pPic->pData = rgb_buf;

	// 第四步: 把内容丢到fb中去显示
	fb_draw(pPic);
	

	// 最后关闭打开的文件
	close(fd);
	
	return 0;
}


// 封装的一个对外使用的bmp显示函数
// 本函数对外只需要一个bmp图片的pathname即可,那些复杂的数据结构都是bmp显示模块内部处理的
// 正确显示图片返回0,显示过程中出错则返回-1
int display_bmp(const char *pathname)
{
	int ret = -1;
	struct pic_info picture;
	
	// 第一步: 检测给的图片是不是bmp图片
	ret = is_bmp(pathname);
	if (ret != 0)
	{
		return -1;
	}
	// 第二步: 显示该jpg图片
	picture.pathname = pathname;
	picture.pData = rgb_buf;
	bmp_analyze(&picture);
}

fb_jpeg.c

/*
 * 本文件用来解码jpg图片,并调用fb.c中的显示接口来显示到lcd上
 */
#include <stdio.h>
 
#include <config.h>			// for debug

#include <jpeglib.h>
#include <jerror.h>
#include <string.h>


// 函数功能: 判断一个图片文件是不是jpg图片
// 函数参数: path是图片文件的pathname
// 返回值:   如果是jpg则返回0,不是则返回1,错误返回-1
int is_jpg(const char *path)
{
	FILE *file = NULL;
	char buf[2] = {0};
	// 打开文件
	file = fopen(path, "rb");
	if (NULL == file)
	{
		fprintf(stderr, "fopen %s error.\n", path);
		fclose(file);
		return -1;
	}
	// 读出前2个字节
	fread(buf, 1, 2, file);
	debug("read: 0x%x%x\n", buf[0], buf[1]);
	// 判断是不是0xffd8
	if (!((buf[0] == 0xff) && (buf[1] == 0xd8)))
	{
		fclose(file);
		return 1;		// 不是jpg图片
	}
	// 是0xffd8开头,就继续
	// 文件指针移动到倒数2个字符的位置
	fseek(file, -2, SEEK_END);
	// 读出2个字节
	fread(buf, 1, 2, file);
	debug("read: 0x%x%x\n", buf[0], buf[1]);
	// 判断是不是0xffd9
	if (!((buf[0] == 0xff) && (buf[1] == 0xd9)))
	{
		fclose(file);
		return 1;		// 不是jpg图片
	}

	fclose(file);
	
	return 0;
}



struct my_error_mgr 
{  
	struct jpeg_error_mgr pub;	/* "public" fields */  
//	jmp_buf setjmp_buffer;	/* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;


// 自己定义的错误处理函数
METHODDEF(void)my_error_exit (j_common_ptr cinfo)
{  
	//my_error_ptr myerr = (my_error_ptr) cinfo->err;  
	//(*cinfo->err->output_message) (cinfo);    
	fprintf(stderr, "my_error_exit\n");
	//longjmp(myerr->setjmp_buffer, 1);
}

/*
 * 函数功能: 解码jpg图片,并将解码出来的数据存储
 * 函数参数: pPIC,记录源jpg图片,解码出来的图片宽高、图片数据缓冲区等信息
 * 返回值  : 成功解码则返回0,失败则返回-1
 */
 
static int jpg_analyze(struct pic_info *pPic)
{
	struct jpeg_decompress_struct cinfo;		// cinfo贯穿整个解码过程的信息记录和传递的数据结构
	struct my_error_mgr jerr;					// 错误处理的	
	//JSAMPARRAY buffer = NULL;					// 指向解码行数据的指针
	char * buffer = NULL;
	FILE * infile;								// 指向fopen打开源jpg图片文件的指针
	int row_stride;								// 解码出来的一行图片信息的字节数

	if ((infile = fopen(pPic->pathname, "rb")) == NULL) 
	{    
		fprintf(stderr, "can't open %s\n", pPic->pathname);    
		return -1;  
	}

	// 第1步: 错误处理函数部分的绑定
	cinfo.err = jpeg_std_error(&jerr.pub);	
	jerr.pub.error_exit = my_error_exit;
	// 给解码器做必要的内存分配和数据结构的初始化
	jpeg_create_decompress(&cinfo);

	// 第2步: 将fopen打开的源jpg图片和解码器相关联
	jpeg_stdio_src(&cinfo, infile);

	// 第3步: 读jpg文件头
	jpeg_read_header(&cinfo, TRUE);

	// 第4步: 启动解码器
	jpeg_start_decompress(&cinfo);
	

	debug("image resolution: %d * %d, bpp/8=%d.\n", 
		cinfo.output_width, cinfo.output_height, cinfo.output_components);
	// 解码出来的数据一行的字节数
	row_stride = cinfo.output_width * cinfo.output_components;
	//buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
	buffer = (char *)malloc(row_stride);
	if (NULL == buffer)
	{
		fprintf(stderr, "cinfo.mem->alloc_sarray error.\n");
		return -1;
	}

	// 第5步: 逐行解码,并将解码出的数据丢到事先准备好的缓冲区去
	while (cinfo.output_scanline < cinfo.output_height) 
	{	 
		// 解码一行信息,并且丢到buffer中
		//jpeg_read_scanlines(&cinfo, buffer, 1);
		jpeg_read_scanlines(&cinfo, &buffer, 1);	 

		// 将buffer中这一行数据移走到别的地方去暂存或者使用,总之是要腾出buffer空间
		// 来给循环的下一次解码一行来使用
		memcpy(pPic->pData + (cinfo.output_scanline-1) * row_stride, buffer, row_stride);
	}

	// 第6步: 解码完了,做各种清理工作
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(infile);


	// jpg图片的数据记录下来
	pPic->width = cinfo.output_width;
	pPic->height = cinfo.output_height;
	pPic->bpp = cinfo.output_components * 8;


	return 0;
}


// 封装的一个对外使用的jpg显示函数
// 本函数对外只需要一个jpg图片的pathname即可,那些复杂的数据结构都是jpg显示模块内部处理的
// 正确显示图片返回0,显示过程中出错则返回-1
int display_jpg(const char *pathname)
{
	int ret = -1;
	struct pic_info picture;
	
	// 第一步: 检测给的图片是不是jpg图片
	ret = is_jpg(pathname);
	if (ret != 0)
	{
		return -1;
	}
	// 第二步: 解析该jpg图片
	picture.pathname = pathname;
	picture.pData = rgb_buf;
	jpg_analyze(&picture);

	// 第三步: 显示该jpg图片
	fb_draw2(&picture);
}

fb_png.c

/*
 * 本文件用来解码png图片,并调用fb.c中的显示接口来显示到lcd上
 */
#include <stdio.h>
#include <string.h>
 
#include <config.h>			// for debug

#include <png.h>
#include <pngstruct.h>		// 这个一定要放在png.h的后面包含
#include <pnginfo.h>



#define PNG_BYTES_TO_CHECK 		8



// 函数功能: 判断一个图片文件是不是png图片
// 函数参数: path是图片文件的pathname
// 返回值:   如果是png则返回0,不是则非0
int is_png(const char *path)
{
	FILE *fp = NULL;
	char buf[PNG_BYTES_TO_CHECK] = {0};	

	/* Open the prospective PNG file. */   
	if ((fp = fopen(path, "rb")) == NULL)		
		return -1;	

	/* Read in some of the signature bytes */	
	if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)	   
		return -1; 

//	printf("%d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);
	/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.		
	Return nonzero (true) if they match */	 
	return(png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}


/*
 * 函数功能: 解码png图片,并将解码出来的数据存储
 * 函数参数: pPIC,记录源png图片,解码出来的图片宽高、图片数据缓冲区等信息
 * 返回值  : 成功解码则返回0,失败则返回-1
 */
 
static int png_analyze(struct pic_info *pPic)
{
	FILE *fp = NULL;
	png_structp png_ptr;   
	png_infop info_ptr;
	int color_type;
	png_bytep* row_pointers;
	unsigned long len = 0;
	int pos = 0;
	int i = 0, j = 0;

	if ((fp = fopen(pPic->pathname, "rb")) == NULL) 
	{	 
		fprintf(stderr, "can't open %s\n", pPic->pathname);    
		return -1;	
	}

	// 第1步: 相关数据结构实例化
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (png_ptr == 0)
	{
		fclose(fp);
		return -1;
	}

	info_ptr = png_create_info_struct(png_ptr);
  	if (info_ptr == 0)
  	{
   		png_destroy_read_struct(&png_ptr, 0, 0);
   		fclose(fp);
   		return -1;
  	}

	// 第2步: 设置错误处理函数
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, 0);
		fclose(fp);
		return -1;
	}

	// 第3步: 将要解码的png图片的文件指针和png解码器绑定起来
	png_init_io(png_ptr, fp);

	// 第4步: 读取png图片信息
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);

	// 第5步: 相关图片信息打印出来看一看
	color_type = info_ptr->color_type;
	debug("color_type = %d\n", color_type);

	pPic->width = info_ptr->width;
	pPic->height = info_ptr->height;
	pPic->bpp = info_ptr->pixel_depth;
	len = info_ptr->width * info_ptr->height * info_ptr->pixel_depth / 8;
	debug("width = %u, height = %u, bpp = %u\n", pPic->width, pPic->height, pPic->bpp);

	// 第6步: 读取真正的图像信息
	row_pointers = png_get_rows(png_ptr,info_ptr);

	// 只处理RGB24位真彩色图片,其他格式的图片不管
	// 第7步: 图像数据移动到我们自己的buf中
	if(color_type == PNG_COLOR_TYPE_RGB)
  	{
   		//memcpy(pPic->pData, row_pointers, len);
		for(i=0; i<pPic->height; i++)
		{
			for(j=0; j<3*pPic->width; j+=3)
			{
				pPic->pData[pos++] = row_pointers[i][j+0];		
				pPic->pData[pos++] = row_pointers[i][j+1];		
				pPic->pData[pos++] = row_pointers[i][j+2];		
			}
		}
  	}

	// 第8步: 收尾处理
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	// close file
	fclose(fp);
	
	return 0;
}



// 封装的一个对外使用的png显示函数
// 本函数对外只需要一个png图片的pathname即可,那些复杂的数据结构都是jpg显示模块内部处理的
// 正确显示图片返回0,显示过程中出错则返回-1
int display_png(const char *pathname)
{
	int ret = -1;
	struct pic_info picture;

	// 第一步: 检测给的图片是不是jpg图片
	ret = is_png(pathname);
	if (ret != 0)
	{
		return -1;
	}
	debug("%s is a png\n", pathname);

	// 第二步: 解析jpg图片
	picture.pathname = pathname;
	picture.pData = rgb_buf;
	png_analyze(&picture);

	// 第三步: 显示jpg图片
	fb_draw2(&picture);

	return 0;
}

makefile

obj-y += fb.o
obj-y += fb_bmp.o
obj-y += fb_jpeg.o
obj-y += fb_png.o

picture.h

const unsigned char gImage_picture[421500] = { /* 0X00,0X18,0XF4,0X01,0X19,0X01,0X00,0X1B, */
0X6E,0X5C,0X52,0X6F,0X5B,0X52,0X6E,0X5A,0X4F,0X6D,0X59,0X4E,0X6C,0X58,0X4D,0X6C,
0X56,0X49,0X69,0X53,0X46,0X67,0X51,0X44,0X69,0X51,0X47,0X68,0X50,0X46,0X65,0X4C,
0X45,0X63,0X4A,0X43,0X62,0X49,0X42,0X60,0X47,0X42,0X5E,0X45,0X40,0X5D,0X44,0X3F,
0X5C,0X43,0X3C,0X5B,0X44,0X3C,0X5B,0X44,0X3C,0X5C,0X45,0X3D,0X5C,0X45,0X3D,0X5A,
0X46,0X3D,0X5A,0X46,0X3D,0X59,0X45,0X3C,0X56,0X41,0X3C,0X57,0X42,0X3D,0X58,0X43,
0X3E,0X57,0X42,0X3D,0X55,0X40,0X3B,0X54,0X3F,0X3A,0X54,0X3F,0X3A,0X54,0X3F,0X3A,
0X55,0X42,0X3B,0X55,0X42,0X3B,0X56,0X43,0X3C,0X59,0X45,0X3E,0X58,0X44,0X3D,0X54,
0X40,0X39,0X51,0X3D,0X36,0X52,0X3B,0X35,0X56,0X41,0X3C,0X55,0X40,0X3B,0X54,0X3F,
0X3A,0X55,0X40,0X3B,0X55,0X42,0X3C,0X55,0X42,0X3C,0X53,0X40,0X3A,0X52,0X3F,0X39,
0X56,0X43,0X3F,0X55,0X42,0X3E,0X55,0X42,0X3E,0X56,0X43,0X3D,0X56,0X43,0X3D,0X55,
0X44,0X3C,0X56,0X45,0X3D,0X56,0X45,0X3D,0X5C,0X49,0X45,0X5A,0X47,0X43,0X5A,0X47,
0X41,0X5B,0X48,0X42,0X5C,0X49,0X43,0X5C,0X49,0X43,0X5D,0X4A,0X43,0X5E,0X4B,0X44,
0X60,0X4F,0X48,0X60,0X4F,0X48,0X61,0X50,0X49,0X61,0X50,0X49,0X62,0X51,0X4A,0X63,};

在这里插入图片描述

在这里插入图片描述

image_manager.c

#include "image_manager.h"

#include <config.h>
#include <fb.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>




// 定义存储图片信息的数组

image_info_t images[MAX_IMAGE_CNT];
unsigned int image_index = 0;			// 数组images中的计数index


// images数组本来是空的,然后程序初始化时会去一个事先约定好的目录(image目录)下去
// 递归检索所有的文件及子文件夹,并且将所有的图片格式收集并且填充记录到images数组中
// 经过检索后,image数组中就记录了所有的图片,然后显示图片逻辑部分再去这个图片库中
// 拿出相应的图片来显示即可
// path是要去检索的文件夹的pathname
int scan_image(const char *path)
{
	// 在本函数中递归检索path文件夹,将其中所有图片填充到iamges数组中去
	DIR *dir;
	struct dirent *ptr;
	char base[1000];

	if ((dir = opendir(path)) == NULL)
	{
		perror("Open dir error...");
		exit(1);
	}

	// readdir函数每调用一次就会返回opendir打开的basepath目录下的一个文件,直到
	// basepath目录下所有文件都被读完之后,就会返回NULL
	while ((ptr = readdir(dir)) != NULL)
	{
		if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0)    ///current dir OR parrent dir
			continue;

		debug("d_name = %s.\n", ptr->d_name);
		debug("d_type = %d, DT_REG = %d, DT_DIR = %d, DT_UNKNOWN = %d.\n", 
			ptr->d_type, DT_REG, DT_DIR, DT_UNKNOWN);
		switch (ptr->d_type)
		{
			case DT_REG:			// 普通文件
				printf("d_name:%s/%s\n", path, ptr->d_name);
				break;
			case DT_DIR:			// 文件夹
				memset(base,'\0',sizeof(base));
				strcpy(base,path);
				strcat(base,"/");
				strcat(base,ptr->d_name);
				scan_image(base);
				break;
			case DT_UNKNOWN:		// 不识别的文件格式
				printf("unknown file type.\n");
				break;
			default:
				break;
		}
	}
}



int scan_image2(const char *path)
{
	// 在本函数中递归检索path文件夹,将其中所有图片填充到iamges数组中去
	DIR *dir;
	struct dirent *ptr;
	char base[1000];
	struct stat sta;

	if ((dir = opendir(path)) == NULL)
	{
		perror("Open dir error...");
		exit(1);
	}

	// readdir函数每调用一次就会返回opendir打开的basepath目录下的一个文件,直到
	// basepath目录下所有文件都被读完之后,就会返回NULL
	while ((ptr = readdir(dir)) != NULL)
	{
		if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0)    ///current dir OR parrent dir
			continue;

		// 用lstat来读取文件属性并判断文件类型
		memset(base,'\0',sizeof(base));
		strcpy(base,path);
		strcat(base,"/");
		strcat(base,ptr->d_name);
		lstat(base, &sta);

		if (S_ISREG(sta.st_mode))
		{
			//printf("regular file.\n");
			//printf("d_name:%s/%s\n", path, ptr->d_name);
			// 如果是普通文件,就要在这里进行处理:
			// 处理思路就是 先判定是否属于已知的某种图片格式,如果是则放到images数组中
			// 如果都不属于则不理他
			if (!is_bmp(base))
			{
				strcpy(images[image_index].pathname, base);
				images[image_index].type = IMAGE_TYPE_BMP;
			}
			if (!is_jpg(base))
			{
				strcpy(images[image_index].pathname, base);
				images[image_index].type = IMAGE_TYPE_JPG;
			}
			if (!is_png(base))
			{
				strcpy(images[image_index].pathname, base);
				images[image_index].type = IMAGE_TYPE_PNG;
			}		
			image_index++;
			
		}
		if (S_ISDIR(sta.st_mode))
		{
			//printf("directory.\n");
			//printf("d_name:%s/%s\n", path, ptr->d_name);
			scan_image2(base);
		}
	}
}



void print_images(void)
{
	int i;

	printf("iamge_index = %d.\n", image_index);
	for (i=0; i<image_index; i++)
	{
		printf("images[i].pathname = %s,		type = %d.\n", images[i].pathname, images[i].type);
	}
}


void show_images(void)
{
	int i;

	for (i=0; i<image_index; i++)
	{
		switch (images[i].type)
		{
			case IMAGE_TYPE_BMP:
				display_bmp(images[i].pathname);		break;
			case IMAGE_TYPE_JPG:
				display_jpg(images[i].pathname);		break;
			case IMAGE_TYPE_PNG:
				display_png(images[i].pathname);		break;
			default:
				break;
		}
		sleep(2);
	}
}


static void show_image(int index)
{
	debug("index = %d.\n", index);
	switch (images[index].type)
	{
		case IMAGE_TYPE_BMP:
			display_bmp(images[index].pathname);		break;
		case IMAGE_TYPE_JPG:
			display_jpg(images[index].pathname);		break;
		case IMAGE_TYPE_PNG:
			display_png(images[index].pathname);		break;
		default:
			break;
	}	
}


// 本函数实现通过触摸屏来对图片翻页显示
int ts_updown(void)
{
	// 第一步: 触摸屏的触摸操作检测
	int fd = -1, ret = -1;
	struct input_event ev;
	int i = 0;					// 用来记录当前显示的是第几个图片
		
	fd = open(DEVICE_TOUCHSCREEN, O_RDONLY);
	if (fd < 0)
	{
		perror("open");
		return -1;
	}
		
	while (1)
	{
		memset(&ev, 0, sizeof(struct input_event));
		ret = read(fd, &ev, sizeof(struct input_event));
		if (ret != sizeof(struct input_event))
		{
			perror("read");
			close(fd);
			return -1;
		}

		// 第二步: 根据触摸坐标来翻页
		if ((ev.type == EV_ABS) && (ev.code == ABS_X))
		{
			// 确定这个是x坐标
			if ((ev.value >= 0) && (ev.value < TOUCH_WIDTH))
			{
				// 上翻页
				if (i-- <= 1)
				{
					i = image_index;
					debug("i=%d.\n", i);
				}
				
			}
			else if ((ev.value > (WIDTH - TOUCH_WIDTH)) && (ev.value <= WIDTH))
			{
				// 下翻页			
				if (i++ >= image_index)
				{
					i = 1;
					debug("i=%d.\n", i);
				}
			}
			else
			{
				// 不翻页
			}
			show_image(i - 1);
		}
		
			
/*
		printf("-------------------------\n");
		printf("type: %hd\n", ev.type);
		printf("code: %hd\n", ev.code);
		printf("value: %d\n", ev.value);
		printf("\n");
		*/
	}	
	close(fd);

	return 0;
	
}

image_manager.h


#define PATHNAME_LEN		256

typedef enum image_type
{
	IMAGE_TYPE_BMP,
	IMAGE_TYPE_JPG,
	IMAGE_TYPE_PNG,
	IMAGE_TPPE_UNKNOWN,
}image_type_e;


// 结构体用来封装一个图片的信息
typedef struct image_info
{
	char pathname[PATHNAME_LEN];			// 图片文件的pathname
	image_type_e type;						// 图片文件的格式
}image_info_t;

makefile

obj-y += image_manager.o

在这里插入图片描述

fb.h

#include <config.h>


 // 宏定义
#define FBDEVICE	"/dev/fb0"
 
 // 旧开发板
 //#define WIDTH	 800 
 //#define HEIGHT	 480
 
 // 新开发板
#define WIDTH		1024	
#define HEIGHT		600
 
 
#define WHITE		0xffffffff			// test ok
#define BLACK		0x00000000
#define RED			0x00ff0000
#define GREEN		0xff00ff00			// test ok
#define BLUE		0xff0000ff			
 

 
 // 函数声明
 int fb_open(void);
 void fb_close(void);
 void fb_draw_back(unsigned int width, unsigned int height, unsigned int color);
 void fb_draw_line(unsigned int color);
 /*
 void fb_draw_picutre(void);
 void fb_draw_picutre2(void);
 void fb_draw_picutre3(void);
 void fb_draw_picutre4(void);
 void fb_draw_picutre5(void);
 void fb_draw_picutre6(unsigned int x0, unsigned int y0);
 void fb_draw_picutre7(unsigned int x0, unsigned int y0);
 void fb_draw_picutre8(unsigned int x0, unsigned int y0);
 void fb_draw_picutre9(unsigned int x0, unsigned int y0);
 */


// 这两个显示函数的差异是: 彼此的rgb顺序相反且转了180度
void fb_draw(const struct pic_info *pPic);
void fb_draw2(const struct pic_info *pPic);

config.h

#ifndef __CONFIG_H__
#define __CONFIG_H__


/******** 宏定义 ****************************************************************/

//#define DEBUG			// 打开调试信息输出的开关

// debug宏的定义
#ifdef DEBUG
#define debug(...)                                                      \
        {                                                               \
            fprintf(stderr, "[debug][%s:%s:%d] ",                     \
                    __FILE__, __FUNCTION__, __LINE__);                  \
            fprintf(stderr, __VA_ARGS__);                               \
        }
#else
#define debug(...)  
#endif

// 我们规定最大支持1920*1080这么大的图片,BPP最多24
#define BMP_MAX_RESOLUTION		(1920*1080)
#define BMP_BUF_SIZE			(BMP_MAX_RESOLUTION*3)

// 我们规定最多支持100张图片
#define MAX_IMAGE_CNT			100

// 定义系统中的触摸屏设备的设备名
#define DEVICE_TOUCHSCREEN		"/dev/input/event1"
#define TOUCH_WIDTH				200				// 定义触摸翻页区域的宽度


/***********  结构体定义  ****************************************************/

// 结构体用来封装一个图片的各种信息
typedef struct pic_info
{
	char *pathname;			// 图片在文件系统中的路径名+文件名
	unsigned int width;		// 图片分辨率之宽
	unsigned int height;	// 图片分辨率之高
	unsigned int bpp;		// 图片bpp
	char *pData;			// 指向图片有效数据存储的buf数据
}pic_info;



/***********  全局变量 ***************************************************/
extern char rgb_buf[BMP_BUF_SIZE];





/********* 函数原型 *******************************************************/
int is_bmp(const char *path);
int is_jpg(const char *path);
int is_png(const char *path);


int display_bmp(const char *pathname);
int display_jpg(const char *pathname);
int display_png(const char *pathname);


int scan_image(const char *path);
int scan_image2(const char *path);
void show_images(void);
int ts_updown(void);






#endif

main.c

#include <stdio.h>
#include <unistd.h>

#include <fb.h>
#include <config.h>



char rgb_buf[BMP_BUF_SIZE];






int main(void)
{
	int ret = -1;

	printf("image decode player.....\n");

	ret = fb_open();
	if (ret < 0)
	{
		printf("fb_open error.\n");
		return -1;
	}

	//fb_draw_back(1024, 600, RED);
	//fb_draw_picutre6(100, 100);
	//fb_draw_picutre7((1024-500)/2, (600-281)/2);
	//fb_draw_picutre9(800, 100);

// 测试bmp图片显示,ok	
//	picture.pathname = "meinv.bmp";			// 指向要显示的图片
//	bmp_analyze(&picture);

// 测试jpg图片显示
//	display_bmp("123.bmp");
//	sleep(3);
//	display_jpg("meinv.jpg");

//	display_png("meinv.png");
//	debug("-------------\n");


	scan_image2("./image");
//	print_images();
//	while(1)
//		show_images();

	ts_updown();

	
	
	fb_close();

	

	return 0;
}

在这里插入图片描述
主makefile


#CROSS_COMPILE = arm-none-linux-gnueabi-
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

AS			= $(CROSS_COMPILE)as
LD			= $(CROSS_COMPILE)ld
CC			= $(CROSS_COMPILE)gcc
CPP			= $(CC) -E
AR			= $(CROSS_COMPILE)ar
NM			= $(CROSS_COMPILE)nm
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump

# export导出的变量是给子目录下的Makefile使用的
export AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP

# 编译器在编译时的参数设置
CFLAGS := -Wall -O2 -g -DDEBUG
# 添加头文件路径,不添加的话include目录下的头文件编译时找不到
CFLAGS += -I $(shell pwd)/include -I/opt/libdecode/include

# 链接器的链接参数设置
LDFLAGS := -ljpeg -lz -lpng -L/opt/libdecode/lib

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR

# 定义将来编译生成的可执行程序的名字
TARGET := imageplayer

# 添加项目中所有用到的源文件,有顶层目录下的.c文件,和子文件夹
# 添加顶层目录下的.c文件
obj-y += main.o

# 添加顶层目录下的子文件夹(注意目录名后面加一个/)
obj-y += display/
obj-y += image_manage/

all: 
	make -C ./ -f $(TOPDIR)/Makefile.build
	$(CC) $(LDFLAGS) -o $(TARGET) built-in.o

cp:
	cp ../testproject/ /root/rootfs/ -rf

clean:
	rm -f $(shell find -name "*.o")
	rm -f $(TARGET)

distclean:
	rm -f $(shell find -name "*.o")
	rm -f $(shell find -name "*.d")
	rm -f $(TARGET)
	

在这里插入图片描述

PHONY := __build
__build:


obj-y :=
subdir-y :=

include Makefile


__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y	+= $(__subdir-y)


subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)


cur_objs := $(filter-out %/, $(obj-y))
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))

ifneq ($(dep_files),)
  include $(dep_files)
endif


PHONY += $(subdir-y)


__build : $(subdir-y) built-in.o

$(subdir-y):
	make -C $@ -f $(TOPDIR)/Makefile.build

built-in.o : $(cur_objs) $(subdir_objs)
	$(LD) -r -o $@ $^

dep_file = .$@.d

%.o : %.c
	$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<
	
.PHONY : $(PHONY)

项目整理后的
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

/*
 *  dpicture/display/fb.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of fb:  Aston Zhu <AstonZhu.0@gmail.com> 
 */

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>

#include <config.h>
#include <fb.h>
#include <dpicture.h>

/****************************** global variables *****************************/


	
	
/******************************************************************************
Description.: open framebuffer device from global config var FB_DEV
Parameter	: global, a pointer to data structure of global_t
Return Value: return 0 if successfully, -1 if failure occured
Input Value.: global, a pointer to data structure of global_t
Output Value: none
******************************************************************************/
static int fb_open(void)
{
	global.fb_info.fbfd = open(FB_DEV, O_RDWR);
	if (global.fb_info.fbfd < 0) {
		fprintf(stderr, "Error: cannot open framebuffer device.%x\n", global.fb_info.fbfd);
		return -1;
	}
	DBG("The framebuffer device: %s was opened successfully.\n", FB_DEV);
	
	return 0;
}

/******************************************************************************
Description.: get fscreeninfo and vscreeninfo from the driver layer, and save 3
			  most important params(xres, yres, bpp) to fbinfo.
Parameter	: global, a pointer to data structure of global_t
Return Value: return 0 if successfully, -1 if failure occured
Input Value.: global, a pointer to data structure of global_t
Output Value: none
******************************************************************************/
static int fb_getinfo(void)
{
	struct fb_var_screeninfo vinfo;	
	struct fb_fix_screeninfo finfo;
	
    // Get fixed screen information
	if (ioctl(global.fb_info.fbfd, FBIOGET_FSCREENINFO, &finfo)) {
		fprintf(stderr, "Error reading fixed information.\n");
		return -1;
	}
	DBG("mem_start:0x%x,smem_len:%d\n", (unsigned int)finfo.smem_start, finfo.smem_len );
	DBG("mmio_start:0x%x ,mmio_len:%d\n", (unsigned int)finfo.mmio_start, finfo.mmio_len );

	// Get variable screen information
	if (ioctl(global.fb_info.fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
		fprintf(stderr, "Error reading variable information.\n");
		return -1;
	}
	
	global.fb_info.wfb = vinfo.xres;						// x resolution
	global.fb_info.hfb = vinfo.yres;						// y resolution
	global.fb_info.bpp = vinfo.bits_per_pixel;				// bpp setting of the driver
	global.fb_info.sizefb = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;		// size of fb
	
	DBG("display size and resolution: %u, %u x %u, bpp: %u.\n", global.fb_info.sizefb, global.fb_info.wfb, global.fb_info.hfb, global.fb_info.bpp);

	return 0;
}

/******************************************************************************
Description.: set bits_per_pixel to new_bpp 
Parameter	: new_bpp, the new value of bpp we want to set
Return Value: return 0 if successfully, -1 if failure occured
Input Value.: new_bpp of a enumeration
Output Value: none
******************************************************************************/
static int fb_setbpp(e_bpp new_bpp)
{
	struct fb_var_screeninfo vinfo;	
	// 1. 先读出原来的vinfo,以得知原来的bpp
	if (ioctl(global.fb_info.fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
		fprintf(stderr, "Error reading variable information.\n");
		return -1;
	}
	DBG("original resolution: %dx%d, bpp: %d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
	// 2. 再将新的bpp写入
	vinfo.bits_per_pixel = new_bpp;
	if (ioctl(global.fb_info.fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
		fprintf(stderr, "Error writing variable information.\n");
		return -1;
	}
	DBG("write vinfo success\n");
#if 0
	// 3. 再次读出新的bpp,看看是否有修改过来
	if (ioctl(global->fb_info.fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
		fprintf(stderr, "Error reading variable information.\n");
		return -1;
	}
	DBG("new resolution: %dx%d, bpp: %d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
#endif	
}

/******************************************************************************
Description.: map the framebuffer to process address space, so that we can 
			  operate the fb directly from user space.
Parameter	: global, a pointer to data structure of global_t
Return Value: return 0 if successfully, -1 if failure occured
Input Value.: global, a pointer to data structure of global_t
Output Value: none
******************************************************************************/
static int fb_mapdev(void)
{
	// Map the device to memory
	global.fb_info.pfb.pfb32 = mmap(0, global.fb_info.sizefb, PROT_READ | PROT_WRITE, 
			MAP_SHARED, global.fb_info.fbfd, 0);
       
	if ((int)global.fb_info.pfb.pfb32 == -1) {
		fprintf(stderr, "Error: failed to map framebuffer device to memory.\n");
		return -1;
	}
	DBG("The framebuffer device was mapped to memory successfully.\n");
	
	return 0;
}

/******************************************************************************
Description.: fb display using raw data.
Parameter	: global, a pointer to data structure of global_t
Return Value: return 0 if successfully, -1 if failure occured
Input Value.: global, a pointer to data structure of global_t
Output Value: none
******************************************************************************/
int fb_draw(void)
{
	unsigned int x = 0, y = 0;
	unsigned int x_edge = 0, y_edge = 0;
	unsigned int isx_beyond_screen = 0;			//  if x axis display is beyond the screen area.
	//unsigned int isy_beyond_screen;			//  if y axis display is beyond the screen area.
	unsigned int x_excess = 0;					// x axis pixel beynod the screen area
	//unsigned int y_excess = 0;				// y axis pixel beynod the screen area
	unsigned int p = 0;
	unsigned short c16 = 0;
	unsigned int c32 = 0;

	unsigned int i = 0, j = 0;	
	unsigned short r = 0, g = 0, b = 0, pixel16 = 0;
	
	// this time, we reserve the display greater than our lcd resolution
	if ((global.pic_info.wdata > global.fb_info.wfb) 
		|| (global.pic_info.hdata > global.fb_info.hfb))
	{
		fprintf(stderr, "ERROR: data resolution greater than fb\n");
		return -1;
	}

	if (global.x0 + global.pic_info.wdata > global.fb_info.wfb)
	{
		isx_beyond_screen = 1;		// x axis picture is beyond the screen 
		x_edge = global.fb_info.wfb;
		x_excess = global.x0 + global.pic_info.wdata - global.fb_info.wfb;
	}
	else
	{
		isx_beyond_screen = 0;		
		x_edge = global.x0 + global.pic_info.wdata;
	}

	y_edge = (global.y0 + global.pic_info.hdata > global.fb_info.hfb)
		? (global.fb_info.hfb) : (global.y0 + global.pic_info.hdata);

	switch (global.fb_info.bpp)
	{
		case BPP_8:
			printf("BPP8 is to be support\n");
			break;
			
		case BPP_16:
			DBG("fb bpp = 16\n");
			// if the picture bpp is not bpp16, convert it to bpp16 first
			switch (global.pic_info.bpp_picture)
			{
				case BPP_8:
					printf("BPP8, to be supported.\n");
					break;
						
				case BPP_16:
					printf("BPP16, to be supported.\n");
					break;
						
				case BPP_24:		// case BPP24, turn rgb888 to rgb565		
					DBG("picture bpp = 24, fb bpp = 16\n");
								
					for (i=0; i<global.pic_info.len/3; i++)
					{			
						b = (*(global.pic_info.pdata + i * 3 + 0) >> 3) & 0x001F;
						g = ((*(global.pic_info.pdata + i * 3 + 1) >> 2) << 5 ) & 0x07E0;
						r = ((*(global.pic_info.pdata + i * 3 + 2) >> 3) << 11) & 0xF800;
						pixel16 = (unsigned short) (r | g | b);
			
						global.pic_info.pdata[j+0] = (pixel16 >> 0) & 0xff;
						global.pic_info.pdata[j+1] = (pixel16 >> 8) & 0xff;
						j += 2;
					}
					global.pic_info.len = (global.pic_info.len * 2) / 3;
					break;

				case BPP_32:
					DBG("picture bpp = 32, to be supported.\n");
					break;
						
				default:
					printf("picture bpp: %d, not supported yet.\n", global.pic_info.bpp_picture);
					break;
			}

			// then, display the bpp16 picture.
			for (y=global.y0; y<y_edge; y++)
			{
				for (x=global.x0; x<x_edge; x++) 
				{
					c16 = global.pic_info.pdata[p+0] | (global.pic_info.pdata[p+1]<<8);
					*(global.fb_info.pfb.pfb16 + y * global.fb_info.wfb + x) = c16;
					p += 2;					
				}
				if (isx_beyond_screen)
				{
					p += 2 * x_excess;
				}
			}	
			break;
			
		case BPP_24:
			printf("BPP24 is to be support\n");
			break;
			
		case BPP_32:
			DBG("fb bpp = 32\n");
			
			if (global.pic_info.bpp_picture < 24)
			{
				fprintf(stderr, "system framebuffer is 32 bpp, but the picture is %d bpp.\n", global.pic_info.bpp_picture);
				return -1;
			}
	
			for (y=global.y0; y<y_edge; y++)
			{
				for (x=global.x0; x<x_edge; x++) 
				{
					c32 = global.pic_info.pdata[p+0] | (global.pic_info.pdata[p+1]<<8)
									 | (global.pic_info.pdata[p+2]<<16);
					*(global.fb_info.pfb.pfb32 + y * global.fb_info.wfb + x) = c32;
					p += 3;
				}
				if (isx_beyond_screen)
				{
					p += 3 * x_excess;
				}
			}
			break;
			
		default:
			break;
	}
	
	return 0;
}

static unsigned short rgb888torgb565(unsigned int color)
{
	unsigned short  r = (((color >> 0) & 0xff) >> 3) & 0x001F;
	unsigned short  g = (((color >> 8) & 0xff >> 2) << 5) & 0x07E0;
	unsigned short  b = (((color >> 16) & 0xff >> 3) << 11) & 0xF800;

	return (unsigned short) (r | g | b);
}


int fb_drawback(unsigned int color)
{
	unsigned int x;
	unsigned char c[3];
	
	if ((global.pic_info.wdata > global.fb_info.wfb) 
		|| (global.pic_info.hdata > global.fb_info.hfb))
	{
		fprintf(stderr, "ERROR: data resolution greater than fb\n");
		return -1;
	}
	
	switch (global.fb_info.bpp)
	{
		case BPP_8:
			printf("BPP8 is to be support\n");
			break;
		case BPP_16:			
			for (x=0; x<global.fb_info.sizefb/2; x+=1)
			{
				*(global.fb_info.pfb.pfb16 + x) = rgb888torgb565(color);
			}
			break;
		case BPP_24:	// 尚未调试ok
			c[2] = (color >> 16) & 0xff;
			c[1] = (color >> 8) & 0xff;
			c[0] = (color >> 0) & 0xff;
			for (x=0; x<global.fb_info.sizefb/3; x+=3)
			{
				memmove(global.fb_info.pfb.pfb8 + x, c, 3);		
			}
			break;
		case BPP_32:
			for (x=0; x<global.fb_info.sizefb/4; x+=1)
			{
				*(global.fb_info.pfb.pfb32 + x) = color;
			}
			break;
		default:
			break;
	}

	return 0;
}

int draw_test(void)
{
	fb_drawback(0x191970);		// MidnightBlue
	sleep(3);
	
	fb_drawback(0x008B00);		// Green
	sleep(3);
	
	fb_drawback(0xC71585);		// MediumVioletRed
	sleep(3);
	
	return 0;
}

int fb_init(void)
{
	int ret = 0;
	
	ret = fb_open();
	if (ret < 0)
		return ret;
		
	ret = fb_getinfo();
	if (ret < 0)
		return ret;
		
	//set_bpp(16);	
	ret = fb_mapdev();

	return ret;
}

void fb_close(void)
{
	munmap(global.fb_info.pfb.pfb32, global.fb_info.sizefb);
	close(global.fb_info.fbfd);
}

在这里插入图片描述

/*
 *  dpicture/display/fb_bmp.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of fb_bmp.c:  Aston Zhu <AstonZhu.0@gmail.com>
 *
 * 	This file is used for display bmp file. 
 */

 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

#include <bmp.h>
#include <fb.h>
#include <config.h>
#include <dpicture.h>


/******** global variables *************/
static bitmap_fileheader_t g_fileheader;			// file header, 14 bytes
static bitmap_infoheader_t g_infoheader;			// info header, 40 bytes


/******************************************************************************
Description.: simple tool to convert char array to unsigned long in binary level 
Parameter	: string, char array to be converted
			  length, length(byte) of the char to be converted
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: string, length
Output Value: none
******************************************************************************/
static unsigned long chartolong(char *string, int length)
{
	unsigned long number;

	if (length <= 4)
	{
		memset(&number, 0x00, sizeof(long));
		memcpy(&number, string, length);
	}

	return (number);
}

/******************************************************************************
Description.: open bmp file and save useful information to global 
			  variable g_bmpinfo
Parameter	: pathbmp, the bmp file path to be opened
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: string of the bmp file path
Output Value: none
******************************************************************************/
static int fb_open_bmp(const char *pathbmp)
{
	FILE *fp = NULL;
	size_t rc = 0;
	int y = 0;
	int line_length = 0;

	/* open bmp file */
	fp = fopen(pathbmp, "rb");
	if (fp == NULL)
	{
		return -1;
	}

	/* read the bmp header */
	rc = fread(&g_fileheader, sizeof(bitmap_fileheader_t), 1, fp);
	if (rc != 1)		// pay attention to the return value of fread
	{
		fprintf(stderr, "read bmp file header error!\n");
		fclose(fp);
		return -1;
	}
	
	/* verify that it's a valid bmp file */
	if (memcmp(g_fileheader.cftype, "BM", 2) != 0)
	{
		fprintf(stderr, "it's not a BMP file!\n");
		fclose(fp);
		return -1;
	}
	
	/* read the bmp info header */
	rc = fread((char *)&g_infoheader, sizeof(bitmap_infoheader_t), 1, fp);
	if (rc != 1)
	{
		fprintf(stderr, "read bmp info header error!\n");
		fclose(fp);
		return -1;
	}

	global.pic_info.wdata 			= chartolong(g_infoheader.ciwidth, 4);		// width in pixel
	global.pic_info.hdata 			= chartolong(g_infoheader.ciheight, 4);		// height in pixel
	global.pic_info.bpp_picture 	= chartolong(g_infoheader.cibitcount, 2);	// bpp of the picture
	global.pic_info.len				= global.pic_info.wdata * global.pic_info.hdata 
		* (global.pic_info.bpp_picture / 8);										// len in bytes
	DBG("picture info: %u * %u, %ubpp.\n", global.pic_info.wdata, 
		global.pic_info.hdata, global.pic_info.bpp_picture);

	// fseek to the start of the actual bmp data
	fseek(fp, (int)chartolong(g_fileheader.cfoffbits, 4), SEEK_SET);

	line_length = global.pic_info.wdata * global.pic_info.bpp_picture / 8;

	for (y=global.pic_info.hdata - 1; y>=0; y--)
	{
		rc = fread(global.pic_info.pdata + y * line_length, sizeof(char), line_length, fp);
		if (rc != line_length)
		{
			fprintf(stderr, "read bmp image data error!\n");
			fclose(fp);
			return -EIO;
		}
	}
/*
	// read bmp image data to memory we alloc above
	rc = fread(global.pic_info.pdata, sizeof(char), global.pic_info.len, fp);
	if (rc != global.pic_info.len)
	{
		fprintf(stderr, "read bmp image data error!\n");
		fclose(fp);
		return -EIO;
	}
*/	

	return 0;
}


/******************************************************************************
Description.: function to draw bmp file on fb.
Parameter	: pathbmp, the bmp file path to be display
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: string of the bmp file path
Output Value: none
******************************************************************************/
int draw_bmp(const char * pathbmp)
{
	int ret;
	
	ret = fb_open_bmp(pathbmp);
	if (ret < 0)
		return ret;
	
	ret = fb_draw();
	

	return ret;
}


在这里插入图片描述

/*
 *  dpicture/display/fb_jpeg.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of fb_jpeg.c:  Aston Zhu <AstonZhu.0@gmail.com>
 *
 * 	This file is used for display jpg file. 
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <jpeglib.h>
#include <jerror.h>

#include <fb.h>
#include <config.h>
#include <dpicture.h>


/******************************************************************************
Description.: decode jpg file to bit map data.
Parameter	: jpg, file handler to jpg file to be decoded
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: jpg file handler
Output Value: none
******************************************************************************/
static int fb_decode_jpg(FILE *jpg)
{
	unsigned char *buffer = NULL;
	unsigned int nbytes = 0;
	unsigned int bytes_per_line = 0;
	unsigned char *p;
	int i = 0;
	//unsigned char tmp = 0;
	
    /*
     * declaration for jpeg decompression
     */
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

	/*
	* init jpeg decompress object error handler
	*/
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);
	/*
	 * bind jpeg decompress object to infile
	*/
	jpeg_stdio_src(&cinfo, jpg);
	/*
	* read jpeg header
	*/
	jpeg_read_header(&cinfo, TRUE);
	
	/*
	* decompress process.
	* note: after jpeg_start_decompress() is called
	* the dimension infomation will be known,
	* so allocate memory buffer for scanline immediately
	*/
	jpeg_start_decompress(&cinfo);	
	//fprintf(stderr, "output_width = %d\n, output_height = %d\n", 
	//	cinfo.output_width, cinfo.output_height);
	
	global.pic_info.bpp_picture = cinfo.output_components * 8;
	global.pic_info.wdata = cinfo.output_width;
	global.pic_info.hdata = cinfo.output_height;
	global.pic_info.len = cinfo.output_width * cinfo.output_height * cinfo.output_components;
	bytes_per_line = cinfo.output_width * cinfo.output_components;
	
	DBG("cinfo.output_width  = %d, cinfo.output_components = %d\n", 
		cinfo.output_width, cinfo.output_components);
	
	buffer = (unsigned char *)malloc(bytes_per_line);

	// start decode one line by another
	nbytes = 0;
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo, &buffer, 1);

		p = global.pic_info.pdata + nbytes;
		for (i=0; i<cinfo.output_width; i++)
		{
			*(p + 3 * i + 0) = buffer[3 * i + 2];
			*(p + 3 * i + 1) = buffer[3 * i + 1];
			*(p + 3 * i + 2) = buffer[3 * i + 0];
		}
		
		nbytes += bytes_per_line;	
	}

	/*
	* finish decompress, destroy decompress object
	*/
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	/*
	* release memory buffer
	*/
	free(buffer);
	
	// close the jpg file we opened before
	fclose(jpg);		

    return (0);
}

/******************************************************************************
Description.: function to open jpg file.
Parameter	: pathjpg, the jpg file path to be opened
			  global, a pointer to data structure of global_t
Return Value: return file handler if successfully, NULL if error occured.
Input Value.: string of the jpg file path
Output Value: none
******************************************************************************/
static FILE * fb_open_jpg(const char * pathjpg)
{
	FILE *fp = NULL;
	
	/* open jpg file */
	fp = fopen(pathjpg, "rb");

	return fp;
}


/******************************************************************************
Description.: function to draw jpg file on fb.
Parameter	: pathjpg, the jpg file path to be display
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: string of the jpg file path
Output Value: none
******************************************************************************/
int draw_jpg(const char * pathjpg)
{
	FILE *fp = NULL;
	int ret = 0;
	
	// open jpg file
	fp = fb_open_jpg(pathjpg);
	if (NULL == fp)
	{
		fprintf(stderr, "fail to open jpg file: %s.\n", pathjpg);
		return -EIO;
	}
	// decode jpg file to bmp data
	ret = fb_decode_jpg(fp);
	if (ret < 0)
		return ret;

	// display 
	ret = fb_draw();
	
	
	return ret;
}

在这里插入图片描述

/*
 *  dpicture/display/fb_png.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of fb_png.c:  Aston Zhu <AstonZhu.0@gmail.com>
 *
 * 	This file is used for display png file. 
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <png.h>
#include <pngstruct.h>
#include <pnginfo.h>

#include <fb.h>
#include <config.h>
#include <dpicture.h>


/******************************************************************************
Description.: decode png file to bit map data.
Parameter	: png, file handler to png file to be decoded
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: png file handler
Output Value: none
******************************************************************************/
static int fb_decode_png(FILE *png)
{
	int i = 0, j = 0;
	
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  	// check pointer
  	if (png_ptr == 0)
  	{
   		fclose(png);
   		return -1;
  	}
	
  	// create info struct
  	png_infop info_ptr = png_create_info_struct(png_ptr);
  	// check pointer
  	if (info_ptr == 0)
  	{
   		png_destroy_read_struct(&png_ptr, 0, 0);
   		fclose(png);
   		return -1;
  	}
	
  	// set error handling
  	if (setjmp(png_jmpbuf(png_ptr)))
  	{
   		png_destroy_read_struct(&png_ptr, &info_ptr, 0);
   		fclose(png);
   		return -1;
  	}
  	// I/O initialization using standard C streams
  	png_init_io(png_ptr, png);
  
  	// read entire image , ignore alpha channel,如果你要使用alpha通道,请把PNG_TRANSFORM_STRIP_ALPHA去掉
  	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);
	/*
	  PNG_TRANSFORM_EXPAND有下边几个处理:
	  1.Expand paletted colors into true RGB triplets
	  2.Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
	  3.Expand paletted or RGB images with transparency to full alpha channels so the data will be available 
	    as RGBA quartets。
	  PNG_TRANSFORM_STRIP_ALPHA:Strip alpha bytes from the input data without combining withthe background
	*/
 	int color_type = info_ptr->color_type;
	DBG("color_type = %d\n", color_type);

	global.pic_info.wdata = info_ptr->width;
	global.pic_info.hdata = info_ptr->height;
	global.pic_info.bpp_picture = info_ptr->pixel_depth;
	DBG("width = %u, height = %u, bpp = %u\n", global.pic_info.wdata,
		global.pic_info.hdata, global.pic_info.bpp_picture);

  	png_bytep* row_pointers = png_get_rows(png_ptr,info_ptr);
  	int pos = 0;
	
  	if(color_type == PNG_COLOR_TYPE_GRAY)
  	{// gray-scale image
   		for(i=0; i<global.pic_info.hdata; i++)
   		{
    		for(j=0; j<global.pic_info.wdata; j+=1)
    		{
     			//m_8bit[pos++] = row_pointers[i][j];
     			global.pic_info.pdata[pos++] = row_pointers[i][j];
    		}
   		}
		global.pic_info.len = global.pic_info.wdata * global.pic_info.hdata;
		DBG("gray-scale image handled ok.\n");
  	}
  	else
  	{// true color image
   		for(i=0; i<global.pic_info.hdata; i++)
   		{
    		for(j=0; j<3*global.pic_info.wdata; j+=3)
    		{
     			//m_bgra[pos++] = row_pointers[i][j+2];	// blue
     			//m_bgra[pos++] = row_pointers[i][j+1];	// green
     			//m_bgra[pos++] = row_pointers[i][j];		// red
     			global.pic_info.pdata[pos++] = row_pointers[i][j+2];	// blue
				global.pic_info.pdata[pos++] = row_pointers[i][j+1];	// green
				global.pic_info.pdata[pos++] = row_pointers[i][j];		// red
			}
   		}
		global.pic_info.len = global.pic_info.wdata * global.pic_info.hdata * 3;
		DBG("true color image handled ok.\n");
  	}
  	// free memory
  	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  	// close file
  	fclose(png);

	return 0;
}


/******************************************************************************
Description.: function to open png file.
Parameter	: pathpng, the png file path to be opened
			  global, a pointer to data structure of global_t
Return Value: return file handler if successfully, NULL if error occured.
Input Value.: string of the png file path
Output Value: none
******************************************************************************/
static FILE * fb_open_png(const char * pathpng)
{
	FILE *fp = NULL;
	
	/* open png file */
	fp = fopen(pathpng, "rb");

	return fp;
}


/******************************************************************************
Description.: function to draw png file on fb.
Parameter	: pathpng, the png file path to be display
			  global, a pointer to data structure of global_t
Return Value: return 0 if successfully, relevant errno if failure occured
Input Value.: string of the png file path
Output Value: none
******************************************************************************/
int draw_png(const char *pathpng)
{
	FILE *fp = NULL;
	int ret = 0;
	
	// open jpg file
	fp = fb_open_png(pathpng);
	if (NULL == fp)
	{
		fprintf(stderr, "fail to open png file: %s.\n", pathpng);
		return -EIO;
	}
	// decode png file to bmp data
	ret = fb_decode_png(fp);
	if (ret < 0)
		return ret;

	// display 
	ret = fb_draw();
	
	
	return ret;
}

obj-y += fb.o
obj-y += fb_bmp.o
obj-y += fb_jpeg.o
obj-y += fb_png.o

在这里插入图片描述
在这里插入图片描述

/*
 *  dpicture/include/bmp.h
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of bmp.h:  Aston Zhu <AstonZhu.0@gmail.com> 
 */

#ifndef __BMP_H__
#define __BMP_H__

#include <fb.h>


// bitmap file header, totally 14 bytes
typedef struct
{
	char cftype[2]; 	/* 文件类型, 必须为 "BM" (0x424D)*/
	char cfsize[4]; 	/* 文件的大小(字节) */
	char cfreserved[4]; /* 保留, 必须为 0 */
	char cfoffbits[4]; 	/* 位图阵列相对于文件头的偏移量(字节)*/
}__attribute__((packed)) bitmap_fileheader_t; /* 文件头结构 */

//bitmap info header, totally 40 bytes
typedef struct
{
	char cisize[4]; 			/* size of BITMAPINFOHEADER */
	char ciwidth[4]; 			/* 位图宽度(像素) */
	char ciheight[4]; 			/* 位图高度(像素) */
	char ciplanes[2]; 			/* 目标设备的位平面数, 必须置为1 */
	char cibitcount[2]; 		/* 每个像素的位数, 1,4,8或24 */
	char cicompress[4]; 		/* 位图阵列的压缩方法,0=不压缩 */
	char cisizeimage[4]; 		/* 图像大小(字节) */
	char cixPelspermeter[4];	/* 目标设备水平每米像素个数 */
	char ciYpelsperpeter[4];	/* 目标设备垂直每米像素个数 */
	char ciclrused[4]; 			/* 位图实际使用的颜色表的颜色数 */
	char ciclrimportant[4]; 	/* 重要颜色索引的个数 */
}__attribute__((packed)) bitmap_infoheader_t; /* 位图信息头结构 */



/***** function prototype ********/
int draw_bmp(const char * pathbmp);




#endif

config.h

#ifndef __CONFIG_H__
#define __CONFIG_H__

#include <syslog.h>
#include <signal.h>

#define	FB_DEV			"/dev/fb0" 				// fb device in SQ210
#define TS_MT_DEV 		"/dev/input/event1"		// touch screen device in SQ210




#define DEBUG
// debug and log related macros
#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif

#define LOG(...) { char _bf[1024] = {0}; snprintf(_bf, sizeof(_bf)-1, __VA_ARGS__); fprintf(stderr, "%s", _bf); syslog(LOG_INFO, "%s", _bf); }

dpicture.h

/*
 *  dpicture/include/dpicture.h
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of dpicture.h:  Aston Zhu <AstonZhu.0@gmail.com> 
 *
 *	header of some global macros and structures.
 */
#include <fb.h>

#ifndef __DPICTURE_H__
#define __DPICTURE_H__


/******** macro and structure definition ***********/

#define PATH_LENGTH			256		// max length of the file path name
#define MAX_IMAGES			100		// maximum quantity of the pictures

#define MAX_RES_WIDTH		1920	// the maximum x axis resolution we support
#define MAX_RES_HEIGHT		1280	// the maximum y axis resolution we support
#define MAX_BPP_IN_BYTE		4		// the maxmum bpp of picture we support


typedef enum _e_image_type
{
	IMAGE_BMP,						// bmp picture
	IMAGE_JPG,						// jpg picture
	IMAGE_PNG,						// png picture
	IMAGE_GIF,						// gif picture
}e_image_type;

typedef struct 
{
	e_image_type type;				// expression format of the picture
	char pathname[PATH_LENGTH];	// full path and name of the picture
}image_info_t;


/* voriable prototype declairation */
image_info_t images[MAX_IMAGES];	// defined in dpicture/picture_manager.c
unsigned int cnt_image;				// defined in dpicture/picture_manager.c

global_t global;					// defined in dpicture/dpicture.c



/* function prototype declairation */
int paging_init(void);
int scan_dir(const char *path);
void draw_picture(unsigned int i);

int draw_png(const char *pathpng);
int draw_jpg(const char * pathjpg);








#endif

fb.h

/*
 *  dpicture/include/fb.h
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of fb.h:  Aston Zhu <AstonZhu.0@gmail.com> 
 */

#ifndef __FB_H__
#define __FB_H__
 

// enum of bits_per_pixel we supported
typedef enum _e_bpp
{
	BPP_8 = 8,
	BPP_16 = 16,
	BPP_24 = 24,
	BPP_32 = 32,
}e_bpp; 
 
union u_pfb
{
	unsigned char 	*pfb8;		// pointer to fb when BPP_8
	unsigned short 	*pfb16;		// pointer to fb when BPP_16
	unsigned int 	*pfb32;		// pointer to fb when BPP_32
}; 

struct fb_info
{
	int fbfd;					// handler of framebuffer
	union u_pfb pfb;			// pointer to fb
	unsigned int wfb;			// width of framebuffer
	unsigned int hfb;			// height of framebuffer
	unsigned int sizefb;		// framebuffer size in byte
	e_bpp bpp;					// bit per pixel
};

struct picture
{	
	unsigned int bpp_picture;		// bpp of the picture
	unsigned int wdata;				// width of the picture
	unsigned int hdata;				// height of the picture
	unsigned int len;				// length of picture data
	unsigned char *pdata;			// picture data
};

// data structure used for describe fb
struct _global
{
	unsigned int x0;			// x axis of start point of display(top left)
	unsigned int y0;			// y axis of start point of display(top left)
	struct fb_info fb_info;		// infomation of framebuffer
	struct picture pic_info;	// information of the picture
};

typedef struct _global global_t;


 /******** function prototype ************/
int fb_init();
void fb_close();
int fb_drawback(unsigned int color);
int draw_test(); 
int fb_draw(); 


#endif

ui.h

/*
 *  dpicture/include/ui.h
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of ui.h:  Aston Zhu <AstonZhu.0@gmail.com> 
 *
 *	header of ui related.
 */

#ifndef __UI_H__
#define __UI_H__


#define MAX_TOUCH_POINTS		5	// we support 5 points maximum

#define RIGHT_THRRESHOLD		600
#define LEFT_THRESHOLD			200



// multi-touch touch screen report event
typedef struct ts_mt_event_t
{
	unsigned int touch_points;		// actual touch points
	unsigned int  xpoint[MAX_TOUCH_POINTS];
	unsigned int  ypoint[MAX_TOUCH_POINTS];
}ts_mt_event;

// single-touch touch screen report event
typedef struct
{
	unsigned int x;				// 
	unsigned int y;
	unsigned int value;			// 1 for push down or 0 for pull up
}ts_st_event;

// key press report event
typedef struct
{
	unsigned int key_no;		// number of key 
	unsigned int value;			// 1 for push down or 0 for pull up
}key_event;



#endif

在这里插入图片描述
在这里插入图片描述

input_touch.c

/*
 *  dpicture/paging.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of paging.c:  Aston Zhu <AstonZhu.0@gmail.com> 
 *
 *	indepdent thread that receive signal from input dev, then control 
 *	the paging of the picture.
 */

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <linux/input.h>

#include <dpicture.h>
#include <config.h>
#include <ui.h>
 

//extern unsigned int input_stop;				// defined in dpicture/main.c
//extern unsigned int cnt_image;				// defined in dpicture/picture_manager.c


static pthread_t thread_input;
static char devname[] = TS_MT_DEV;
static unsigned int cur_disp = 0;


void show_next(void)
{
	if (cur_disp++ >= cnt_image)
	{
		cur_disp = 0;
	}
	
	draw_picture(cur_disp);
}


void show_prev(void)
{
	if (cur_disp-- <= 0)
	{
		cur_disp = cnt_image - 1;
	}
	
	draw_picture(cur_disp);
}


void do_ts_mt_push_down(unsigned int x, unsigned int y)
{
	DBG("x = %u, 	y = %u.	cur_disp = %d.\n", x, y, cur_disp);
	
	if (x > RIGHT_THRRESHOLD)
	{
		show_next();
	}
	if (x < LEFT_THRESHOLD)
	{
		show_prev();
	}
}




int ts_mt_process(void)
{
	int fd = 0;
	int ret = 0;
	
	int tempx = 0, tempy = 0;
	unsigned int valid_down = 1;			// 1 for new valid push down, ignore report if 0
	unsigned int step = 0;
	
	fd = open(devname, O_RDONLY);
	if (fd == -1)
	{
		fprintf(stderr, "open device file %s error.\n", devname);
		return -EIO;
	}
	
	struct input_event *pevent = NULL;
	pevent = (struct input_event *)malloc(sizeof(struct input_event));
	if (NULL == pevent)
	{
		fprintf(stderr, "fail to malloc.\n");
		return -ENOMEM;
	}
	
	while ((ret = read(fd, pevent, sizeof(struct input_event))) != 0)
	{
		switch (pevent->type)
		{
			case EV_SYN:
				switch (pevent->code)
				{
					case SYN_REPORT:
						{
							step++;
							if (step == 1)
							{
								// 
								if (valid_down)
								{
									// 
									do_ts_mt_push_down(tempx, tempy);
									valid_down = 0;
								}
							}
							if (step == 2)
							{
								valid_down = 1;
							}
						}
						break;
						
					case SYN_MT_REPORT:
						{
							step = 0;
						}
						break;
						
					default:
						break;
				}
			break;
				
			case EV_ABS:
				switch (pevent->code)
				{
					case ABS_MT_TOUCH_MAJOR:
						{
							// not use
						}
						break;
						
					case ABS_MT_WIDTH_MAJOR:
						{
							// not use
						}
						break;
						
					case ABS_MT_POSITION_X:
						{
							tempx = pevent->value;
						}
						break;
						
					case ABS_MT_POSITION_Y:
						{
							tempy = pevent->value;
						}
						break;
						
					default:
						break;
				}
			break;
			
			#if 0
				//printf("event type: EV_ABS, code = 0x%x\n", pevent->code);
				if (pevent->code == 0)
					//printf("code = ABS_X, value = %d.\n", pevent->value);
				if (pevent->code == 1)
					//printf("code = ABS_Y, value = %d.\n", pevent->value);
				if (pevent->code == 2)
					//printf("code = ABS_Z, value = %d.\n", pevent->value);
				if (pevent->code == 48)
					printf("code = ABS_MT_TOUCH_MAJOR, value = %d.\n", pevent->value);
				//if (pevent->code == 49)
				//	printf("code = ABS_MT_TOUCH_MINOR, value = %d.\n", pevent->value);
				if (pevent->code == 50)
					printf("code = ABS_MT_WIDTH_MAJOR, value = %d.\n", pevent->value);
				//if (pevent->code == 51)
				//	printf("code = ABS_MT_WIDTH_MINOR, value = %d.\n", pevent->value);
				//if (pevent->code == 52)
				//	printf("code = ABS_MT_ORIENTATION, value = %d.\n", pevent->value);
				if (pevent->code == 53)
					printf("code = ABS_MT_POSITION_X, value = %d.\n", pevent->value);
				if (pevent->code == 54)
					printf("code = ABS_MT_POSITION_Y, value = %d.\n", pevent->value);
			#endif			
				
			default:
				printf("unexpected event type: %hu.\n", pevent->type);
				break;
		}
		
	}
	
	return 0;
}


void *paging_routine(void *arg)
{
	ts_mt_process();
	
	return NULL;
}


int paging_init(void)
{
	int ret = 0;
	
	ret = pthread_create(&thread_input, NULL, paging_routine, NULL);
	if (ret != 0)
	{
		fprintf(stderr, "create paging_toutine thread error.\n");
		return -1;
	}

	
	ret = pthread_detach(thread_input);
	if (ret != 0)
	{
		fprintf(stderr, "detach paging_toutine thread error.\n");
		return -1;
	}

	return 0;
}

触摸屏上报事件,3是触摸屏
在这里插入图片描述

picture_manerger.c

/*
 *  dpicture/picture_manager.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of picture_manager.c:  Aston Zhu <AstonZhu.0@gmail.com>
 *
 * 	This file is used to manage the picture file in ./resource directory
 * 	and the sub-dirs. We store our picture there, and they may be bmp\
 *	jpg\png\gif and other image format. We should decode the pictures accordingly
 *	so, we analize the directory and identify the image format here.
 */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>



#include <config.h>
#include <dpicture.h>



/********** global variables definition ***********/
image_info_t images[MAX_IMAGES];
unsigned int cnt_image;




/******************************************************************************
Description.: check that if file is a valid bmp format file.
Parameter	: path, pathname of the file to be check.
Return Value: return 0 if is bmp, if it's not bmp return 1; 
			  if error return -1 
Input Value.: pathname of the file
Output Value: none
******************************************************************************/
static int is_bmp(const char *path)
{
	char buf[2] = {0};
	FILE *fp = NULL;
	int rc = 0;
	
	fp = fopen(path, "rb");
	if (NULL == fp)
	{
		fprintf(stderr, "fail to open file %s.\n", path);
		return -EIO;
	}

	rc = fread(buf, 1, 2, fp);
	if (rc != 2)		// pay attention to the return value of fread
	{
		fprintf(stderr, "in is_bmp, read start 2 bit error!\n");
		fclose(fp);
		return -EIO;
	}

	if (!strncmp(buf, "BM", 2))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

/******************************************************************************
Description.: check that if file is a valid jpg format file.
Parameter	: path, pathname of the file to be check.
Return Value: return 0 if is jpg, if it's not jpg return 1; 
			  if error return -1 
Input Value.: pathname of the file
Output Value: none
******************************************************************************/
static int is_jpg(const char *path)
{
	char buf[2] = {0};
	FILE *fp = NULL;
	int rc = 0;
	
	fp = fopen(path, "rb");
	if (NULL == fp)
	{
		fprintf(stderr, "fail to open file %s.\n", path);
		return -EIO;
	}

	rc = fread(buf, 1, 2, fp);
	if (rc != 2)		// pay attention to the return value of fread
	{
		fprintf(stderr, "in is_jpg, read start 2 bit error!\n");
		fclose(fp);
		return -EIO;
	}

	if ((buf[0] == 0xff) && (buf[1] == 0xD8))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}


/******************************************************************************
Description.: check that if file is a valid png format file.
Parameter	: path, pathname of the file to be check.
Return Value: return 0 if is png, if it's not png return 1; 
			  if error return -1 
Input Value.: pathname of the file
Output Value: none
******************************************************************************/
static int is_png(const char *path)
{
	char buf[4] = {0};
	FILE *fp = NULL;
	int rc = 0;
	
	fp = fopen(path, "rb");
	if (NULL == fp)
	{
		fprintf(stderr, "in is_png, fail to open file %s.\n", path);
		return -EIO;
	}

	rc = fread(buf, 1, 4, fp);
	if (rc != 4)		// pay attention to the return value of fread
	{
		fprintf(stderr, "read start 2 bit error!\n");
		fclose(fp);
		return -EIO;
	}

	if (!strncmp(buf+1, "PNG", 3))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}



/******************************************************************************
Description.: recursivly scan a directory to find all pictures of bmp\jpg\
			  \png, and save their information to global array images.
Parameter	: path, pathname of the directory to be scaned.
Return Value: return 0 if success, return -1 if error occurs. 
Input Value.: pathname of the directory
Output Value: none
******************************************************************************/
int scan_dir(const char *path)
{
	char dirname[PATH_LENGTH];
	DIR *pdir = opendir(path);
	
	if (NULL == pdir)
	{
		fprintf(stderr, "opendir error.\n");
		return -1;
	}
	
	struct dirent *pdirent;
	while (NULL != (pdirent = readdir(pdir)))
	{
		DBG("success to readdir, and type = %d, file name is [%s]\n", pdirent->d_type, pdirent->d_name);
		// exclude . and ..
		if ((!strcmp(pdirent->d_name, ".")) || (!strcmp(pdirent->d_name, "..")))
		{
			continue;
		}
		// sub dirs
		if (pdirent->d_type == DT_DIR)
		{
		// we will support nested directory very soon		
			memset(dirname, 0, PATH_LENGTH);
			memcpy(dirname, path, strlen(path));
			strcat(dirname, "/");
			strcat(dirname, pdirent->d_name);
			scan_dir(dirname);			
		}
		// regular file 
		if (pdirent->d_type == DT_REG)
		//if (pdirent->d_type == DT_REG)
		{
			// regular file processed one by one
			memset(dirname, 0, PATH_LENGTH);
			memcpy(dirname, path, strlen(path));
			strcat(dirname, "/");
			strcat(dirname, pdirent->d_name);
			DBG("dirname = %s\n", dirname);
			if (!is_bmp(dirname))
			{
				//printf("%s is bmp.\n", dirname);
				memcpy(images[cnt_image].pathname, dirname, PATH_LENGTH);
				images[cnt_image].type = IMAGE_BMP;
				cnt_image++;
				continue;
			}
		
			if (!is_png(dirname))
			{
				//printf("%s is png.\n", dirname);
				memcpy(images[cnt_image].pathname, dirname, PATH_LENGTH);
				images[cnt_image].type = IMAGE_PNG;
				cnt_image++;
				continue;
			}
			if (!is_jpg(dirname))
			{
				//printf("%s is jpg.\n", dirname);
				memcpy(images[cnt_image].pathname, dirname, PATH_LENGTH);
				images[cnt_image].type = IMAGE_JPG;
				cnt_image++;
				continue;
			}
			
			DBG("%s is not a supported image format.\n", dirname);
		}

		if (pdirent->d_type == DT_UNKNOWN)
		{
			// unknown format file... 
			/* yes, this should appear here, but we find the function 
			readdir often make mistakes, so either the picture file or 
			the directory can be error parsing to DT_UNKNOWN
			*/
			memset(dirname, 0, PATH_LENGTH);
			memcpy(dirname, path, strlen(path));
			strcat(dirname, "/");
			strcat(dirname, pdirent->d_name);
			DBG("in DT_UNKONWN, dirname = %s\n", dirname);
			scan_dir(dirname);	
		}
	}
	DBG("after scan_dir, %u images totally.\n", cnt_image);
	int i = 0;
	for (i=0; i<cnt_image; i++)
	{
		DBG("%dst image = [%s], format is %d.\n", i+1, images[i].pathname, images[i].type);
	}
	
	return 0;
}

int my_scan_dir(const char *path)
{
	// 如果readdir读取type为NUMKNOWN,导致得到的图片数量为0,则再次读取
	do
	{
		scan_dir(path);
	}while(cnt_image == 0);
}

dpicture.c

/*
 *  dpicture/dpicture.c
 *
 *  Copyright (C) 2013  Aston Zhu
 *
 *  Simplified starting of main.c:  Aston Zhu <AstonZhu.0@gmail.com> 
 *
 *	entry and main function of the project.
 */

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>

#include <config.h>
#include <fb.h>
#include <bmp.h>				// for display bmp picture
#include <dpicture.h>


/* global switch to start or stop paging logic from input device */
unsigned int input_stop = 0;

/* global info */
global_t global;	


/* we saved picture data here */
static unsigned char picture_data[MAX_RES_WIDTH*MAX_RES_HEIGHT*MAX_BPP_IN_BYTE];

	

void draw_picture(unsigned int i)
{
	switch (images[i].type)
	{
		case IMAGE_BMP:
			DBG("display bmp: %s\n", images[i].pathname);
			draw_bmp((const char *)images[i].pathname);
			break;
			
		case IMAGE_PNG:
			DBG("display png: %s\n", images[i].pathname);
			draw_png((const char *)images[i].pathname);
			break;
			
		case IMAGE_JPG:
			DBG("display jpg: %s\n", images[i].pathname);
			draw_jpg((const char *)images[i].pathname);
			break;
			
		default:
			break;
	}

}





void close_handler(int sig)
{
	LOG("received <CTRL + C>, we will exit soon.");
	// add what we want to do when exit here
	input_stop = 1;					// stop the thread of paging
	fb_close();
	
	LOG("we will exit now.");
	closelog();
	exit(0);
}

int main(int argc, char **argv)
{

	openlog("dpicture", LOG_PID | LOG_CONS, LOG_USER);
	syslog(LOG_INFO, "starting application...");

	memset(&global, 0, sizeof(global_t));	
	// bonding static memory to global pointer
	global.pic_info.pdata = picture_data;

	fb_init();

	// do close_handler when user press <CTRL + C>
	if (signal(SIGINT, close_handler) == SIG_ERR)
	{
		LOG("bonding signal handler for SIGINT error.");
		closelog();
		exit(EXIT_FAILURE);
	}

	//scan_dir("pictures");
	my_scan_dir("pictures");
		
	
	//draw_test(&ginfo);			// draw background for test, bpp16 & bpp32 test ok
	// color value table: http://www.yanses.com/content/?288.html
	fb_drawback(0x000000);	// clear background to black

	// set the start point of draw region
	global.x0 = 0;
	global.y0 = 0;

#if 1
	paging_init();

	draw_jpg("resource/start_page.jpg");

	//while(1);
	while(1)
	{
		fprintf(stderr, "heartbeat...\n");
		sleep(1);
	}
#endif	

#if 0
	draw_bmp("resource/shortcut.bmp");
	//draw_jpg("resource/shortcut.JPG");
	//draw_png("resource/shortcut.PNG");
#endif		
	
	fb_close();

	return 0;
}

zhu makefile


CROSS_COMPILE = arm-linux-

AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump

export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP

CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include -I/opt/libdecode/include


LDFLAGS := -ljpeg -lpng -lz -lpthread -L/opt/libdecode/lib

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR

TARGET := dpicture


obj-y += dpicture.o picture_manager.o
obj-y += display/
obj-y += ui/

all : 
	make -C ./ -f $(TOPDIR)/Makefile.build
	$(CC) $(LDFLAGS) -o $(TARGET) built-in.o


clean:
	rm -f $(shell find -name "*.o")
	rm -f $(TARGET)

distclean:
	rm -f $(shell find -name "*.o")
	rm -f $(shell find -name "*.d")
	rm -f $(TARGET)
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值