jq实现点事图片移动_LCD屏实现图片移动(包含触摸效果)

9d8e8e4499840d48b00ed7803284f517.png

图控大叔

构图传递思想

阅读从未如此简单!!!

01

前言

       前些天分享了LCD屏实现图片移动的代码分享,但是上次未加入触摸效果,本次推文在上次效果的基础上增加了触摸效果,其实主要是获取LCD触摸屏函数的应用675266131cebe28325e33d1781c05a05.png

02

干货

       实现思路(可能很low):

1、设置全局变量存储图片左上角位置点(x、y)

2、通过某函数获取得到触摸坐标

3、得到的触摸坐标放在全局变量中

4、将全局变量放入图片显示函数中

5、来个死循环嗨一下

注:该图片显示函数已经经过多次调试,进行了优化,极大程度上避免了段错误的出现。

注:小编的思路可能很low,但是小编把代码分享出来,是希望作为一个参考方案,而不是标准答案,至于复杂功能的开发,则需要大家的深入学习。

注:由于小编忘记了Linux环境下,多个.c文件如何编译,因此把全部函数放在了一个.c文件中。后期小编再整合吧,目前先这样分享出来!

例程代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LCD_H 480
#define LCD_W 800
#define TS_DEV "/dev/input/event0"//"/dev/ubuntu_event"
#define TS_MODE 1


#include 

//1表示坐标范围为:x:0~1023, y:0~599
//0表示坐标范围为:x:0~799 y:0~479


/*
#define LCD_H 480
#define LCD_W 800
此处宏定义将规范图片显示的范围
*/
int show_bmp(int x, int y, int bmp_w, int bmp_h, char *bmp_path);
int single_color(int x1, int y1,int x2, int y2, unsigned int color, unsigned int *addr);
int bmp_color(int star_w, int star_h,int bmp_w, int bmp_h, unsigned int *color, unsigned int *addr);
int get_xy(int x, int y);

int mouse_x = 0;
int mouse_y = 0;

/*
int mouse_x = 0;
int mouse_y = 0;
此处为全局变量,
作为触摸屏坐标获取值的存储变量
也作为图片显示函数的起始点
*/
int main(int argc, const char **argv){

  show_bmp(0, 0, 400, 300, "./1.bmp");
  
  return 0;
}

int show_bmp(int x, int y, int bmp_w, int bmp_h, char *bmp_path){
  //char *bmp_path = "/gz2030/1.bmp";
  if(x+bmp_w > 800 || y+bmp_h > 480)
  {
    printf("bmp: %s too big", bmp_path);
    return -1;
  }

  printf("bmp_path:%s\n", bmp_path);
  //1》打开bmp文件bmp_w*bmp_h
  FILE *bmp_fp = fopen(bmp_path, "r");
  
  if(bmp_fp == NULL)
  {
    fprintf(stderr, "fopen %s failed: %s\n", bmp_path, strerror(errno));
    return -1;
  }
  else
  {
    printf("showing %s bmp_w: %d bmp_h : %d\n", bmp_path, bmp_w, bmp_h);
    
  }

  //2》跳过54个字节文件头
  //lseek(bmp_fp->_fileno, 54, SEEK_SET);
  fseek(bmp_fp, 54, SEEK_SET);
  
  unsigned char bmp_buf[bmp_w*bmp_h*3];
  bzero(bmp_buf, bmp_w*bmp_h*3);
  
  //3》读取bmp文件像素点数据bmp_w*bmp_h*3
  fread(bmp_buf, bmp_w*bmp_h*3, 1, bmp_fp);
  
  //4》关闭bmp文件
  fclose(bmp_fp);
  
  //5》打开LCD屏幕文件
  int lcd_fd = open("/dev/fb0", O_RDWR);
  if(lcd_fd == -1)
  {
    perror("open /dev/fb0 failed");
    return -1;
  }
  
  //6》内存映射
  unsigned int *addr = mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED , lcd_fd, 0);
  if(addr == MAP_FAILED)
  {
    perror("mmap /dev/fb0 failed");
    return -1;
  }
  
  unsigned int lcd_buf[bmp_w*bmp_h];
  bzero(lcd_buf, bmp_w*bmp_h*4);
  
  unsigned int lcd_buf_2[800*480];
  bzero(lcd_buf_2, 800*480*4);
  
  int i, j,k,m;

  //7》把bmp像素点数据转化成LCD类型的像素点数据
  for(j=0; j  {
    for(i=0; i    {
      lcd_buf[i+j*bmp_w] = bmp_buf[0+3*i+j*bmp_w*3] | (bmp_buf[1+3*i+j*bmp_w*3]<<8) | (bmp_buf[2+3*i+j*bmp_w*3]<<16);
    }
  }
  
  //白色清屏
  single_color(0,0,480,800,0xffffff,addr);
  
  //8》把像素点数据通过指针赋值的方式写入到文件
  //多组数据以便观察
  
  usleep(1000*50);
  bmp_color(0,0,400,300,lcd_buf,addr);
  
  while(1)//死循环
  {
    get_xy(mouse_x, mouse_y);
    
    bmp_color(mouse_x,mouse_y,400,300,lcd_buf,addr);
    
  }

  //9》关闭文件和接触内存映射
  close(lcd_fd);
  munmap(addr, 800*480*4);
  
  return 0;
}
int single_color(int x1, int y1,int x2, int y2, unsigned int color, unsigned int *addr){
    int i, j;
    
    for(j=x1; j    {
    
      for(i=y1; i      {
        
        *(addr+800*j+i) = color;
        
      }
      //usleep(1000*2);//此处加入延迟便于观察,可注释掉
      //printf("j is %d\n",j);
    }
    return 0;
}

/*
bmp_color:静态图片实现位置变化
star_h、star_w:移动起始点
bmp_h、bmp_w:图片宽度、长度
color:图片像素点(以数组形式出现)
*addr:内存映射地址
异常情况说明:
因为现实中LCD屏尺寸不一
本次使用的LCD屏尺寸为:480*800
因此对star_h、star_w、bmp_h、bmp_w的数值填充时
需要理性填写,不要给自己挖坑
另外,该函数对于不合理的数组进行判别
如:图片尺寸不合理时,打印错误;
图片尺寸合理,但是移动起点不合理时,
自动判别处理,重新赋值移动起点
记录于:2020/7/4
*/

int bmp_color(int star_w, int star_h,int bmp_w, int bmp_h, unsigned int *color, unsigned int *addr){
    int i,j;
    
    //判断数值是否合理
    if( (bmp_h>LCD_H) || (bmp_w>LCD_W) )
    {
      printf("the photo is too big\n");
    }
    
    else if( LCD_H-star_h    {
      
      star_h = LCD_H -star_h + bmp_h;
       
      if( star_h < LCD_H )
      star_h = LCD_H-star_h;

      else
      star_h = star_h-LCD_H;
      
      if( LCD_W-star_w      {
        star_w = LCD_W - bmp_w;
        
        //printf("star_w is %d\n",star_w);
        
      }
      //先将屏幕以白色清屏
      single_color(0,0,480,800,0xffffff,addr);
      
      for(j=0; j      {
        for(i=0; i        {
          //显示到指定坐标位置,正立的
          *(addr+i+(bmp_h-1-j)*800+800*star_h+star_w) = color[i+j*bmp_w] ;

        }
        //usleep(1000);//此处加入延迟便于观察,可注释掉
      }
    }
    
    else if( LCD_W-star_w    {
      star_w = LCD_W - bmp_w;
      
      if( LCD_H-star_h      {
        star_h = LCD_H -star_h + bmp_h;
         
        if( star_h < LCD_H )
        star_h = LCD_H-star_h;

        else
        star_h = star_h-LCD_H;
      }
      //先将屏幕以白色清屏
      single_color(0,0,480,800,0xffffff,addr);
      
      for(j=0; j      {
        for(i=0; i        {
          //显示到指定坐标位置,正立的
          *(addr+i+(bmp_h-1-j)*800+800*star_h+star_w) = color[i+j*bmp_w] ;

        }
        //usleep(1000);//此处加入延迟便于观察,可注释掉
      }
    }
    
    else
    {
      //先将屏幕以白色清屏
      single_color(0,0,480,800,0xffffff,addr);
      
      for(j=0; j      {
        for(i=0; i        {
          //显示到指定坐标位置,正立的
          *(addr+i+(bmp_h-1-j)*800+800*star_h+star_w) = color[i+j*bmp_w] ;

        }
        //usleep(1000);//此处加入延迟便于观察,可注释掉
      }
    }
    
    return 0;
}

int get_xy(int x, int y){
  int  pressure;
  //1、打开触摸屏设备文件: /dev/input/event0
  int ts_fd = open(TS_DEV, O_RDWR );
  if(ts_fd == -1)
  {
    fprintf(stderr, " open %s failed:%s\n", TS_DEV, strerror(errno));
    return -1;
  }
  
  struct input_event ts_buf;    
  bzero(&ts_buf, sizeof(ts_buf)); //清空结构体
  
  
  while(1) //要多次的读取事件的值
  {
    //2、读取触摸屏文件里面的数据:struct input_event
    //每读取一次,触摸屏数据,只能获取到x.y轴、压力值中的一个
    //阻塞等待手指点击屏幕,手指没有点击屏幕它是不会往下执行
    read(ts_fd, &ts_buf, sizeof(ts_buf));
    
    //3、分析处理触摸屏数据获取你要的值:x、y轴、压力值
    //判断事件类型是否为EV_ABS事件
    if(ts_buf.type == EV_ABS)
    {
      usleep(1000*5);
      //进一步判断事件类型是否为x轴事件
      if(ts_buf.code == ABS_X)
      {
        //获取x轴坐标值
        x = ts_buf.value;

#if TS_MODE
        x = (x) * 800/1024;
        mouse_x = x;//赋值给全局变量
#endif
        printf("*x1: %d\n", x);
      }
        else if(ts_buf.code == ABS_Y)
      {
        //获取y轴坐标值
        y = ts_buf.value;
#if TS_MODE
        y = (y) * 480/600;
        mouse_y = y;//赋值给全局变量
#endif
        printf("*y1: %d\n\n", y);
      }
      
    }
    //判断事件类型是否为EV_KEY,手指离开屏幕,压力值为0,就停止坐标捕捉
    if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)
    {
      printf("*y2: %d\n", y);
      printf("*x2: %d\n\n", x);
      
      //赋值给全局变量
      mouse_x = x;
      mouse_y = y;
      break; //跳出死循环
    }
  
  }
  
  //4、关闭触摸屏文件
  close(ts_fd);

}

演示效果

03

结尾

       本次推文的内容到这里就要结束了,小编发现自己还是有很多不足,比如说连简单的多个.c文件同时编译都忘记了,害,慢慢整理出来吧!

       《图控大叔》,与你一起进步!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值