LibJPEG库使用_通过LibJPEG将RGB数据保存为JPG图片存储到磁盘

举报
DS小龙哥 发表于 2024/09/10 16:31:54 2024/09/10
【摘要】 LibJPEG库是一个广泛使用的开源C库,用于处理JPEG图像的压缩和解压缩。该库由独立JPEG小组(Independent JPEG Group, IJG)开发,提供了功能强大的API,用于创建和读取JPEG文件。


一、前言

LibJPEG库是一个广泛使用的开源C库,用于处理JPEG图像的压缩和解压缩。该库由独立JPEG小组(Independent JPEG Group, IJG)开发,提供了功能强大的API,用于创建和读取JPEG文件。LibJPEG库支持JPEG的所有常见功能,包括高质量的压缩、解压缩、图像处理、颜色空间转换等。采用DCT(离散余弦变换)算法实现了高效的图像压缩,同时支持各种图像质量的调整。LibJPEG的灵活性和性能使其成为图像处理应用中的标准工具,被广泛应用于图像编辑软件、图像查看器、图像传输等多个领域。该库跨平台兼容,支持Windows、Linux、macOS等操作系统,开发者可以轻松将其集成到不同的平台和应用中。LibJPEG库还具有良好的文档支持,提供详细的编程指南和示例代码,帮助开发者快速上手和实现复杂的图像处理功能。由于其开源性质和广泛的应用,LibJPEG在业界享有很高的声誉,成为许多图像处理项目的首选库。


LibJPEG库的源码下载地址:https://www.ijg.org/


image-20240808164050380





下载后是一个ZIP的压缩包,解压看到的数据:

image-20240808162923658



如果要下载编译好的二进制文件,可以去这里下载:https://gnuwin32.sourceforge.net/packages/jpeg.htm

image-20240808163240331


二、函数接口解释

LibJPEG库提供了一组函数接口,用于实现JPEG图像的压缩和解压缩操作。

以下是一些常用的LibJPEG库函数接口及其详细讲解,包括函数功能、参数作用等。

2.1 JPEG压缩相关函数

jpeg_create_compress

  • 功能:初始化JPEG压缩对象。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

  • 说明:必须在进行任何其他JPEG压缩操作之前调用该函数。

jpeg_stdio_dest

  • 功能:设置压缩数据的目标为标准I/O流。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

    • FILE *outfile:目标文件的文件指针。

  • 说明:指定JPEG数据输出的目标文件。

jpeg_set_defaults

  • 功能:设置JPEG压缩参数的默认值。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

  • 说明:设置一组默认的JPEG压缩参数。

jpeg_set_quality

  • 功能:设置JPEG压缩质量。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

    • int quality:压缩质量,范围为0(最差)到100(最佳)。

    • boolean force_baseline:如果为TRUE,强制生成符合JPEG标准的文件。

  • 说明:调整JPEG压缩的质量参数。

jpeg_start_compress

  • 功能:启动压缩过程。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

    • boolean write_all_tables:如果为TRUE,写入所有JPEG标记。

  • 说明:在压缩数据之前调用该函数。

jpeg_write_scanlines

  • 功能:写入压缩数据行。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

    • JSAMPARRAY scanlines:指向存储图像数据的缓冲区。

    • JDIMENSION num_lines:要写入的行数。

  • 说明:写入图像数据到JPEG压缩对象中。

jpeg_finish_compress

  • 功能:完成压缩过程。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

  • 说明:在完成所有数据写入后调用,关闭JPEG压缩对象。

jpeg_destroy_compress

  • 功能:销毁JPEG压缩对象。

  • 参数

    • struct jpeg_compress_struct *cinfo:指向JPEG压缩对象的指针。

  • 说明:释放JPEG压缩对象分配的所有资源。

2.2 JPEG解压缩相关函数

jpeg_create_decompress

  • 功能:初始化JPEG解压缩对象。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

  • 说明:必须在进行任何其他JPEG解压缩操作之前调用该函数。

jpeg_stdio_src

  • 功能:设置解压数据的源为标准I/O流。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

    • FILE *infile:源文件的文件指针。

  • 说明:指定JPEG数据输入的源文件。

jpeg_read_header

  • 功能:读取JPEG文件的头部信息。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

    • boolean require_image:如果为TRUE,要求图像数据存在。

  • 说明:读取JPEG文件的头部信息,解析JPEG图像的元数据。

jpeg_start_decompress

  • 功能:启动解压缩过程。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

  • 说明:在解压缩数据之前调用该函数。

jpeg_read_scanlines

  • 功能:读取解压缩的数据行。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

    • JSAMPARRAY scanlines:指向存储解压缩数据的缓冲区。

    • JDIMENSION max_lines:要读取的最大行数。

  • 说明:从JPEG解压缩对象中读取图像数据。

jpeg_finish_decompress

  • 功能:完成解压缩过程。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

  • 说明:在完成所有数据读取后调用,关闭JPEG解压缩对象。

jpeg_destroy_decompress

  • 功能:销毁JPEG解压缩对象。

  • 参数

    • struct jpeg_decompress_struct *cinfo:指向JPEG解压缩对象的指针。

  • 说明:释放JPEG解压缩对象分配的所有资源。

2.3 辅助函数

jpeg_std_error

  • 功能:初始化JPEG错误处理对象。

  • 参数

    • struct jpeg_error_mgr *err:指向JPEG错误处理对象的指针。

  • 说明:设置默认的JPEG错误处理例程。

这些函数共同构成了LibJPEG库的核心接口,通过它们可以实现JPEG图像的高效压缩和解压缩。在使用这些函数时,需要按照特定的调用顺序来确保正确的操作和资源管理。



三、代码实现

以下是将RGB565图像转换为RGB888并压缩为JPEG格式的完整示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <jpeglib.h>
​
// 将RGB565转换为RGB888
void RGB565_to_RGB888(uint16_t rgb565, uint8_t *r, uint8_t *g, uint8_t *b) {
    *r = ((rgb565 >> 11) & 0x1F) << 3;
    *g = ((rgb565 >> 5) & 0x3F) << 2;
    *b = (rgb565 & 0x1F) << 3;
}
​
// 将RGB565格式图像转换为RGB888格式
void convert_RGB565_to_RGB888(const uint8_t *rgb565_image, uint8_t *rgb888_image, int width, int height) {
    for (int i = 0; i < width * height; i++) {
        uint16_t rgb565 = ((uint16_t)rgb565_image[2 * i + 1] << 8) | rgb565_image[2 * i];
        RGB565_to_RGB888(rgb565, &rgb888_image[3 * i], &rgb888_image[3 * i + 1], &rgb888_image[3 * i + 2]);
    }
}
​
// 将RGB888格式图像压缩为JPEG格式
void compress_to_JPEG(const uint8_t *rgb888_image, int width, int height, const char *filename) {
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
​
    FILE *outfile;
    JSAMPROW row_pointer[1];
    int row_stride;
​
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
​
    if ((outfile = fopen(filename, "wb")) == NULL) {
        fprintf(stderr, "can't open %s\n", filename);
        exit(1);
    }
    jpeg_stdio_dest(&cinfo, outfile);
​
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
​
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 75, TRUE);
    jpeg_start_compress(&cinfo, TRUE);
​
    row_stride = width * 3;
​
    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = (JSAMPROW) &rgb888_image[cinfo.next_scanline * row_stride];
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }
​
    jpeg_finish_compress(&cinfo);
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);
}
​
int main() {
    // 假设图像尺寸为100x100
    int width = 100;
    int height = 100;
​
    // 示例RGB565数据
    uint8_t rgb565_image[20000];
    for (int i = 0; i < 20000; i++) {
        rgb565_image[i] = rand() % 256; // 用随机数据填充
    }
​
    // 分配RGB888图像数据的内存
    uint8_t *rgb888_image = (uint8_t *)malloc(width * height * 3);
    if (rgb888_image == NULL) {
        fprintf(stderr, "Unable to allocate memory for RGB888 image\n");
        return 1;
    }
​
    // 转换RGB565到RGB888
    convert_RGB565_to_RGB888(rgb565_image, rgb888_image, width, height);
​
    // 压缩并保存为JPEG文件
    compress_to_JPEG(rgb888_image, width, height, "output.jpg");
​
    // 释放内存
    free(rgb888_image);
​
    printf("Compression to JPEG completed.\n");
​
    return 0;
}
​
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。