如何在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.