Linux应用编程之图片浏览APP实现

来源:互联网 发布:怎么报考网络教育 编辑:程序博客网 时间:2024/04/28 04:27

目前只支持jpeg格式的图片,需要显示其他图片的在main函数中添加就可以。解析出图片头字节,根据字节判断是属于什么格式的图片。

有四个文件:main.c  input_manager.c   touchscreen.c    input_manager.h    编译时候加上-ljpeg -lts -lpthread库


main.c文件

#include <stdio.h>#include <jpeglib.h>#include <setjmp.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <linux/fb.h>#include <string.h>#include <stdlib.h>#include <tslib.h>#include <dirent.h>#include <string.h> #include <unistd.h> #include <input_manager.h>#define FB_DEVICE_NAME "/dev/fb0"//#define DBG_PRINTF(...)  #define DBG_PRINTF printf#define FILE_PATH  "/tmp/digitpic/icons_jpeg"static int g_fd;static struct fb_var_screeninfo g_tFBVar;static struct fb_fix_screeninfo g_tFBFix;static unsigned char *g_pucFBMem;static unsigned int g_dwScreenSize;static unsigned int g_dwLineWidth;static unsigned int g_dwPixelWidth;static int FBDeviceInit(void){int ret;g_fd = open(FB_DEVICE_NAME, O_RDWR);if (0 > g_fd){DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);}ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);if (ret < 0){DBG_PRINTF("can't get fb's var\n");return -1;}ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);if (ret < 0){DBG_PRINTF("can't get fb's fix\n");return -1;}g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);if (0 > g_pucFBMem){DBG_PRINTF("can't mmap\n");return -1;}g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;return 0;}static int FBShowPixel(int iX, int iY, unsigned int dwColor){unsigned char *pucFB;unsigned short *pwFB16bpp;unsigned int *pdwFB32bpp;unsigned short wColor16bpp; /* 565 */int iRed;int iGreen;int iBlue;if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres)){DBG_PRINTF("out of region\n");return -1;}pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;pwFB16bpp  = (unsigned short *)pucFB;pdwFB32bpp = (unsigned int *)pucFB;switch (g_tFBVar.bits_per_pixel){case 8:{*pucFB = (unsigned char)dwColor;break;}case 16:{iRed   = (dwColor >> (16+3)) & 0x1f;iGreen = (dwColor >> (8+2)) & 0x3f;iBlue  = (dwColor >> 3) & 0x1f;wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;*pwFB16bpp= wColor16bpp;break;}case 32:{*pdwFB32bpp = dwColor;break;}default :{DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);return -1;}}return 0;}static int FBCleanScreen(unsigned int dwBackColor){unsigned char *pucFB;unsigned short *pwFB16bpp;unsigned int *pdwFB32bpp;unsigned short wColor16bpp; /* 565 */int iRed;int iGreen;int iBlue;int i = 0;pucFB      = g_pucFBMem;pwFB16bpp  = (unsigned short *)pucFB;pdwFB32bpp = (unsigned int *)pucFB;switch (g_tFBVar.bits_per_pixel){case 8:{memset(g_pucFBMem, dwBackColor, g_dwScreenSize);break;}case 16:{iRed   = (dwBackColor >> (16+3)) & 0x1f;iGreen = (dwBackColor >> (8+2)) & 0x3f;iBlue  = (dwBackColor >> 3) & 0x1f;wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;while (i < g_dwScreenSize){*pwFB16bpp= wColor16bpp;pwFB16bpp++;i += 2;}break;}case 32:{while (i < g_dwScreenSize){*pdwFB32bpp= dwBackColor;pdwFB32bpp++;i += 4;}break;}default :{DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);return -1;}}return 0;}static int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray){int i = iXStart * 3;int iX;unsigned int dwColor;if (iY >= g_tFBVar.yres)return -1;if (iXStart >= g_tFBVar.xres)return -1;if (iXEnd >= g_tFBVar.xres){iXEnd = g_tFBVar.xres;}for (iX = iXStart; iX < iXEnd; iX++){/* 0xRRGGBB */dwColor = (pucRGBArray[i]<<16) + (pucRGBArray[i+1]<<8) + (pucRGBArray[i+2]<<0);i += 3;FBShowPixel(iX, iY, dwColor);}return 0;}static int show_jpeg_file(char *file_name){struct jpeg_decompress_struct cinfo;struct jpeg_error_mgr jerr;FILE * infile;int row_stride;unsigned char *buffer;int  Width,Height,temp;// 分配和初始化一个decompression结构体cinfo.err = jpeg_std_error(&jerr);jpeg_create_decompress(&cinfo);// 指定源文件if ((infile = fopen(file_name, "rb")) == NULL) {fprintf(stderr, "can't open %s\n",file_name);return -1;}jpeg_stdio_src(&cinfo, infile);// 用jpeg_read_header获得jpg信息jpeg_read_header(&cinfo, TRUE);/* 源信息 */printf("image_width = %d\n", cinfo.image_width);printf("image_height = %d\n", cinfo.image_height);printf("num_components = %d\n", cinfo.num_components);// 设置解压参数,比如放大、缩小//printf("enter scale M/N:\n");//scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom);  //手动输入缩放比例,麻烦,下面给出自己计算//printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);Width  =cinfo.image_width;Height =cinfo.image_height;if((Width>420)||(Height>272))  /* 需要缩小 */{if(Width/Height>=(420/272))  /*以宽度为标准缩放*/{cinfo.scale_num=1;cinfo.scale_denom=Width/420;}else   /*以高度为标准缩放*/{cinfo.scale_num=1;cinfo.scale_denom=Height/272;}}else   /* 保持图片原先大小 */{cinfo.scale_num=1;cinfo.scale_denom=1; }printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);// 启动解压:jpeg_start_decompressjpeg_start_decompress(&cinfo);/* 输出的图象的信息 */printf("output_width = %d\n", cinfo.output_width);printf("output_height = %d\n", cinfo.output_height);printf("output_components = %d\n", cinfo.output_components);// 一行的数据长度row_stride = cinfo.output_width * cinfo.output_components;buffer = malloc(row_stride);// 循环调用jpeg_read_scanlines来一行一行地获得解压的数据while (cinfo.output_scanline < cinfo.output_height) {(void) jpeg_read_scanlines(&cinfo, &buffer, 1);// 写到LCD去FBShowLine(0, cinfo.output_width, cinfo.output_scanline, buffer);}free(buffer);jpeg_finish_decompress(&cinfo);jpeg_destroy_decompress(&cinfo);return 0;}static struct dirent **namelist; static int  scandir_file(){         int n;         n = scandir(FILE_PATH, &namelist, NULL, alphasort);        if (n < 0)        {              DBG_PRINTF("scandir  error\n");return -1;        }return n;}/*Allocate and initialize a JPEG decompression object    // 分配和初始化一个decompression结构体Specify the source of the compressed data (eg, a file) // 指定源文件Call jpeg_read_header() to obtain image info   // 用jpeg_read_header获得jpg信息Set parameters for decompression   // 设置解压参数,比如放大、缩小jpeg_start_decompress(...);    // 启动解压:jpeg_start_decompresswhile (scan lines remain to be read)jpeg_read_scanlines(...);   // 循环调用jpeg_read_scanlinesjpeg_finish_decompress(...);   // jpeg_finish_decompressRelease the JPEG decompression object   // 释放decompression结构体*//* Uage: jpg2rgb <jpg_file> */int main(int argc, char **argv){   int file_all_num;   int file_num=2;   int i;    char strTmp[256];   int iError;   T_InputEvent tInputEvent;iError=InputInit();if (iError){DBG_PRINTF("InputInit error!\n");return -1;}iError=AllInputDevicesInit();if (iError){DBG_PRINTF("InputInit error!\n");return -1;}iError=FBDeviceInit();if (iError){DBG_PRINTF("InputInit error!\n");return -1;}file_all_num=scandir_file();for(i=0;i<file_all_num;i++)printf("file_all_num=%d,namelist[%d]->d_name=%s\n",file_all_num,i,namelist[i]->d_name);snprintf(strTmp, 256, "%s/%s",FILE_PATH, namelist[file_num]->d_name);strTmp[255] = '\0';DBG_PRINTF("strTmp=%s,file_num=%d\n",strTmp,file_num);FBCleanScreen(0);show_jpeg_file(strTmp);while(1){ if (0 == GetInputEvent(&tInputEvent));{usleep(100000);    /* delay  */DBG_PRINTF("tInputEvent.iVal=%d\n",tInputEvent.iVal);if (tInputEvent.iVal == INPUT_VALUE_DOWN){file_num++;if(file_num>=file_all_num)file_num=2;while((0 == strcmp(namelist[file_num]->d_name, ".")) || (0 == strcmp(namelist[file_num]->d_name, "..")))  {file_num++;  }}else if (tInputEvent.iVal == INPUT_VALUE_UP){file_num--;if(file_num<0)file_num=file_all_num-1;while ((0 == strcmp(namelist[file_num]->d_name, ".")) || (0 == strcmp(namelist[file_num]->d_name, "..")))  {file_num=file_all_num-1;  }}else {FBCleanScreen(0);return -1;}snprintf(strTmp, 256, "%s/%s",FILE_PATH, namelist[file_num]->d_name);    strTmp[255] = '\0';DBG_PRINTF("strTmp=%s,file_num=%d\n",strTmp,file_num);FBCleanScreen(0);show_jpeg_file(strTmp); }}return 0;}


input_manager.h文件

#ifndef _INPUT_MANAGER_H#define _INPUT_MANAGER_H#include <sys/time.h>#include <pthread.h>#define INPUT_TYPE_STDIN        0#define INPUT_TYPE_TOUCHSCREEN  1#define INPUT_VALUE_UP          1  #define INPUT_VALUE_DOWN        2#define INPUT_VALUE_EXIT        3#define INPUT_VALUE_UNKNOWN     -1typedef struct InputEvent {struct timeval tTime;int iType;  /* stdin, touchsceen */int iVal;   /*  */}T_InputEvent, *PT_InputEvent;typedef struct InputOpr {char *name;pthread_t tTreadID;int (*DeviceInit)(void);int (*DeviceExit)(void);int (*GetInputEvent)(PT_InputEvent ptInputEvent);struct InputOpr *ptNext;}T_InputOpr, *PT_InputOpr;int InputInit(void);int RegisterInputOpr(PT_InputOpr ptInputOpr);void ShowInputOpr(void);int AllInputDevicesInit(void);int GetInputEvent(PT_InputEvent ptInputEvent);int TouchScreenInit(void);#endif /* _INPUT_MANAGER_H */


touchscreen.c文件:

#include <input_manager.h>#include <stdlib.h>#include <tslib.h>#define DBG_PRINTF(...)  /* 参考tslib里的ts_print.c */static struct tsdev *g_tTSDev;static int giXres=420;static int giYres=272;/* 注意: 由于要用到LCD的分辨率, 此函数要在SelectAndInitDisplay之后调用 */static int TouchScreenDevInit(void){char *pcTSName = NULL;if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL ) {g_tTSDev = ts_open(pcTSName, 0);  /* 以阻塞方式打开 */}else{g_tTSDev = ts_open("/dev/event0", 1);}if (!g_tTSDev) {DBG_PRINTF("ts_open error!\n");return -1;}if (ts_config(g_tTSDev)) {DBG_PRINTF("ts_config error!\n");return -1;}return 0;}static int TouchScreenDevExit(void){return 0;}static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent){struct ts_sample tSamp;int iRet;iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */if (iRet < 0) {return -1;}/* 处理数据 *//* 如果此次触摸事件发生的时间, 距上次事件超过了500ms */ptInputEvent->tTime = tSamp.tv;ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;if ((tSamp.y < giYres/3)||(tSamp.x < giXres/3)){ptInputEvent->iVal = INPUT_VALUE_UP;}else if ((tSamp.y > 2*giYres/3)||(tSamp.x > 2*giXres/3)){ptInputEvent->iVal = INPUT_VALUE_DOWN;}else{ptInputEvent->iVal = INPUT_VALUE_EXIT;}return 0;}static T_InputOpr g_tTouchScreenOpr = {.name          = "touchscreen",.DeviceInit    = TouchScreenDevInit,.DeviceExit    = TouchScreenDevExit,.GetInputEvent = TouchScreenGetInputEvent,};int TouchScreenInit(void){return RegisterInputOpr(&g_tTouchScreenOpr);}


input_manager.c文件:

#include <input_manager.h>#include <string.h>#define DBG_PRINTF printfstatic PT_InputOpr g_ptInputOprHead;static T_InputEvent g_tInputEvent;static pthread_mutex_t g_tMutex  = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t  g_tConVar = PTHREAD_COND_INITIALIZER;int RegisterInputOpr(PT_InputOpr ptInputOpr){PT_InputOpr ptTmp;if (!g_ptInputOprHead){g_ptInputOprHead   = ptInputOpr;ptInputOpr->ptNext = NULL;}else{ptTmp = g_ptInputOprHead;while (ptTmp->ptNext){ptTmp = ptTmp->ptNext;}ptTmp->ptNext  = ptInputOpr;ptInputOpr->ptNext = NULL;}return 0;}void ShowInputOpr(void){int i = 0;PT_InputOpr ptTmp = g_ptInputOprHead;while (ptTmp){printf("%02d %s\n", i++, ptTmp->name);ptTmp = ptTmp->ptNext;}}static void *InputEventTreadFunction(void *pVoid){T_InputEvent tInputEvent;/* 定义函数指针 */int (*GetInputEvent)(PT_InputEvent ptInputEvent);GetInputEvent = (int (*)(PT_InputEvent))pVoid;while (1){if(0 == GetInputEvent(&tInputEvent)){/* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 *//* 访问临界资源前,先获得互斥量 */pthread_mutex_lock(&g_tMutex);g_tInputEvent = tInputEvent;/*  唤醒主线程 */pthread_cond_signal(&g_tConVar);/* 释放互斥量 */pthread_mutex_unlock(&g_tMutex);}}return NULL;}int AllInputDevicesInit(void){PT_InputOpr ptTmp = g_ptInputOprHead;int iError = -1;while (ptTmp){if (0 == ptTmp->DeviceInit()){/* 创建子线程 */iError=pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent);if(iError ==0){DBG_PRINTF("%s pthread_create  is succesd!\n",ptTmp->name);}}ptTmp = ptTmp->ptNext;}return iError;}int GetInputEvent(PT_InputEvent ptInputEvent){/* 休眠 */pthread_mutex_lock(&g_tMutex);pthread_cond_wait(&g_tConVar, &g_tMutex);/* 被唤醒后,返回数据 */*ptInputEvent = g_tInputEvent;pthread_mutex_unlock(&g_tMutex);return 0;}int InputInit(void){int iError;iError = TouchScreenInit();return iError;}


下一篇文章讲解图片的缩放合并算法。

1 0
原创粉丝点击