如何在JZ2440 4.3寸LCD顯示屏顯示jpg圖片

內核版本:Linux version 4.4.0-130-generic

交叉編譯工具:gcc-3.4.5-glibc-2.3.6

libjpeg庫版本:jpegsrc.v9c

材料準備:4.3(480*272)寸jpg圖像,編譯好的生成文件,上傳到開發板(可以參考我之前寫過的文章)

代碼如下(包含BMP和JPGE代碼),詳情請看代碼註釋

  
  
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <linux/input.h>
  7. #include <sys/mman.h>
  8. //jpeg庫的標準頭文件
  9. #include <stdio.h>
  10. #include "jpeglib.h"
  11. #include <setjmp.h>
  12. int lcd; //全局變量
  13. short * fb_mem; //這塊的數據類型一定要注意,如果使用就要跟一個像素匹配兩個字節(一個像素由多少個字節組成有關)
  14. /*jpeg顯示所需的結構體*/
  15. struct my_error_mgr {
  16. struct jpeg_error_mgr pub; /* "public" fields */
  17. jmp_buf setjmp_buffer; /* for return to caller */
  18. };
  19. typedef struct my_error_mgr * my_error_ptr;
  20. /*jpeg顯示所需的結構體*/
  21. METHODDEF( void)
  22. my_error_exit (j_common_ptr cinfo)
  23. {
  24. /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  25. my_error_ptr myerr = (my_error_ptr) cinfo->err;
  26. /* Always display the message. */
  27. /* We could postpone this until after returning, if we chose. */
  28. (*cinfo->err->output_message) (cinfo);
  29. /* Return control to the setjmp point */
  30. longjmp(myerr->setjmp_buffer, 1);
  31. }
  32. int init_lcd()
  33. {
  34. lcd = open( "/dev/fb0",O_RDWR); //1.打開LCD設備
  35. if(lcd == -1)
  36. {
  37. perror( "open LCD Err");
  38. return -1;
  39. }
  40. printf( "request LCD OK!\n");
  41. //映射顯存
  42. fb_mem = mmap( NULL, //映射後的地址,NULL系統自動分配
  43. 480* 272* 2, //映射的大小,字節
  44. PROT_READ|PROT_WRITE, //映射的操作
  45. MAP_SHARED, //映射的共享操作 MAP_SHARED MAP_PRIVATE
  46. lcd, //目標設備的文件描述符
  47. 0); //映射的數據地址偏移量,默認0
  48. if(fb_mem == MAP_FAILED)
  49. {
  50. perror( "LCD mmap");
  51. return -1;
  52. }
  53. }
  54. int uninit_lcd()
  55. {
  56. close(lcd); //6.關閉LCD
  57. /*取消映射*/
  58. munmap(fb_mem, //映射後的操作地址
  59. 480* 272* 2); //映射的大小
  60. }
  61. // 解碼 JPEG 圖片,並轉成 RGB 值
  62. int show_JPEG_file (char * filename)
  63. {
  64. int i,x;
  65. //unsigned int lcdbuf[800];
  66. short lcdbuf[ 480]; //注意,這裏lcdbuf是2個字節的數據類型,因爲一個此lcd一個像素用兩個字節表示
  67. //JPEG 解碼信息結構體
  68. struct jpeg_decompress_struct cinfo;
  69. struct my_error_mgr jerr;
  70. /* More stuff */
  71. FILE * infile; /* source file */
  72. JSAMPARRAY buffer; /* Output row buffer */
  73. int row_stride; /* physical row width in output buffer */
  74. //打開要解碼的JPG圖片文件
  75. if ((infile = fopen(filename, "rb")) == NULL) {
  76. fprintf( stderr, "can't open %s\n", filename);
  77. return 0;
  78. }
  79. /* Step 1: allocate and initialize JPEG decompression object */
  80. //分配並初始化解碼結構體信息
  81. cinfo.err = jpeg_std_error(&jerr.pub);
  82. jerr.pub.error_exit = my_error_exit;
  83. //判斷文件類型並做出錯處理
  84. if (setjmp(jerr.setjmp_buffer)) {
  85. /* If we get here, the JPEG code has signaled an error.
  86. * We need to clean up the JPEG object, close the input file, and return.
  87. */
  88. jpeg_destroy_decompress(&cinfo);
  89. fclose(infile);
  90. return 0;
  91. }
  92. /* Now we can initialize the JPEG decompression object. */
  93. jpeg_create_decompress(&cinfo);
  94. /* Step 2: specify data source (eg, a file) */
  95. //指定解碼的源文件關聯
  96. jpeg_stdio_src(&cinfo, infile);
  97. /* Step 3: read file parameters with jpeg_read_header() */
  98. //獲取jpeg文件的頭信息,獲取文件大小及尺寸
  99. ( void) jpeg_read_header(&cinfo, TRUE);
  100. /* Step 4: set parameters for decompression */
  101. //設置必要的解碼信息,可省略
  102. /* Step 5: Start decompressor */
  103. //開始解碼
  104. ( void) jpeg_start_decompress(&cinfo);
  105. /* JSAMPLEs per row in output buffer */
  106. // 設置每行jpg像素數據解碼的大小
  107. row_stride = cinfo.output_width * cinfo.output_components;
  108. //加載jpg文件的數據源,並賦值數據地址到buffer
  109. buffer = (*cinfo.mem->alloc_sarray)
  110. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
  111. /* Step 6: while (scan lines remain to be read) */
  112. /* jpeg_read_scanlines(...); */
  113. //逐行解碼
  114. while (cinfo.output_scanline < cinfo.output_height)
  115. {
  116. //讀取新的一行的jpeg數據
  117. ( void) jpeg_read_scanlines(&cinfo, buffer, 1);
  118. //將解碼後的數據進行處理(自定義)
  119. //put_scanline_someplace(buffer[0], row_stride);
  120. //如何將解碼後的每行像素的RGB數據(buffer[0]),寫入顯存
  121. //fb_mem <----- buffer[0](data) row_stride(size)
  122. for(x= 0,i= 0;x< 480;x++,i+= 3)
  123. //for(x=0,i=0;x<800;x++,i+=3)
  124. { //r g b
  125. lcdbuf[x] = ((buffer[ 0][i])>> 3) << 11 | ((buffer[ 0][i+ 1])>> 2) << 5 | buffer[ 0][i+ 2]>> 3;
  126. //算法:jpg解碼後的24rgb圖像轉化爲16位的rgb圖像(此4.3寸LCD,1個像素由2個字節組成)
  127. }
  128. memcpy((fb_mem+(cinfo.output_scanline -1)* 480),lcdbuf, sizeof(lcdbuf));
  129. }
  130. /* Step 7: Finish decompression */
  131. //結束解碼
  132. ( void) jpeg_finish_decompress(&cinfo);
  133. /* Step 8: Release JPEG decompression object */
  134. //釋放解碼結構的空間內容
  135. jpeg_destroy_decompress(&cinfo);
  136. //uninit_lcd(); //關閉LCD
  137. //釋放jpeg文件的資源
  138. fclose(infile);
  139. //結束
  140. return 1;
  141. }
  142. int show_bmp(char *file) //顯示一張圖片 思路
  143. {
  144. int ret,x,y,i;
  145. //注意:因爲此LCD是一個像素包含兩個字節,所以要用short,用int類型則會出錯
  146. short lcdbuf[ 480* 272* 2];
  147. char temp[ 3] = { 0};
  148. char bmpbuf[ 480* 272* 3];
  149. int bmp = open(file,O_RDONLY); //2.打開bmp圖片
  150. if(bmp == -1)
  151. {
  152. perror( "open BMP Err");
  153. return -1;
  154. }
  155. lseek(bmp, 54, SEEK_SET); //偏移54個字節
  156. ret = read(bmp,bmpbuf, 480* 272* 3); //3.讀取bmp信息
  157. if(ret == -1)
  158. {
  159. perror( "read BMP Err");
  160. return -1;
  161. }
  162. //4.change 24bit RGB to 16bit 思路:r:g:b = 5:6:5
  163. //取r的高五位,g的高6位,b的高5位,或運算,重新組成一個新的16位
  164. for(y= 0,i= 0;y< 272;y++)
  165. {
  166. for(x= 0;x< 480;x++,i+= 3)
  167. {
  168. // B G R
  169. lcdbuf[( 271-y)* 480+x] = (bmpbuf[i])>> 3 | (bmpbuf[i+ 1]>> 2)<< 5 | (bmpbuf[i+ 2]>> 3) << 11;
  170. //將24位轉化爲16位算法
  171. }
  172. }
  173. memcpy(fb_mem,lcdbuf, 480* 272* 2);
  174. //ret = write(lcd,lcdbuf,480*272*2); //5.往LCD寫數據
  175. if(ret == -1)
  176. {
  177. perror( "write LCD Err");
  178. return -1;
  179. }
  180. //close(lcd); //6.關閉lcd,在專門的關閉初始化函數實現
  181. close(bmp); //7.關閉圖片
  182. return 0;
  183. }
  184. int main()
  185. {
  186. init_lcd(); //LCD 初始化
  187. printf( "my Project!\n");
  188. show_bmp( "picture_3.bmp");
  189. sleep( 3);
  190. show_JPEG_file( "test.jpg");
  191. uninit_lcd(); //關閉LCD
  192. return 0;
  193. }

步驟如下

1.

2.

3.