1. 前言
在開發板上如果想要顯示jpeg格式的圖片,必須用到libjpeg庫,不可能自己去編寫jpg的解碼代碼。
libjpeg是一個完全用C語言編寫的庫,包含了被廣泛使用的JPEG解碼、JPEG編碼和其他的JPEG功能的實現。這個庫由獨立JPEG工作組維護。
源碼獲取地址: www.ijg.org/
2. 安裝編譯步驟
下面介紹libjpeg庫交叉編譯器的詳細步驟。
①下載源碼包,將源碼包拷貝到linux系統下。比如:jpegsrc.v9b.tar.gz
?
②解碼源碼包
[root@xiaolong jpeg-9b]# tar xf jpegsrc.v9b.tar.gz
?
③配置源碼
[root@xiaolong jpeg-9b]#
./configure --prefix=/usr/local/lib CC=arm-linux-gcc --host=arm-linux --enable-shared --enable-static
注意:
/usr/local/lib 表示指定源碼最終安裝的路徑。
?
④編譯源碼
[root@xiaolong jpeg-9b]# make
?
⑤安裝源碼
[root@xiaolong jpeg-9b]# make install
?
安裝好的目錄如下:(/usr/local/lib)
[root@xiaolong lib]# ls
bin include lib share
?
文件結構:
[root@xiaolong lib]# pwd
/usr/local/lib
[root@xiaolong lib]# tree ./
./
├── bin
│ ├── cjpeg
│ ├── djpeg
│ ├── jpegtran
│ ├── rdjpgcom
│ └── wrjpgcom
├── include
│ ├── jconfig.h
│ ├── jerror.h
│ ├── jmorecfg.h
│ └── jpeglib.h
├── lib
│ ├── libjpeg.a
│ ├── libjpeg.la
│ ├── libjpeg.so -> libjpeg.so.9.2.0
│ ├── libjpeg.so.9 -> libjpeg.so.9.2.0
│ └── libjpeg.so.9.2.0
└── share
└── man
└── man1
├── cjpeg.1
├── djpeg.1
├── jpegtran.1
├── rdjpgcom.1
└── wrjpgcom.1
?
6 directories, 19 files
復制代碼
3. 使用步驟
1.將以下幾個頭文件拷貝到需要編譯的工程目錄下:
jmorecfg.h、jpeglib.h、jerror.h、jconfig.h
?
2.將以下頭文件加到工程中:
#include "jpeglib.h"
?
3./將usr/local/lib目錄下的生成的庫文件拷貝到開發板的lib目錄下。
?
4.編譯選擇--任意一種:
arm-linux-gcc -o app show_jpeg.c -L/usr/local/lib
arm-linux-gcc -o app show_jpeg.c -l:libjpeg.so.9
arm-linux-gcc show_jpeg.c -ljpeg -static -o app
?
show_jpeg.c是要編譯的源文件
app 是生成的目標文件。
-static 表示靜態生成
#include 頭文件定義解壓縮使用的數據結構信息。
復制代碼
4. 使用案例
4.1 使用libjpg庫編碼-RGB數據保存為jpg圖片
下面這個是利用libjpeg封裝的一個方便函數,用于將傳入的rgb數據壓縮編碼成jpg文件保存,一般用與屏幕截屏、相機拍照等地方。
#include
#define JPEG_QUALITY 100 //圖片質量
int savejpg(uchar *pdata, char *jpg_file, int width, int height)
{ //分別為RGB數據,要保存的jpg文件名,圖片長寬
int depth = 3;
JSAMPROW row_pointer[1];//指向一行圖像數據的指針
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *outfile;
cinfo.err = jpeg_std_error(&jerr);//要首先初始化錯誤信息
//* Now we can initialize the JPEG compression object.
jpeg_create_compress(&cinfo);
if ((outfile = fopen(jpg_file, "wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", jpg_file);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = width; //* image width and height, in pixels
cinfo.image_height = height;
cinfo.input_components = depth; //* # of color components per pixel
cinfo.in_color_space = JCS_RGB; //* colorspace of input image
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); //* limit to baseline-JPEG values
jpeg_start_compress(&cinfo, TRUE);
int row_stride = width * 3;
while (cinfo.next_scanline < cinfo.image_height)
? ? {
? ? ? ? ? ? ?row_pointer[0] = (JSAMPROW)(pdata + cinfo.next_scanline * row_stride);//一行一行數據的傳,jpeg為大端數據格式
? ? ? ? ? ? ?jpeg_write_scanlines(&cinfo, row_pointer, 1);
? ? }
?
? ? ?jpeg_finish_compress(&cinfo);
? ? ?jpeg_destroy_compress(&cinfo);//這幾個函數都是固定流程
? ? ?fclose(outfile);
? ? ?return 0;
?}
復制代碼
4.2 LCD顯示jpg格式圖片
下面代碼利用libjpeg庫解碼傳入的jpg文件,得到rgb數據,再繪制到LCD屏上顯示。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
?
// 24位色和16位色轉換宏
// by cheungmine
#define RGB888_TO_RGB565(r,g,b) ((WORD)(((WORD(r)<<8)&0xF800)|((WORD(g)<<3)&0x7E0)|((WORD(b) >> 3))))
#define RGB_TO_RGB565(rgb) ((WORD)(((((WORD)((rgb)>>3))&(0x1F))<<11)|((((WORD)((rgb)>>10))&(0x3F))<<5)|(((WORD)((rgb)>>19))&(0x1F))))
#define RGB888_TO_RGB555(r,g,b) ((WORD)(((WORD(r)<<7)&0x7C00)|((WORD(g)<<2)&0x3E0)|((WORD(b)>>3))))
#define RGB_TO_RGB555(rgb) ((WORD)(((((WORD)((rgb)>>3))&(0x1F))<<10)|((((WORD)((rgb)>>11))&(0x1F))<<5)|(((WORD)((rgb)>>19))&(0x1F))))
#define RGB555_TO_RGB(rgb555) ((DWORD)(((BYTE)(((rgb555)>>7)&0xF8)|((WORD)((BYTE)(((rgb555)>>2)&0xF8))<<8))|(((DWORD)(BYTE)(((rgb555)<<3)&0xF8))<<16)))
?#define RGB565_TO_RGB(rgb565) ? ((DWORD)(((BYTE)((((rgb565)&0xF800)>>11)<<3)|((WORD)((BYTE)((((rgb565)&0x07E0)>>5)<<2))<<8))|(((DWORD)(BYTE)(((rgb565)&0x001F)<<3))<<16)))
?unsigned short ?rgb888_to_rgb555(unsigned char red,unsigned char green,unsigned char blue);
?unsigned short ?rgb888_to_rgb565(unsigned char red,unsigned char green,unsigned char blue);
? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?/*--------------------------------------------------------------
? JPEG圖片顯示
?---------------------------------------------------------------*/
?static unsigned char *fbmem = NULL;
?static struct fb_var_screeninfo var;//定義可變參數結構體來接收驅動傳過來的可變參數結構體
?static struct fb_fix_screeninfo fix;//定義固定參數結構體來接收驅動傳過來的固定參
??
?//顯示JPEG
?int show_jpeg(unsigned char *file)
?{
? ? ?struct jpeg_decompress_struct cinfo; //存放圖像的數據
? ? ?struct jpeg_error_mgr jerr; //存放錯誤信息
? ? ?FILE ? ? ? ? ? *infile;
? ? ?unsigned int *dst=fbmem;
? ? ?unsigned char ?*buffer;
? ? ?unsigned int ? ?x;
? ? ?unsigned int ? ?y;
? ? ?/*
? ? ?* 打開圖像文件
? ? ?*/
? ? ?if ((infile = fopen(file, "rb")) == NULL) {
? ? ? ? ?fprintf(stderr, "open %s failed\n", file);
? ? ? ? ?exit(-1);
? ? }
??
? ? ?/*
? ? ? * init jpeg壓縮對象錯誤處理程序
? ? ? */
? ? ?cinfo.err = jpeg_std_error(&jerr); //初始化標準錯誤,用來存放錯誤信息
? ? ?jpeg_create_decompress(&cinfo); ? ?//創建解壓縮結構信息
? ? ?
? ? ?
? ? ?/*
? ? ? * 將jpeg壓縮對象綁定到infile
? ? ? */
? ? ?jpeg_stdio_src(&cinfo, infile);
??
? ? ?/*
? ? ? * 讀jpeg頭
? ? ? */
? ? ?jpeg_read_header(&cinfo, TRUE);
? ?
? ? ?/*
? *開始解壓
? */
? ? ?jpeg_start_decompress(&cinfo);
? ? ?
? ? ?printf("JPEG高度: %d\n",cinfo.output_height);
? ? ?printf("JPEG寬度: %d\n",cinfo.output_width);
? ? ?printf("JPEG顏色位數(字節單位): %d\n",cinfo.output_components);
? ? ?
? ? ?//為一條掃描線上的像素點分配存儲空間
? ? ?buffer = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);
? ? ?y = 0;
??
? ? ?//將圖片內容顯示到framebuffer上
? ? ?while (cinfo.output_scanline < cinfo.output_height)
? ? {
? ? ? ? ?
? ? ? ? ? //讀取一行的數據 ? ?
? ? ? ? ?jpeg_read_scanlines(&cinfo, &buffer, 1);
? ? ? ? ?
? ? ? ? ?//判斷LCD屏的映射空間像素位數
? ? ? ? ?if (var.bits_per_pixel == 32)
? ? ? ? {
? ? ? ? ? ? ?unsigned int ?color;
? ? ? ? ? ? ?for (x = 0; x < cinfo.output_width; x++) {
? ? ? ? ? ? ? ? ?color = buffer[x * 3 + 0] << 16 ?|
? ? ? ? ? ? ? ? ? ? ? ? ?buffer[x * 3 + 1] << 8 ? |
? ? ? ? ? ? ? ? ? ? ? ? ?buffer[x * 3 + 2] << 0;
? ? ? ? ? ? ? ? ?dst = ((unsigned int *) fbmem + y * var.xres + x);
? ? ? ? ? ? ? ? ?*dst = color;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? ?y++; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 顯示下一個像素點
? ? }
? ? ?
? ? ?/*
? ? ? * 完成解壓,摧毀解壓對象
? ? ? */
? ? ?jpeg_finish_decompress(&cinfo); //結束解壓
? ? ?jpeg_destroy_decompress(&cinfo); //釋放結構體占用的空間
??
? ? ?/*
? ? ? * 釋放內存緩沖區
? ? ? */
? ? ?free(buffer);
??
? ? ?/*
? ? ? * 釋放內存緩沖區
? ? ? */
? ? ?fclose(infile);
? ? ?return 0;
?}
??
?/*映射LCD顯示的內存空間*/
?unsigned char * fmem(unsigned char *fbname)
?{
? int fb;
? unsigned char *mem;
? fb = open(fbname,2);
? if(fb<0)
? {
? printf("open fbdev is error!!!\n");
? return NULL;
? }
? ioctl(fb,FBIOGET_VSCREENINFO,&var);//獲取固定參數結構體放在var結構體中
? ioctl(fb,FBIOGET_FSCREENINFO,&fix);//獲取固定參數,存放在fix結構體中
? mem = (unsigned char *)mmap(NULL,fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
? if(mem == (unsigned char *)-1)
? {
? printf("fbmmap is error!!!\n");
? munmap(mem,fix.smem_len);
? return NULL;
? }
? return mem;
?}
??
??
?int main (int argc,char** argv) //./a.out /dev/fb0 xxx.bmp
?{
? int fb ,i=4;
? char key;
? unsigned char * bmpmem;
? if(argc!=3)
? {
? printf("Usage: ./%s \n",argv[0]);
? return -1;
? }
? fbmem = ?fmem(argv[1]); ? //將緩沖設備映射到內存進行寫入
? memset(fbmem,0x00,fix.smem_len);//清屏函數 往映射的地址填充fix.sem_len大小的0xff顏色進去
? show_jpeg(argv[2]); ? ? ? ? ?//程序運行時顯示主界面
? return 0;
?}
審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
Linux
+關注
關注
87文章
11304瀏覽量
209483 -
C語言
+關注
關注
180文章
7604瀏覽量
136813 -
編譯
+關注
關注
0文章
657瀏覽量
32870
發布評論請先 登錄
相關推薦
【芯靈思A83T試用體驗】3、交叉編譯OpenCV2.4.9
opencv-unix到Linux宿主機上,利用交叉編譯器arm-linux-gcc來將opencv編譯成可以在ARM平臺上運行的鏈接
發表于 05-21 22:17
【NanoPi NEO2試用體驗】libjpeg庫的編譯和安裝
的是libjpeg。Libjpeg是一款常用的jpeg圖像壓縮和解壓的函數庫,安裝libjpeg可以直接使用apt-get等命令也可以下載libjp
發表于 06-22 09:12
【Linux】嵌入式Linux系統的移植(上篇:交叉編譯器、連接方式)
的移植要點搭建交叉開發環境bootloader的選擇與移植kernel的設置、編譯、移植和調試根文件系統的制作嵌入式Linux系統的移植基本步驟確定目標機、主機的連接方式安裝
發表于 11-01 16:57
?14次下載
嵌入式Linux開發環境搭建-(7)嵌入式Linux開發板截屏工具gsnap移植
嵌入式Linux開發板截屏工具gsnap移植PC機:ubuntu16.04.2 LTS開發板:i.MX6UL交叉編譯器:arm-
發表于 11-01 17:38
?12次下載
嵌入式Linux開發環境搭建-(4)安裝交叉編譯工具鏈
在ubuntu16.04.2中,安裝交叉編譯工具鏈在ubuntu中進行嵌入式應用程序開發,安裝交叉編譯工具鏈是不可缺少的一個環節。PC操作系
發表于 11-02 11:06
?18次下載
嵌入式Linux開發環境搭建-(6)交叉編譯QT4.8.7源碼生成qmake工具
交叉編譯QT4.8.7源碼生成qmake工具TQ-i.MX6UL使用的QT版本是QT4.8.7,板卡出廠前附帶的開發資料中,天嵌官方沒有為開發者編譯
發表于 11-02 13:21
?3次下載
嵌入式Linux開發環境搭建-3-安裝交叉編譯工具鏈
嵌入式Linux開發環境搭建-安裝交叉編譯工具鏈1、下載2、解壓3、設置環境變量參考文檔ubuntu下安裝交叉
發表于 11-02 13:21
?12次下載
Linux下播放器開發-交叉編譯Mplayer
如何將MplayerJ交叉編譯移植到嵌入式開發板上運行,在命令行上正常的播放視頻,LCD屏采用的幀緩沖驅動框架渲染圖像。
Linux應用開發-串口下載命令rzsz交叉編譯
rz/sz工具是通過Zmodem協議傳輸文件的命令,常用于Linux與windows之前的數據傳輸。
這篇文章就介紹如何在交叉編譯rz/sz命令,并在Linux
Linux交叉編譯選項與源碼與目標文件分離
交叉編譯選項 編譯Linux,通常只需要運行 make menuconfig 配置要編譯的模塊,然后運行 make 。
評論