內核版本: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代碼),詳情請看代碼註釋
-
#include <stdio.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <unistd.h>
-
#include <linux/input.h>
-
#include <sys/mman.h>
-
-
//jpeg庫的標準頭文件
-
#include <stdio.h>
-
#include "jpeglib.h"
-
#include <setjmp.h>
-
-
int lcd;
//全局變量
-
short * fb_mem;
//這塊的數據類型一定要注意,如果使用就要跟一個像素匹配兩個字節(一個像素由多少個字節組成有關)
-
-
/*jpeg顯示所需的結構體*/
-
struct my_error_mgr {
-
struct jpeg_error_mgr pub;
/* "public" fields */
-
-
jmp_buf setjmp_buffer;
/* for return to caller */
-
};
-
-
typedef
struct my_error_mgr * my_error_ptr;
-
-
-
/*jpeg顯示所需的結構體*/
-
METHODDEF(
void)
-
my_error_exit (j_common_ptr cinfo)
-
{
-
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
-
my_error_ptr myerr = (my_error_ptr) cinfo->err;
-
-
/* Always display the message. */
-
/* We could postpone this until after returning, if we chose. */
-
(*cinfo->err->output_message) (cinfo);
-
-
/* Return control to the setjmp point */
-
longjmp(myerr->setjmp_buffer,
1);
-
}
-
-
-
int init_lcd()
-
{
-
lcd = open(
"/dev/fb0",O_RDWR);
//1.打開LCD設備
-
if(lcd ==
-1)
-
{
-
perror(
"open LCD Err");
-
return
-1;
-
}
-
printf(
"request LCD OK!\n");
-
-
//映射顯存
-
fb_mem = mmap(
NULL,
//映射後的地址,NULL系統自動分配
-
480*
272*
2,
//映射的大小,字節
-
PROT_READ|PROT_WRITE,
//映射的操作
-
MAP_SHARED,
//映射的共享操作 MAP_SHARED MAP_PRIVATE
-
lcd,
//目標設備的文件描述符
-
0);
//映射的數據地址偏移量,默認0
-
-
if(fb_mem == MAP_FAILED)
-
{
-
perror(
"LCD mmap");
-
return
-1;
-
}
-
}
-
-
int uninit_lcd()
-
{
-
close(lcd);
//6.關閉LCD
-
/*取消映射*/
-
munmap(fb_mem,
//映射後的操作地址
-
480*
272*
2);
//映射的大小
-
}
-
-
// 解碼 JPEG 圖片,並轉成 RGB 值
-
int show_JPEG_file (char * filename)
-
{
-
int i,x;
-
//unsigned int lcdbuf[800];
-
short lcdbuf[
480];
//注意,這裏lcdbuf是2個字節的數據類型,因爲一個此lcd一個像素用兩個字節表示
-
//JPEG 解碼信息結構體
-
struct jpeg_decompress_struct cinfo;
-
-
struct my_error_mgr jerr;
-
/* More stuff */
-
FILE * infile;
/* source file */
-
JSAMPARRAY buffer;
/* Output row buffer */
-
int row_stride;
/* physical row width in output buffer */
-
-
-
//打開要解碼的JPG圖片文件
-
if ((infile = fopen(filename,
"rb")) ==
NULL) {
-
fprintf(
stderr,
"can't open %s\n", filename);
-
return
0;
-
}
-
-
/* Step 1: allocate and initialize JPEG decompression object */
-
//分配並初始化解碼結構體信息
-
cinfo.err = jpeg_std_error(&jerr.pub);
-
jerr.pub.error_exit = my_error_exit;
-
-
//判斷文件類型並做出錯處理
-
if (setjmp(jerr.setjmp_buffer)) {
-
/* If we get here, the JPEG code has signaled an error.
-
* We need to clean up the JPEG object, close the input file, and return.
-
*/
-
jpeg_destroy_decompress(&cinfo);
-
fclose(infile);
-
return
0;
-
}
-
-
/* Now we can initialize the JPEG decompression object. */
-
jpeg_create_decompress(&cinfo);
-
-
/* Step 2: specify data source (eg, a file) */
-
//指定解碼的源文件關聯
-
jpeg_stdio_src(&cinfo, infile);
-
-
/* Step 3: read file parameters with jpeg_read_header() */
-
//獲取jpeg文件的頭信息,獲取文件大小及尺寸
-
(
void) jpeg_read_header(&cinfo, TRUE);
-
-
/* Step 4: set parameters for decompression */
-
//設置必要的解碼信息,可省略
-
-
/* Step 5: Start decompressor */
-
//開始解碼
-
(
void) jpeg_start_decompress(&cinfo);
-
-
/* JSAMPLEs per row in output buffer */
-
// 設置每行jpg像素數據解碼的大小
-
row_stride = cinfo.output_width * cinfo.output_components;
-
-
//加載jpg文件的數據源,並賦值數據地址到buffer
-
buffer = (*cinfo.mem->alloc_sarray)
-
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride,
1);
-
-
/* Step 6: while (scan lines remain to be read) */
-
/* jpeg_read_scanlines(...); */
-
-
//逐行解碼
-
while (cinfo.output_scanline < cinfo.output_height)
-
{
-
//讀取新的一行的jpeg數據
-
(
void) jpeg_read_scanlines(&cinfo, buffer,
1);
-
//將解碼後的數據進行處理(自定義)
-
//put_scanline_someplace(buffer[0], row_stride);
-
//如何將解碼後的每行像素的RGB數據(buffer[0]),寫入顯存
-
//fb_mem <----- buffer[0](data) row_stride(size)
-
for(x=
0,i=
0;x<
480;x++,i+=
3)
-
//for(x=0,i=0;x<800;x++,i+=3)
-
{
//r g b
-
lcdbuf[x] = ((buffer[
0][i])>>
3) <<
11 | ((buffer[
0][i+
1])>>
2) <<
5 | buffer[
0][i+
2]>>
3;
-
//算法:jpg解碼後的24rgb圖像轉化爲16位的rgb圖像(此4.3寸LCD,1個像素由2個字節組成)
-
}
-
-
memcpy((fb_mem+(cinfo.output_scanline
-1)*
480),lcdbuf,
sizeof(lcdbuf));
-
}
-
-
/* Step 7: Finish decompression */
-
//結束解碼
-
(
void) jpeg_finish_decompress(&cinfo);
-
-
/* Step 8: Release JPEG decompression object */
-
//釋放解碼結構的空間內容
-
jpeg_destroy_decompress(&cinfo);
-
-
//uninit_lcd(); //關閉LCD
-
//釋放jpeg文件的資源
-
fclose(infile);
-
-
//結束
-
return
1;
-
}
-
-
-
int show_bmp(char *file) //顯示一張圖片 思路
-
{
-
int ret,x,y,i;
-
//注意:因爲此LCD是一個像素包含兩個字節,所以要用short,用int類型則會出錯
-
short lcdbuf[
480*
272*
2];
-
char temp[
3] = {
0};
-
char bmpbuf[
480*
272*
3];
-
-
int bmp = open(file,O_RDONLY);
//2.打開bmp圖片
-
if(bmp ==
-1)
-
{
-
perror(
"open BMP Err");
-
return
-1;
-
}
-
-
lseek(bmp,
54, SEEK_SET);
//偏移54個字節
-
-
ret = read(bmp,bmpbuf,
480*
272*
3);
//3.讀取bmp信息
-
if(ret ==
-1)
-
{
-
perror(
"read BMP Err");
-
return
-1;
-
}
-
-
//4.change 24bit RGB to 16bit 思路:r:g:b = 5:6:5
-
//取r的高五位,g的高6位,b的高5位,或運算,重新組成一個新的16位
-
for(y=
0,i=
0;y<
272;y++)
-
{
-
for(x=
0;x<
480;x++,i+=
3)
-
{
-
// B G R
-
lcdbuf[(
271-y)*
480+x] = (bmpbuf[i])>>
3 | (bmpbuf[i+
1]>>
2)<<
5 | (bmpbuf[i+
2]>>
3) <<
11;
-
//將24位轉化爲16位算法
-
-
}
-
}
-
-
memcpy(fb_mem,lcdbuf,
480*
272*
2);
-
//ret = write(lcd,lcdbuf,480*272*2); //5.往LCD寫數據
-
-
if(ret ==
-1)
-
{
-
perror(
"write LCD Err");
-
return
-1;
-
}
-
-
//close(lcd); //6.關閉lcd,在專門的關閉初始化函數實現
-
close(bmp);
//7.關閉圖片
-
-
return
0;
-
}
-
-
int main()
-
{
-
init_lcd();
//LCD 初始化
-
printf(
"my Project!\n");
-
-
show_bmp(
"picture_3.bmp");
-
sleep(
3);
-
show_JPEG_file(
"test.jpg");
-
uninit_lcd();
//關閉LCD
-
-
return
0;
-
}
-
步驟如下
1.
2.
3.