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

news2024/9/21 21:24:24

一、前言

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;
}
​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2143971.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cpp快速入门语法(上)(1)

文章目录 前言一、C关键字(C98)二、命名空间命名空间的定义命名空间的使用 三、C输入 & 输出四、缺省参数总结 前言 其实有时候我也会尝试代入下祖师爷本杰明当年在贝尔实验室的心理活动&#xff0c;我心想&#xff0c;他可能一开始是大抵受不了C语言的某些缺点&#xff0c…

梦想之家|AI技术赋能家居,重塑生活空间

人工智能&#xff08;AI&#xff09;在智能家居方面的应用非常广泛&#xff0c;极大地提升了家庭的便利性、安全性和能源效率。当前&#xff0c;AI技术的迅速发展&#xff0c;为传统家居产品带来了智能化升级。从智能单品到智能互联&#xff0c;AI技术的融入使得这些家居产品具…

DC-DC降压10A电源降压可调模块24V转12V9V5V3V-AH1514芯片

AH1514&#xff1a;一款高效率小体积的DC-DC降压电源芯片 摘要&#xff1a;本文介绍了一款高性能的DC-DC降压电源芯片——AH1514&#xff0c;该芯片具有24V转12V、9V、5V、3V可调输出&#xff0c;支持7V-38V输入&#xff0c;20A峰值输出电流&#xff0c;且具有小体积、高效率的…

C++速通LeetCode简单第19题-只出现一次的数字

方法一&#xff1a;暴力求解&#xff0c;排序后两个两个比较&#xff0c;两者不同时前者为答案&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {if(nums.size() 1) return nums[0];list<int> l;int ans 0;for(int i 0;i< n…

3.js - THREE.CubeTextureLoader() 添加环境纹理,以创建立方体贴图

使用 THREE.CubeTextureLoader() 添加环境纹理&#xff0c;以创建立方体贴图 不使用 THREE.CubeTextureLoader() 的时候 源码 import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls import { RGBELoader } from three/exam…

【话题讨论】AI时代程序员核心力:技术深耕,跨界学习,软硬兼备

目录 引言 一、AI辅助编程对程序员工作的影响 1.1 AI工具如何提升工作效率 1.2 AI工具的风险 1.3 应对策略 二、程序员应重点发展的核心能力 2.1 核心竞争力 2.2 企业和教育机构的调整 三、人机协作模式下的职业发展规划 3.1 持续学习的重要性 3.2 选择适合自己的…

电脑提示‘由于找不到 msvcr120.dll,无法继续执行代码’的科学解决方案分析

如果你在启动特定的应用程序或游戏时遇到错误提示&#xff1a;“由于找不到 msvcr120.dll&#xff0c;无法继续执行代码”&#xff0c;这表明你的系统可能缺少运行某些基于 Visual C 2013 开发的程序所需的关键组件。不过&#xff0c;不必担心&#xff0c;有几种方法可以解决这…

使用C++程序编写5 个浮点数,求平均值后输出

源代码如下&#xff1a; #include <iostream>using namespace std;int main() {float arr[5]{7,10,3,9,8};int i;float sum 0;float avg 0;for(i0;i<5;i){sum sum arr[i];}avg sum/5;cout << "平均值是&#xff1a;" << avg << endl…

VoIP协议

VoIP协议是VoIP业务的规范标准。我们都知道VoIP业务有着压倒性的优势。随着网络应用的多元化和低成本化发展&#xff0c;VoIP业务直接冲击着传统通信市场&#xff0c;那么目前VoIP协议目前常用的协议,如H.323、SIP、MEGACO和MGCP。 H.248 H.248是定义网关控制协议的ITU建议书…

squid代理及常见的代理上网(Squid Proxy and Common Proxy Internet Access)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

【学术会议征稿】第九届计算机技术与机械电气工程国际学术论坛(ISCME 2024)

第九届计算机技术与机械电气工程国际学术论坛&#xff08;ISCME 2024&#xff09; 2024 9th International Seminar on Computer Technology, Mechanical and Electrical Engineering 第九届计算机技术与机械电气工程国际学术论坛&#xff08;ISCME 2024&#xff09;将于2024…

还在为机器学习中,层出不穷的概念烦恼么?不妨看看这边,南瓜书第1,2章学习总结-task01

第一章&#xff1a;绪论 这里面讲了机器学习的基本概念&#xff0c;包括基本术语 1.1.基本概念 数据集和样本集的区别。原始检测数据是总体,总体是统计所研究对象的全体,是包含所研究变量的全部个体的集合,具有同质性、差异性、大量性。构成总体的个别事物叫总体单位。样本检测…

idea插件开发的第四天-完善JSON工具

介绍 Demo说明 本文基于maven项目开发,idea版本为2022.3以上,jdk为1.8本文在Tools插件之上进行开发本次demo将使用idea的一些组件优化 Tools插件说明 Tools插件是一个Idea插件,此插件提供统一Spi规范,极大的降低了idea插件的开发难度,并提供开发者模块,可以极大的为开发者开…

nodejs 009: 使用nvm进行node版本管理(包括Could not retrieve的手动处理办法)

nvm 有些问题类似&#xff1a;“v8::Object::Set": No overloaded function accepts 2 Arguments”可能需要通过更换nodejs的版本来解决&#xff08;如下图所示&#xff0c;需要看当时的项目的时间&#xff0c;查找当时的流行nodejs版本&#xff09;。这时可以使用nvm进行…

干耳朵里的耳屎结坨了怎么弄出来?可视挖耳勺推荐

干耳朵里的耳屎结坨了怎么弄出来&#xff1f;这个是很多干耳朵小伙伴的一个难题。用棉签掏根本掏不出来&#xff0c;反而会越推越进。用普通耳勺掏不仅不够精准还会因为盲掏&#xff0c;弄伤自己的耳膜或者刮破耳道。所以干耳朵里的耳屎结坨了&#xff0c;建议用可视挖耳勺来掏…

robosuite基础教程(一)——基本概念

robosuite和robomimic都是由ARISE Initiative开发的开源工具&#xff0c;旨在推进机器人学习和机器人操作领域的研究。 一、基本概念 robosuite是一个由MuJoCo物理引擎驱动的模拟框架&#xff0c;专为机器人学习设计。它提供了一套基准环境&#xff0c;是Advancing Robot Int…

C++/CLI编程知识点小记

1.前言 本篇博文并非详细的C/CLI教程&#xff0c;仅是博主就学习和实践总结的部分知识点记录。 第一次接触C/CLI是2017年了&#xff0c;用C编写底层库&#xff0c;C/CLI编写wrapper层&#xff0c;在C#项目中进行调用&#xff0c;开发应用。 2.内容 C/CLI是一种混合编程&…

不要沉迷大模型的技术与理论,学习大模型的方法——从做一个小应用开始

“ 在应用中学习技术&#xff0c;而不是沉迷于技术本身 ” 不知道大家都是怎么学习大模型技术的&#xff0c;但从个人的经验和公众号的反馈来看&#xff0c;有些人在学习大模型技术时转进了牛角尖&#xff0c;导致很多东西学不明白&#xff0c;事倍功半。 今天就从个人的学习…

基于SpringBoot+Vue的校园礼服装租赁系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…