粗淺設計一個登入平臺

Dazz_24發表於2024-05-14

設計一個程式,該程式在執行之後自動播放一段開機動畫,開機動畫結束後可以調轉到登入介面,登入介面有2個按鈕,分別是登入和退出,點選登入之後可以顯示系統主介面。主介面自擬,要求主介面有一個返回按鈕,點選返回按鈕可以回到登入介面。(不使用goto)

定義全域性變數

int cnt = 0;
int x, y;
int *lcd_mp;

將JPG格式的圖片顯示在lcd螢幕的函式介面:

/******************************************************
 *
 *  name      : read_JPEG_file
 *	function  : 將JPG格式的圖片顯示在lcd螢幕
 * argument
 *                      @filename :圖片路徑
 *                      @start_x :圖片顯示在lcd螢幕的x軸
 *                      @start_y :圖片顯示在lcd螢幕的y軸
 *
 *  retval    : 成功為1,否則為0
 *  author    : Dazz
 *  date      : 2024/5/14
 *  note      : None
 *
 * *******************************************************/
int read_JPEG_file(char *filename, int start_x, int start_y)
{

  //(1)	建立解碼物件,並且對解碼物件進行初始化,另外需要建立錯誤處理物件,並和解碼物件進行關聯

  // 建立jpeg解碼物件
  struct jpeg_decompress_struct cinfo;

  // 建立錯誤處理物件
  struct jpeg_error_mgr jerr;
  // 將錯誤物件和解碼物件進行關聯
  cinfo.err = jpeg_std_error(&jerr);

  // 初始化解碼物件
  jpeg_create_decompress(&cinfo);

  //(2)	開啟待解碼的jpg圖片,使用fopen的時候需要新增選項”b”,以二進位制方式開啟檔案!
  FILE *infile;
  if ((infile = fopen(filename, "rb")) == NULL)
  {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
  }


  // 指定資料
  jpeg_stdio_src(&cinfo, infile);

  //(3)	讀取待解碼圖片的檔案頭,並把影像資訊和解碼物件進行關聯,透過解碼物件對jpg圖片進行解碼
  (void)jpeg_read_header(&cinfo, TRUE);

  //(5)	開始對jpg圖片進行解碼,呼叫函式之後開始解碼,可以得到影像寬、影像高等資訊!

  (void)jpeg_start_decompress(&cinfo);

  int row_stride;                                           
  row_stride = cinfo.output_width * cinfo.output_components; // 計算一行的大小


  unsigned char *buffer; /* Output row buffer 定義一個緩衝區 */
  buffer = calloc(1, row_stride);


  int data = 0;

  while (cinfo.output_scanline < cinfo.output_height)
  {

    (void)jpeg_read_scanlines(&cinfo, &buffer, 1); // 從上到下,從左到右  RGB RGB RGB RGB

    for (int i = 0; i < cinfo.output_width; ++i) // 012 345
    {
      data |= buffer[3 * i] << 16;    // R
      data |= buffer[3 * i + 1] << 8; // G
      data |= buffer[3 * i + 2];      // B

      // 把畫素點寫入到LCD的指定位置
      lcd_mp[800 * start_y + start_x + 800 * (cinfo.output_scanline - 1) + i] = data;

      data = 0;
    }
  }


  //(7)	在所有的影像資料都已經解碼完成後,則呼叫函式完成解碼即可,然後釋放相關資源!

  (void)jpeg_finish_decompress(&cinfo);



  // 釋放解碼物件
  jpeg_destroy_decompress(&cinfo);

  fclose(infile);



  return 1;
}

開啟觸控式螢幕,直到使用者點選"登入"的位置的函式介面:

/******************************************************
 *
 *  name      : GeTouchVal_st
 *	function  : 開啟觸控式螢幕,直到使用者點選"登入"的位置
 *  argument  : 開啟觸控式螢幕的返回值
 *  retval    : None
 *  author    : Dazz
 *  date      : 2024/5/14
 *  note      : None
 *
 * *******************************************************/
void GeTouchVal_st(int ts_fd)
{

  // 2.讀取輸入裝置的資訊
  struct input_event ts_event;

  while (1)
  {
    read(ts_fd, &ts_event, sizeof(ts_event));

    // 3.分析讀取的裝置資訊 (type + code + value)
    if (ts_event.type == EV_ABS) // 說明是觸控式螢幕
    {
      if (ts_event.code == ABS_X) // 說明是X軸
      {
        cnt++;
        x = ts_event.value * 800 / 1024;
      }
      if (ts_event.code == ABS_Y) // 說明是Y軸
      {
        cnt++;
        y = ts_event.value * 480 / 600;
      }

      if (cnt >= 2)
      {
        printf("x = %d\t", x); // 輸出X軸座標
        printf("y = %d\n", y); // 輸出Y軸座標
        cnt = 0;
      }
    }
    if (x > 585 && x < 789 && y > 100 && y < 209)
      break;
  }
}

開啟觸控式螢幕,直到使用者點選"返回"的位置的函式介面:

/******************************************************
 *
 *  name      : GeTouchVal_sp
 *	function  : 開啟觸控式螢幕,直到使用者點選"返回"的位置
 *  argument  : 開啟觸控式螢幕的返回值
 *  retval    : None
 *  author    : Dazz
 *  date      : 2024/5/14
 *  note      : None
 *
 * *******************************************************/
void GeTouchVal_sp(int ts_fd)
{

  // 2.讀取輸入裝置的資訊
  struct input_event ts_event;

  while (1)
  {
    read(ts_fd, &ts_event, sizeof(ts_event));

    // 3.分析讀取的裝置資訊 (type + code + value)
    if (ts_event.type == EV_ABS) // 說明是觸控式螢幕
    {
      if (ts_event.code == ABS_X) // 說明是X軸
      {
        cnt++;
        x = ts_event.value * 800 / 1024;
      }
      if (ts_event.code == ABS_Y) // 說明是Y軸
      {
        cnt++;
        y = ts_event.value * 480 / 600;
      }

      if (cnt >= 2)
      {
        printf("x = %d\t", x); // 輸出X軸座標
        printf("y = %d\n", y); // 輸出Y軸座標
        cnt = 0;
      }
    }
    if (x > 35 && x < 135 && y > 2 && y < 111)
      break;
  }
}

主函式:

int main(int argc, char const *argv[])
{
  //開啟LCD   open
  int lcd_fd = open("/dev/fb0", O_RDWR);

  // 對LCD進行記憶體對映  mmap
  lcd_mp = (int *)mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);

  // 顯示gif
  char gif_buf[128] = "0";

  for (int i = 0; i < 60; i++)
  {
    sprintf(gif_buf, "./gif/Frame%d.jpg", i);
    read_JPEG_file(gif_buf, 0, 0);
    usleep(1000 * 1000 / 24);
  }

  //  開啟觸控式螢幕
  int ts_fd = open("/dev/input/event0", O_RDWR);

  while (1)
  {
    read_JPEG_file("./start.jpg", 0, 0);
    GeTouchVal_st(ts_fd);
    read_JPEG_file("./stop.jpg", 0, 0);
    GeTouchVal_sp(ts_fd);
  }
  //關閉檔案
  close(ts_fd);

  return 0;
}

相關文章