1. 前言
在開發(fā)板上如果想要顯示jpeg格式的圖片,必須用到libjpeg庫,不可能自己去編寫jpg的解碼代碼。
libjpeg是一個完全用C語言編寫的庫,包含了被廣泛使用的JPEG解碼、JPEG編碼和其他的JPEG功能的實現(xiàn)。這個庫由獨(dú)立JPEG工作組維護(hù)。
源碼獲取地址: www.ijg.org/
2. 安裝編譯步驟
下面介紹libjpeg庫交叉編譯器的詳細(xì)步驟。
①下載源碼包,將源碼包拷貝到linux系統(tǒng)下。比如: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
?
文件結(jié)構(gòu):
[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
復(fù)制代碼
3. 使用步驟
1.將以下幾個頭文件拷貝到需要編譯的工程目錄下:
jmorecfg.h、jpeglib.h、jerror.h、jconfig.h
?
2.將以下頭文件加到工程中:
#include "jpeglib.h"
?
3./將usr/local/lib目錄下的生成的庫文件拷貝到開發(fā)板的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 是生成的目標(biāo)文件。
-static 表示靜態(tài)生成
#include 頭文件定義解壓縮使用的數(shù)據(jù)結(jié)構(gòu)信息。
復(fù)制代碼
4. 使用案例
4.1 使用libjpg庫編碼-RGB數(shù)據(jù)保存為jpg圖片
下面這個是利用libjpeg封裝的一個方便函數(shù),用于將傳入的rgb數(shù)據(jù)壓縮編碼成jpg文件保存,一般用與屏幕截屏、相機(jī)拍照等地方。
#include
#define JPEG_QUALITY 100 //圖片質(zhì)量
int savejpg(uchar *pdata, char *jpg_file, int width, int height)
{ //分別為RGB數(shù)據(jù),要保存的jpg文件名,圖片長寬
int depth = 3;
JSAMPROW row_pointer[1];//指向一行圖像數(shù)據(jù)的指針
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);//一行一行數(shù)據(jù)的傳,jpeg為大端數(shù)據(jù)格式
? ? ? ? ? ? ?jpeg_write_scanlines(&cinfo, row_pointer, 1);
? ? }
?
? ? ?jpeg_finish_compress(&cinfo);
? ? ?jpeg_destroy_compress(&cinfo);//這幾個函數(shù)都是固定流程
? ? ?fclose(outfile);
? ? ?return 0;
?}
復(fù)制代碼
4.2 LCD顯示jpg格式圖片
下面代碼利用libjpeg庫解碼傳入的jpg文件,得到rgb數(shù)據(jù),再繪制到LCD屏上顯示。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
?
// 24位色和16位色轉(zhuǎn)換宏
// 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;//定義可變參數(shù)結(jié)構(gòu)體來接收驅(qū)動傳過來的可變參數(shù)結(jié)構(gòu)體
?static struct fb_fix_screeninfo fix;//定義固定參數(shù)結(jié)構(gòu)體來接收驅(qū)動傳過來的固定參
??
?//顯示JPEG
?int show_jpeg(unsigned char *file)
?{
? ? ?struct jpeg_decompress_struct cinfo; //存放圖像的數(shù)據(jù)
? ? ?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); //初始化標(biāo)準(zhǔn)錯誤,用來存放錯誤信息
? ? ?jpeg_create_decompress(&cinfo); ? ?//創(chuàng)建解壓縮結(jié)構(gòu)信息
? ? ?
? ? ?
? ? ?/*
? ? ? * 將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顏色位數(shù)(字節(jié)單位): %d\n",cinfo.output_components);
? ? ?
? ? ?//為一條掃描線上的像素點(diǎn)分配存儲空間
? ? ?buffer = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);
? ? ?y = 0;
??
? ? ?//將圖片內(nèi)容顯示到framebuffer上
? ? ?while (cinfo.output_scanline < cinfo.output_height)
? ? {
? ? ? ? ?
? ? ? ? ? //讀取一行的數(shù)據(jù) ? ?
? ? ? ? ?jpeg_read_scanlines(&cinfo, &buffer, 1);
? ? ? ? ?
? ? ? ? ?//判斷LCD屏的映射空間像素位數(shù)
? ? ? ? ?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++; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 顯示下一個像素點(diǎn)
? ? }
? ? ?
? ? ?/*
? ? ? * 完成解壓,摧毀解壓對象
? ? ? */
? ? ?jpeg_finish_decompress(&cinfo); //結(jié)束解壓
? ? ?jpeg_destroy_decompress(&cinfo); //釋放結(jié)構(gòu)體占用的空間
??
? ? ?/*
? ? ? * 釋放內(nèi)存緩沖區(qū)
? ? ? */
? ? ?free(buffer);
??
? ? ?/*
? ? ? * 釋放內(nèi)存緩沖區(qū)
? ? ? */
? ? ?fclose(infile);
? ? ?return 0;
?}
??
?/*映射LCD顯示的內(nèi)存空間*/
?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);//獲取固定參數(shù)結(jié)構(gòu)體放在var結(jié)構(gòu)體中
? ioctl(fb,FBIOGET_FSCREENINFO,&fix);//獲取固定參數(shù),存放在fix結(jié)構(gòu)體中
? 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]); ? //將緩沖設(shè)備映射到內(nèi)存進(jìn)行寫入
? memset(fbmem,0x00,fix.smem_len);//清屏函數(shù) 往映射的地址填充fix.sem_len大小的0xff顏色進(jìn)去
? show_jpeg(argv[2]); ? ? ? ? ?//程序運(yùn)行時顯示主界面
? return 0;
?}
審核編輯:湯梓紅
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209321 -
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136683 -
編譯
+關(guān)注
關(guān)注
0文章
657瀏覽量
32852
發(fā)布評論請先 登錄
相關(guān)推薦
評論