本文主要探讨基于s5pv210实现图片解码显示项目。
项目概述:
硬件:s5pv210(已移植uboot,kernel,busybox,已搭建tftp,已挂在ntfs)
软件:ubuntu14(已搭建tftp,搭建ntfs)
项目功能:基于s5pv210实现对bmp,jpeg,png三种图片的解析和显示,并且支持点击触摸屏两侧实现图片翻页
项目文件架构:(文件具体功能可阅读RADEME(后面))
项目编译:
项目执行调试信息:
项目部分图片:
start.bmp:为起始页面信息,包含触摸翻页的触摸区域显示
项目图片依赖库移植:
jpeg库移植wget https://sourceforge.net/projects/libjpeg/files/libjpeg/6b/jpegsrc.v6b.tar.gz --no-check-certificatemkdir jpegtar -zxvf jpegsrc.v6b.tar.gz -C jpegapt-get install -y libtoolcd jpeg/jpeg-6bcp /usr/share/libtool/config/config.guess .
cp /usr/share/libtool/config/config.sub .mkdir -p /opt/lib_fb/include/mkdir -p /opt/lib_fb/lib/./configure --prefix=/opt/lib_fb --exec-prefix=/opt/lib_fb --enable-shared --enable-static -build=i386 -host=armvim MakefileCC = arm-linux-gcc
AR = arm-linux-ar rc
AR2= arm-linux-ranlibmake && make install-libzlib移植wget wget http://www.zlib.net/zlib-1.3.1.tar.gztar -zxvf zlib-1.3.1.tar.gzcd zlib-1.3.1export CC=arm-linux-gcc./configure -shared --prefix=/opt/lib_fbmake && make installpng库移植wget https://download.sourceforge.net/libpng/libpng-1.6.6.tar.gz --no-check-certificatecd libpng-1.6.6export LDFLAGS="-L/opt/lib_fb/lib"
export CFLAGS="-I/opt/lib_fb/include"
export CPPFLAGS="-I/opt/lib_fb/include"
./configure --host=arm-linux --enable-shared --enable-static --prefix=/opt/lib_fb
make && make installcp /opt/lib_fb/lib/ /root/rootfs/usr/lib -rdfcp /opt/lib_fb/include/ /root/rootfs/usr/include -rdf
项目代码:
README
概述:本程序为图片解析显示程序,支持点击屏幕图片翻页功能,该程序可对bmp,jpeg,png三种图片解析显示。程序包含image文件,include文件,display文件等其他文件。MakefileMakefile:顶层Makefile,顶层Makefile.build,子Makefile子Makefile:obj-y += file.o file.c编进程序obj-y += subdir/ subdir子目录下文件编进程序,"/"不可省略顶层Makefile:obj-y编进程序的文件、子目录定义工具链、编译参数、链接参数,用export导出变量顶层Makefile.build:把目录及子目录要编进程序的文件编译并打包为built-in.oMakefile使用:修改顶层Makefile工具链,编译选项、链接选项,编译文件及子目录(obj-y),TARGET为编译的程序名子Makefile:编译文件及子目录(obj-y)make 编译make clean 清除make distclean 彻底清除includeconfig.h 硬件参数,程序全局变量等init_list.h 链表初始化函数fb_bmp.h bmp图片函数fb.h framebuffer函数fb_jpeg.h jpeg图片函数fb_png.h png图片函数list.h 链表函数displayfb_bmp.c bmp图片程序fb_jpeg.c jpeg图片程序fb_png.c png图片程序fb.c framebuffer程序Makefile 编译子文件规则imagebmp bmp图片jpg jpeg图片png png图片start 起始页图片listinit_list.c 链表初始化程序list.c 链表程序Makefile 编译子文件规则main.c 主程序run.sh 程序执行脚本
run.sh
#!/bin/bash./main image
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)objdumpexport AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMPCFLAGS := -Wall -O2 -g -DDEBUG
CFLAGS += -I $(shell pwd)/include -I /opt/lib_fb/include/LDFLAGS := -ljpeg -lpng -lz -L /opt/lib_fb/lib/export CFLAGS LDFLAGSTOPDIR := $(shell pwd)
export TOPDIRTARGET := mainobj-y += main.o
obj-y += display/
obj-y += list/all : make -C ./ -f $(TOPDIR)/Makefile.build$(CC) $(LDFLAGS) -o $(TARGET) built-in.oclean: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)
Makefile.build
PHONY := __build
__build:obj-y :=
subdir-y :=include Makefile# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
# __subdir-y : c d
# subdir-y : c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)# c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)# a.o b.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)
endifPHONY += $(subdir-y)__build : $(subdir-y) built-in.o$(subdir-y):make -C $@ -f $(TOPDIR)/Makefile.buildbuilt-in.o : $(cur_objs) $(subdir_objs)$(LD) -r -o $@ $^dep_file = .$@.d%.o : %.c$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<.PHONY : $(PHONY)
main.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <string.h>
#include <unistd.h>#include "list.h"
#include "init_list.h"
#include "fb_bmp.h"
#include "fb_jpeg.h"
#include "fb_png.h"
#include "fb.h"int main(int argc,char *argv[])
{int fd = -1, ret = -1;struct input_event ev;pic *tmp;//打开触摸屏设备文件fd = open(X210_TOUCHSCREEN, O_RDONLY);if (fd < 0){perror("open");return -1;}//创建图片链表头节点head = create_node(start_page);tmp = head;//遍历image,填充图片节点信息insert_pic_link(argv[1]);init_pic_link(head);//初始化framebufferinit_fb();//显示起始页display_bmp(start_page);sleep(5);//监听触摸事件,并显示对应图片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)){if ((ev.value >= 0) && (ev.value < 200)){//显示上一页图片,打印图片路径tmp = prev_printf_link(head,tmp);debug("%s\n",tmp->pathname);(*tmp->display)(tmp->pathname);}else if ((ev.value > 800) && (ev.value <= 1024)){//显示上一页图片,打印图片路径tmp = next_printf_link(head,tmp);debug("%s\n",tmp->pathname);(*tmp->display)(tmp->pathname);}else{debug("posion : %d\n",ev.value);}}}close(fd);return 0;
}
include:
config.h
#ifndef __CONFIG_H__
#define __CONFIG_H__//图片类型
enum pic_type
{BMP,JPEG,PNG,UNKNOW
};//图片信息
typedef struct pic_info
{char pathname[256]; //图片路径enum pic_type type; //图片类型int (*display)(char *pathname); //图片显示struct pic_info *next;struct pic_info *prev;
} pic;//图片链表头
pic *head;//像素变量
unsigned int *pfb;//起始页
#define start_page "image/start/start.bmp"//图片存储
#define RGB_MAX_RESOLUTION (1920*1080)
#define RGB_BUF_SIZE (RGB_MAX_RESOLUTION*3)
unsigned char rgb_buf[RGB_BUF_SIZE];//显示器宽高
#define HIGH 600
#define WIDTH 1024//framebuffer 设备
#define FB_DEV "/dev/fb0"//触摸屏设备
#define X210_TOUCHSCREEN "/dev/input/event1"//颜色参数
#define WHITE 0xFFFFFFFF
#define BLACK 0x0#ifdef DEBUG
#define debug(...) \{ \fprintf(stderr, "[debug][%s:%s:%d] ", \__FILE__, __FUNCTION__, __LINE__); \fprintf(stderr, __VA_ARGS__); \}
#else
#define debug(...)
#endif#endif
fb.h
//初始化framebuffer
int init_fb();//初始化背景
int init_background();
fb_bmp.h
//bmp 头信息
typedef struct {unsigned char bmp_type_B; // BMP类型标志(必须为"BM")unsigned char bmp_type_M;unsigned int bmp_Size; // BMP文件大小unsigned short bmp_reserved1; // 保留字段1unsigned short bmp_reserved2; // 保留字段2unsigned int bmp_off_bits; // 从文件头到像素数据起始位置的偏移量
}__attribute__((packed)) bmp_head ;//bmp 所有信息
typedef struct {unsigned int bmp_size; // 结构体长度signed int bmp_width; // 图片宽度signed int bmp_height; // 图片高度unsigned short bmp_lanes; // 目标设备的平面数(通常为1)unsigned short bmp_bit_count; // 每个像素所需的位数unsigned int bmp_compression;// 压缩类型(0表示不压缩)unsigned int bmp_size_image; // 图像大小(对于未压缩的RGB格式,该值应为0)signed int bmp_x_pels_per_meter;// 水平分辨率(像素/米)signed int bmp_y_pels_per_meter;// 垂直分辨率(像素/米)unsigned int bmp_clor_used; // 调色板中使用的颜色索引数(若为0则使用全部颜色)unsigned int bmp_color_important;// 重要颜色索引数(若为0则都被认为是重要的)
} bmp_info;//判断是否为bmp,0 : 是, 1 : 不是
int is_bmp(char *pathname);//bmp显示
int display_bmp(char *pathname);
fb_jpeg.h
//判断是否为jpeg,0 : 是, 1 : 不是
int is_jpeg(char *pathname);//显示jpeg
int display_jpeg(char *pathname);
fb_png.h
//判断是否为png,0 : 是, 1 : 不是
int is_png(char *pathname);//显示png
int display_png(char *pathname);
list.h
#include "config.h"//创建节点
pic * create_node(const char *path_name);//插入尾节点
void insert_tail(pic *phead,pic *new);//返回当前节点的下一个节点
pic *next_printf_link(pic* head,pic *p);//返回当前节点的上一个节点
pic *prev_printf_link(pic* head,pic *p);
init_list.h
//遍历image中的图片,创建图片节点,并且填充图片路径
int insert_pic_link(char *pathname);//初始化节点中图片类型和图片显示函数
void init_pic_link(pic *head);
display:
Makefile
obj-y += fb.o
obj-y += fb_bmp.o
obj-y += fb_jpeg.o
obj-y += fb_png.o
fb_bmp.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#include "config.h"
#include "fb_bmp.h"int is_bmp(char *pathname)
{int fd;bmp_head head_info;fd = open(pathname,O_RDWR);if(fd == -1){perror("open");return 1;}read(fd,&head_info,sizeof(head_info));if(head_info.bmp_type_B != 'B' || head_info.bmp_type_M != 'M'){close(fd);return 1;}close(fd);return 0;
}int display_bmp(char *pathname)
{int fd = -1;int v_len = 0; int rgb_offset = 0;int cnt = 0;unsigned int i,j;unsigned int *tmp = pfb;bmp_info all_info;bmp_head head_info;fd = open(pathname,O_RDWR);if(fd == -1){perror("open");return 1;}debug("open %s success\n",pathname);read(fd,&head_info,sizeof(head_info));read(fd,&all_info,sizeof(all_info));debug("width : %d high : %d bpp : %d\n",all_info.bmp_width,all_info.bmp_height,all_info.bmp_bit_count);v_len = all_info.bmp_width * all_info.bmp_height * all_info.bmp_bit_count / 3;lseek(fd,head_info.bmp_off_bits,SEEK_SET);memset(rgb_buf,0,RGB_BUF_SIZE);read(fd,rgb_buf,v_len);if(all_info.bmp_bit_count != 32 && all_info.bmp_bit_count != 24){printf("%d bpp is not support\n",all_info.bmp_bit_count);close(fd);return -1;}for(i = 0;i < all_info.bmp_height;i++){for(j = 0;j < all_info.bmp_width;j++){cnt = WIDTH * i + (1024 - j);*(tmp + cnt) = ((rgb_buf[rgb_offset + 0] << 0) | (rgb_buf[rgb_offset + 1] << 8) | (rgb_buf[rgb_offset + 2] << 16));rgb_offset += 3;}}return 0;
}
fb_jpeg.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "config.h"#include <jpeglib.h>
#include <jerror.h>struct my_error_mgr
{struct jpeg_error_mgr pub; /* "public" fields */
};typedef struct my_error_mgr * my_error_ptr;METHODDEF(void)my_error_exit (j_common_ptr cinfo)
{fprintf(stderr, "my_error_exit\n");
}int is_jpeg(char *pathname)
{FILE * infile;char head_tmp[2] = {0};if ((infile = fopen(pathname, "rb")) == NULL){fprintf(stderr, "can't open %s\n", pathname);return 1;}fread(head_tmp,2,1,infile);if(!((head_tmp[0] == 0xff) && (head_tmp[1] == 0xd8))){fclose(infile);return 1;}return 0;
}int display_jpeg(char *pathname)
{struct jpeg_decompress_struct cinfo;struct my_error_mgr jerr;FILE * infile;int row_stride;unsigned char *buffer = NULL;unsigned int i,j;int rgb_offset = 0;int cnt = 0;unsigned int *tmp = pfb;if ((infile = fopen(pathname, "rb")) == NULL) {fprintf(stderr, "can't open %s\n", pathname);return 1;}debug("open %s sucess\n",pathname);cinfo.err = jpeg_std_error(&jerr.pub);jerr.pub.error_exit = my_error_exit;jpeg_create_decompress(&cinfo);jpeg_stdio_src(&cinfo, infile);(void) jpeg_read_header(&cinfo, TRUE);(void) jpeg_start_decompress(&cinfo);debug("width : %d height : %d bpp : %d\n",cinfo.output_width, cinfo.output_height, 8 * cinfo.output_components);if((cinfo.output_components * 8) != 24 && (cinfo.output_components * 8) != 32){printf("%d bpp is not support\n",cinfo.output_components * 8);fclose(infile);return -1;}row_stride = cinfo.output_width * cinfo.output_components;buffer = (unsigned char *)malloc(row_stride);if(buffer == NULL){printf("cinfo buffer malloc fail\n");fclose(infile);return -1;}memset(rgb_buf,0,RGB_BUF_SIZE);while (cinfo.output_scanline < cinfo.output_height) {(void) jpeg_read_scanlines(&cinfo, &buffer, 1);memcpy(rgb_buf + (cinfo.output_scanline-1) * row_stride, buffer, row_stride);}rgb_offset = cinfo.output_height * cinfo.output_width * 3 - 3;for(i = 0;i < cinfo.output_height;i++){for(j = 0;j < cinfo.output_width;j++){cnt = WIDTH * i + j;*(tmp + cnt) = ((rgb_buf[rgb_offset + 0] << 0) | (rgb_buf[rgb_offset + 1] << 8) | (rgb_buf[rgb_offset + 2] << 16));rgb_offset -= 3;}}jpeg_finish_decompress(&cinfo);jpeg_destroy_decompress(&cinfo);fclose(infile);return 0;
}
fb_png.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#include <png.h>
#include <pngstruct.h>
#include <pnginfo.h>#include "config.h"#define PNG_BYTES_TO_CHECK 8int is_png(char *pathname)
{FILE *fp = NULL;char buf[PNG_BYTES_TO_CHECK] = {0};if ((fp = fopen(pathname, "rb")) == NULL){printf("open %s fail\n",pathname);return 1;}if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK){printf("read 2 bit error\n");fclose(fp);return 1;}if (!strncmp(buf+1, "PNG", 3)){return 0;}else{return 1;}
}int display_png(char *pathname)
{FILE *fp = NULL;png_structp png_ptr;png_infop info_ptr;png_bytep* row_pointers;unsigned int i,j;int cnt = 0;int pos = 0;int rgb_offset = 0;unsigned int *tmp = pfb;if ((fp = fopen(pathname, "rb")) == NULL){printf("open %s fail\n",pathname);return -1;}debug("open %s sucess\n",pathname);png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);if (png_ptr == 0){printf("png_create_read_struct fail\n");fclose(fp);return -1;}info_ptr = png_create_info_struct(png_ptr);if (info_ptr == 0){printf("png_create_info_struct fail \n");fclose(fp);png_destroy_read_struct(&png_ptr, 0, 0);return -1;}if (setjmp(png_jmpbuf(png_ptr))){png_destroy_read_struct(&png_ptr, &info_ptr, 0);printf("png_jmpbuf fail \n");fclose(fp);return -1;}png_init_io(png_ptr, fp);png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);debug("width : %d height : %d bpp : %d\n",info_ptr->width,info_ptr->height,info_ptr->pixel_depth);if(info_ptr->pixel_depth != 24 && info_ptr->pixel_depth != 32){printf("%d bpp is not support\n",info_ptr->pixel_depth);fclose(fp);png_destroy_read_struct(&png_ptr, &info_ptr, 0);png_destroy_read_struct(&png_ptr, 0, 0);return -1;}row_pointers = png_get_rows(png_ptr,info_ptr);memset(rgb_buf,0,RGB_BUF_SIZE);if(info_ptr->color_type == PNG_COLOR_TYPE_RGB){for(j=0; j< info_ptr->width * 3; j+=3){for(i=0; i< info_ptr->height ; i++){rgb_buf[pos++] = row_pointers[i][j+0];rgb_buf[pos++] = row_pointers[i][j+1];rgb_buf[pos++] = row_pointers[i][j+2];}}}for(j = 0;j < info_ptr->width;j++){for(i = 0;i < info_ptr->height;i++){cnt = WIDTH * (600 - i) + ( 1024 - j);*(tmp + cnt) = ((rgb_buf[rgb_offset + 2] << 0) | (rgb_buf[rgb_offset + 1] << 8) | (rgb_buf[rgb_offset + 0] << 16));rgb_offset += 3;}}png_destroy_read_struct(&png_ptr, &info_ptr, 0);return 0;
}
fb.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>#include "config.h"int init_background()
{unsigned int *tmp = pfb;unsigned int i, j;for(i = 0; i < HIGH;i++){for(j = 0;j < WIDTH;j++){*(tmp + WIDTH *i + j) = BLACK;}}return 0;}int init_fb()
{int fb = -1;struct fb_var_screeninfo var_info = {0};int p_len;int ret = -1;fb = open(FB_DEV,O_RDWR);if(fb == -1){perror("open");return -1;}ret = ioctl(fb, FBIOGET_VSCREENINFO, &var_info);if (ret < 0){perror("ioctl");return -1;}p_len = var_info.xres_virtual * var_info.yres_virtual * var_info.bits_per_pixel / 8;pfb = mmap(NULL,p_len,PROT_READ | PROT_WRITE, MAP_SHARED,fb,0);if(pfb == NULL){perror("mmap");close(fb);}init_background();return 0;
}
list:
Makefile
obj-y += list.o
obj-y += init_list.o
list.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"pic * create_node(const char *path_name)
{pic *p = (pic *)malloc(sizeof(pic));if(p == NULL){printf("malloc error\n");return NULL;}strcpy(p->pathname,path_name);p->next = NULL;p->prev = NULL;return p;
}void insert_tail(pic *phead,pic *new)
{pic *p = phead;if(p == NULL)exit(0);if(p->next == NULL)goto insert;while(p->next != phead){p = p->next;}
insert:p->next = new;new->prev = p;new->next = phead;phead->prev = new;
}pic *next_printf_link(pic* head,pic *p)
{if(p == NULL)exit(0);if(p->next == head)return p->next->next;return p->next;
}pic *prev_printf_link(pic* head,pic *p)
{if(p == NULL)exit(0);if(p->prev == head)return p->prev->prev;return p->prev;
}
init_list.c
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include "list.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "fb_bmp.h"
#include "fb_jpeg.h"
#include "fb_png.h"
#include "fb.h"int insert_pic_link(char *pathname)
{DIR *dir;struct dirent *entry;struct stat sta;char path[256];if ((dir = opendir(pathname)) == NULL){perror("opendir\n");return -1;}while ((entry = readdir(dir)) != NULL) {if(strcmp(entry->d_name, ".")==0 || strcmp(entry->d_name, "..")==0 || strcmp(entry->d_name, "start")==0)continue;sprintf(path, "%s/%s", pathname, entry->d_name);lstat(path, &sta);if(S_ISDIR(sta.st_mode)){insert_pic_link(path);}if(S_ISREG(sta.st_mode)){insert_tail(head,create_node(path));}}closedir(dir);return 0;
}void init_pic_link(pic *head)
{pic *tmp = head->next;while(tmp != head){if(!is_bmp(tmp->pathname)){tmp->type = BMP;tmp->display = display_bmp; }if(!is_jpeg(tmp->pathname)){tmp->type = JPEG;tmp->display = display_jpeg;}if(!is_png(tmp->pathname)){tmp->type = PNG;tmp->display = display_png;}tmp = tmp->next;}if(!is_bmp(tmp->pathname)){tmp->type = BMP;tmp->display = display_bmp;}
}
image: