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

               

目前只支持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 / 8g_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 *pucFBunsigned short *pwFB16bppunsigned int *pdwFB32bppunsigned short wColor16bpp; /* 565 */ int iRedint iGreenint iBlueint i = 0; pucFB      = g_pucFBMem; pwFB16bpp  = (unsigned short *)pucFBpdwFB32bpp = (unsigned int *)pucFBswitch (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 * 3int iXunsigned int dwColorif (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 cinfostruct jpeg_error_mgr jerrFILE * infileint row_strideunsigned char *bufferint  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_decompress  jpeg_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 readjpeg_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;}


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

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值