一、libjpeg 簡介
libjpeg 是一個用于處理 JPEG(Joint Photographic Experts Group)圖像文件的開源 C 庫,主要功能包括 JPEG 圖像的編碼(壓縮)與解碼(解壓縮)。它由 Independent JPEG Group (IJG) 開發,廣泛用于嵌入式系統、圖像編輯軟件、瀏覽器等需要處理 JPEG 圖像的場景。
IJG 是一個非正式組織,負責編寫和分發廣泛使用的免費 JPEG 圖像壓縮庫。第一個版本于 1991 年 10 月 7 日發布。當前版本是 2024 年 1 月 14 日發布的 9f 版本。這為許多應用程序的 JPEG 支持奠定了穩定而堅實的基礎。
二、JPEG 格式簡介
JPEG 是一種有損壓縮的圖像格式,設計目的是在盡可能小的文件大小下保留盡可能高的視覺質量。JPEG 壓縮的核心基于以下步驟:
- 顏色空間轉換:從 RGB 轉為 YCbCr 色彩空間,分離亮度(Y)與色度(Cb、Cr)信息。
- 采樣率降采樣:降低色度分量的分辨率,減少數據量。
- 離散余弦變換 (DCT):將圖像塊從空間域轉換到頻率域。
- 量化:通過對高頻分量進行更強的壓縮來減少不明顯的細節。
- 熵編碼:使用霍夫曼編碼或算術編碼進一步壓縮數據。
三、libjpeg 的主要功能unsetunset
libjpeg 提供了一套功能豐富的接口,支持以下功能:
- JPEG 編碼與解碼:支持標準 JPEG 文件的讀寫。
- 多種圖像格式支持:支持灰度、彩色、子采樣等多種格式。
- 自定義壓縮質量:允許用戶調整壓縮質量以控制文件大小與圖像質量的平衡。
- 擴展性:支持插入自定義標記(metadata),并允許用戶操作圖像流。
四、libjpeg 的技術架構unsetunset
libjpeg 的核心架構分為以下幾部分:
-
數據輸入/輸出處理器:
- 提供標準的輸入流與輸出流接口。
- 支持文件、內存緩沖區等多種數據來源。
-
壓縮與解壓模塊:
- 壓縮模塊:將像素數據轉換為 JPEG 數據流。
- 解壓模塊:解析 JPEG 數據流并恢復為像素數據。
-
色彩轉換器:
- 提供從 RGB 到 YCbCr 的轉換。
- 支持不同子采樣率的配置。
-
DCT 和量化模塊:
- 負責離散余弦變換和頻域數據的量化。
- 使用標準或自定義量化表。
-
熵編碼模塊:
- 提供霍夫曼編碼與解碼功能。
- 可選擇算術編碼(需要啟用)。
五、libjpeg 的使用方法
1. 編碼(壓縮)
以下是使用 libjpeg 將 RGB 圖像編碼為 JPEG 文件的基本流程:
#include
#include
void write_jpeg(const char *filename, unsigned char *image, int width, int height, int quality) {
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *outfile = fopen(filename, "wb");
if (!outfile) {
fprintf(stderr, "Error: Cannot open file %s\n", filename);
return;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3; // RGB
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW row_pointer;
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer = &image[cinfo.next_scanline * width * 3];
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
}
2. 解碼(解壓縮)
解碼 JPEG 文件到內存:
#include
#include
unsigned char* read_jpeg(const char *filename, int *width, int *height) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *infile = fopen(filename, "rb");
if (!infile) {
fprintf(stderr, "Error: Cannot open file %s\n", filename);
return NULL;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
*width = cinfo.output_width;
*height = cinfo.output_height;
int row_stride = cinfo.output_width * cinfo.output_components;
unsigned char *image = malloc(cinfo.output_height * row_stride);
JSAMPROW row_pointer[1];
while (cinfo.output_scanline < cinfo.output_height) {
row_pointer[0] = &image[cinfo.output_scanline * row_stride];
jpeg_read_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_decompress(&cinfo);
fclose(infile);
jpeg_destroy_decompress(&cinfo);
return image;
}
六、libjpeg 的優缺點
優點:
- 輕量級,適合嵌入式系統。
- 高性能,編碼與解碼效率高。
- 開源,跨平臺支持良好。
缺點:
- 不支持 JPEG2000 等更現代的格式。
- 有限的擴展性,不支持復雜的圖像處理功能。
七、ubuntu16.04下交叉編譯libjpeg
官網 : https://www.ijg.org/
下載 jpegsrc.v9b.tar.gz : http://www.ijg.org/files/jpegsrc.v9b.tar.gz
編譯步驟
1. 配置
./configure RANLIB=/opt/SDK/arm-linux-gnueabihf-ranlib
--prefix=/opt/libjpeg-9f
--exec-prefix=/opt/libjpeg-9f
--enable-shared
--enable-static
-host=arm-linux-gnueabihf
2. 編譯
make -j4
make install
libjpeg 是圖像處理領域的經典工具,憑借其高效、穩定的特性,成為 JPEG 圖像壓縮和解壓的行業標準。盡管現代圖像格式不斷涌現(如 WebP、AVIF),libjpeg 仍然是許多系統的首選。對于開發者來說,掌握 libjpeg 的使用方法是高效處理 JPEG 圖像的基礎技能。