RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux應(yīng)用開發(fā)-libjpeg庫交叉編譯與使用

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 09:18 ? 次閱讀

1. 前言

在開發(fā)板上如果想要顯示jpeg格式的圖片,必須用到libjpeg庫,不可能自己去編寫jpg的解碼代碼。

libjpeg是一個完全用C語言編寫的庫,包含了被廣泛使用的JPEG解碼、JPEG編碼和其他的JPEG功能的實現(xiàn)。這個庫由獨(dú)立JPEG工作組維護(hù)。

image-20220124161832316

源碼獲取地址: www.ijg.org/

image-20220124161130968

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屏上顯示。

image-20220124161712017
#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;
?}

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11292

    瀏覽量

    209321
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136683
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    657

    瀏覽量

    32852
收藏 人收藏

    評論

    相關(guān)推薦

    Linux系統(tǒng)下交叉編譯工具鏈的安裝方法

    今天主要和大家聊一聊,如何使用Linux系統(tǒng)下的交叉編譯工具鏈的方法。
    發(fā)表于 11-21 09:30 ?3434次閱讀

    【芯靈思A83T試用體驗】3、交叉編譯OpenCV2.4.9

    opencv-unix到Linux宿主機(jī)上,利用交叉編譯器arm-linux-gcc來將opencv編譯成可以在ARM平臺上運(yùn)行的鏈接
    發(fā)表于 05-21 22:17

    【NanoPi NEO2試用體驗】libjpeg編譯和安裝

    的是libjpeg。Libjpeg是一款常用的jpeg圖像壓縮和解壓的函數(shù),安裝libjpeg可以直接使用apt-get等命令也可以下載libjp
    發(fā)表于 06-22 09:12

    交叉編譯linux內(nèi)核(raspberry_3.6.y)

    一步一步教你交叉編譯linux內(nèi)核,RPI的內(nèi)核編譯教程,小眾的東西了
    發(fā)表于 11-03 17:58 ?0次下載

    arm-linux交叉編譯環(huán)境解析

    交叉編譯環(huán)境介紹 交叉編譯是嵌入式開發(fā)過程中的一項重要技術(shù),它的主要特征是某機(jī)器中執(zhí)行的程序代碼不是在本機(jī)
    發(fā)表于 10-31 11:26 ?7次下載

    Linux】嵌入式Linux系統(tǒng)的移植(上篇:交叉編譯器、連接方式)

    的移植要點(diǎn)搭建交叉開發(fā)環(huán)境bootloader的選擇與移植kernel的設(shè)置、編譯、移植和調(diào)試根文件系統(tǒng)的制作嵌入式Linux系統(tǒng)的移植基本步驟確定目標(biāo)機(jī)、主機(jī)的連接方式安裝
    發(fā)表于 11-01 16:57 ?14次下載
    【<b class='flag-5'>Linux</b>】嵌入式<b class='flag-5'>Linux</b>系統(tǒng)的移植(上篇:<b class='flag-5'>交叉</b><b class='flag-5'>編譯</b>器、連接方式)

    嵌入式Linux開發(fā)環(huán)境搭建-(7)嵌入式Linux開發(fā)板截屏工具gsnap移植

    嵌入式Linux開發(fā)板截屏工具gsnap移植PC機(jī):ubuntu16.04.2 LTS開發(fā)板:i.MX6UL交叉編譯器:arm-
    發(fā)表于 11-01 17:38 ?12次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>環(huán)境搭建-(7)嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>板截屏工具gsnap移植

    嵌入式Linux開發(fā)環(huán)境搭建-(4)安裝交叉編譯工具鏈

    在ubuntu16.04.2中,安裝交叉編譯工具鏈在ubuntu中進(jìn)行嵌入式應(yīng)用程序開發(fā),安裝交叉編譯工具鏈?zhǔn)遣豢扇鄙俚囊粋€環(huán)節(jié)。PC操作系
    發(fā)表于 11-02 11:06 ?18次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>環(huán)境搭建-(4)安裝<b class='flag-5'>交叉</b><b class='flag-5'>編譯</b>工具鏈

    嵌入式Linux開發(fā)環(huán)境搭建-(6)交叉編譯QT4.8.7源碼生成qmake工具

    交叉編譯QT4.8.7源碼生成qmake工具TQ-i.MX6UL使用的QT版本是QT4.8.7,板卡出廠前附帶的開發(fā)資料中,天嵌官方?jīng)]有為開發(fā)編譯
    發(fā)表于 11-02 13:21 ?3次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>環(huán)境搭建-(6)<b class='flag-5'>交叉</b><b class='flag-5'>編譯</b>QT4.8.7源碼生成qmake工具

    嵌入式Linux開發(fā)環(huán)境搭建-3-安裝交叉編譯工具鏈

    嵌入式Linux開發(fā)環(huán)境搭建-安裝交叉編譯工具鏈1、下載2、解壓3、設(shè)置環(huán)境變量參考文檔ubuntu下安裝交叉
    發(fā)表于 11-02 13:21 ?12次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>環(huán)境搭建-3-安裝<b class='flag-5'>交叉</b><b class='flag-5'>編譯</b>工具鏈

    Linux下播放器開發(fā)-交叉編譯Mplayer

    如何將MplayerJ交叉編譯移植到嵌入式開發(fā)板上運(yùn)行,在命令行上正常的播放視頻,LCD屏采用的幀緩沖驅(qū)動框架渲染圖像。
    的頭像 發(fā)表于 08-14 09:12 ?2862次閱讀

    Linux應(yīng)用開發(fā)-串口下載命令rzsz交叉編譯

    rz/sz工具是通過Zmodem協(xié)議傳輸文件的命令,常用于Linux與windows之前的數(shù)據(jù)傳輸。 這篇文章就介紹如何在交叉編譯rz/sz命令,并在Linux
    的頭像 發(fā)表于 08-14 09:20 ?2471次閱讀

    Linux交叉編譯選項與源碼與目標(biāo)文件分離

    交叉編譯選項 編譯Linux,通常只需要運(yùn)行 make menuconfig 配置要編譯的模塊,然后運(yùn)行 make 。
    的頭像 發(fā)表于 09-27 11:48 ?833次閱讀

    linux4.1.15交叉編譯鏈描述及使用方法

    飛凌嵌入式OKMX6ULL-C開發(fā)Linux4.1.15交叉編譯鏈描述及使用方法
    發(fā)表于 03-22 11:18 ?3次下載

    linux開發(fā)板如何編譯curl

    Linux開發(fā)板上編譯 curl 通常涉及到幾個步驟,包括準(zhǔn)備開發(fā)環(huán)境、下載源代碼、配置編譯
    的頭像 發(fā)表于 08-30 15:33 ?596次閱讀
    RM新时代网站-首页