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

科技   2024-11-21 07:33   陕西  


链接:https://www.cnblogs.com/ccblblog/p/18057893

一、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 的主要功能

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

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

四、libjpeg 的技术架构

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

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

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

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

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

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

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

    五、libjpeg 的使用方法

    1. 编码(压缩)

    以下是使用 libjpeg 将 RGB 图像编码为 JPEG 文件的基本流程:

    #include <stdio.h>
    #include <jpeglib.h>

    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 <stdio.h>
    #include <jpeglib.h>

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



    招已经开始啦,大家如果不做好充足准备的话,招很难找到好工作。


    送大家一份就业大礼包,大家可以突击一下春招,找个好工作!


    良许Linux
    良许,自学转行IT并顺利进入500强外企担任Linux开发工程师。公众号分享大量Linux干货,包括Linux基础、Linux应用、Linux工具软件,以及Git、数据库、树莓派等方面技术知识(后台回复 Linux 获取必备Linux资源)
     最新文章