libjpeg 库:图像压缩与解压的核心技术

一、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 压缩的核心基于以下步骤:

  1. 颜色空间转换:从 RGB 转为 YCbCr 色彩空间,分离亮度(Y)与色度(Cb、Cr)信息。
  2. 采样率降采样:降低色度分量的分辨率,减少数据量。
  3. 离散余弦变换 (DCT):将图像块从空间域转换到频率域。
  4. 量化:通过对高频分量进行更强的压缩来减少不明显的细节。
  5. 熵编码:使用霍夫曼编码或算术编码进一步压缩数据。

三、libjpeg 的主要功能unsetunset

libjpeg 提供了一套功能丰富的接口,支持以下功能:

  1. JPEG 编码与解码:支持标准 JPEG 文件的读写。
  2. 多种图像格式支持:支持灰度、彩色、子采样等多种格式。
  3. 自定义压缩质量:允许用户调整压缩质量以控制文件大小与图像质量的平衡。
  4. 扩展性:支持插入自定义标记(metadata),并允许用户操作图像流。

四、libjpeg 的技术架构unsetunset

libjpeg 的核心架构分为以下几部分:

  1. 数据输入/输出处理器

    • 提供标准的输入流与输出流接口。
    • 支持文件、内存缓冲区等多种数据来源。
  2. 压缩与解压模块

    • 压缩模块:将像素数据转换为 JPEG 数据流。
    • 解压模块:解析 JPEG 数据流并恢复为像素数据。
  3. 色彩转换器

    • 提供从 RGB 到 YCbCr 的转换。
    • 支持不同子采样率的配置。
  4. DCT 和量化模块

    • 负责离散余弦变换和频域数据的量化。
    • 使用标准或自定义量化表。
  5. 熵编码模块

    • 提供霍夫曼编码与解码功能。
    • 可选择算术编码(需要启用)。

五、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 图像的基础技能。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 4
收藏 4
关注 36
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧