C++使用libjpeg读写jpeg文件

C++使用libjpeg读写jpeg文件


1、读取jpeg文件

//读取rgb,以下代码由人工智能提供。
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <jpeglib.h>
#include "opencv2/opencv.hpp"

int readJpeg(const char* filename, cv::Mat& pData)
{
	// 打开文件
	FILE* infile;
	if ((infile = fopen(filename, "rb")) == NULL) {
		fprintf(stderr, "Can't open %s\n", filename);
		return 0;
	}
    // 创建JPEG读取对象
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    // 设置输入流
    jpeg_stdio_src(&cinfo, infile);

    // 读取JPEG文件头
    jpeg_read_header(&cinfo, TRUE);

    // 开始解压
    jpeg_start_decompress(&cinfo);

    // 获取图像宽度和高度
    int width = cinfo.output_width;
    int height = cinfo.output_height;
    int channels = cinfo.output_components;//输出的通道数ou
int channels = cinfo.jpeg_color_space;// 原图的和输出的不一样。YCbCr和RGB获取数据相同
    // 创建OpenCV的Mat对象
    pData = cv::Mat(height, width, CV_8UC3);

    // 读取图像数据
    int row_stride = width * channels;
    JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
        ((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
    for (int i = 0; i < height; i++) {
        jpeg_read_scanlines(&cinfo, buffer, 1);
        for (int j = 0; j < width; j++) {
            // 注意:libjpeg存储的是BGR颜色空间,需要转换成OpenCV的RGB颜色空间
            pData.at<cv::Vec3b>(i, j)[0] = buffer[0][j * channels + 2];
            pData.at<cv::Vec3b>(i, j)[1] = buffer[0][j * channels + 1];
            pData.at<cv::Vec3b>(i, j)[2] = buffer[0][j * channels + 0];
        }
    }

	// 结束解压
	jpeg_finish_decompress(&cinfo);

	// 销毁JPEG读取对象
	jpeg_destroy_decompress(&cinfo);

	// 关闭文件
	fclose(infile);

	return 0;
}

2、写入JPEG文件

long writeJpeg(const char* ofilename, cv::Mat& pData)
{
	struct my_error_mgr {
		struct jpeg_error_mgr pub;
		jmp_buf setjmp_buffer;
	};

	typedef struct my_error_mgr* my_error_ptr;
	auto my_error_exit = [](j_common_ptr cinfo){
		my_error_ptr myerr = (my_error_ptr)cinfo->err;
		(*cinfo->err->output_message) (cinfo);
		longjmp(myerr->setjmp_buffer, 1);
	};
	FILE* outfile;
	if ((outfile = fopen(ofilename, "wb")) == NULL) {
		fprintf(stderr, "Can't open %s\n", ofilename);
		return 0;
	}

	// 创建JPEG压缩对象
	struct jpeg_compress_struct cinfo;
	struct my_error_mgr jerr;
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if (setjmp(jerr.setjmp_buffer)) {
		jpeg_destroy_compress(&cinfo);
		fclose(outfile);
		return 0;
	}
	jpeg_create_compress(&cinfo);

	// 设置输出流
	jpeg_stdio_dest(&cinfo, outfile);

	// 设置图像参数
	cinfo.image_width = pData.cols;
	cinfo.image_height = pData.rows;

	//保存为CMYK
	cv::Mat d_pData;
	rgb2cmyk(pData, d_pData);
	cinfo.input_components = 4;
	cinfo.in_color_space = JCS_CMYK;//不同类型只有这里和通道数不一致。
	保存为RGB
	//cinfo.input_components = 3;
	//cinfo.in_color_space = JCS_RGB;

	jpeg_set_defaults(&cinfo);

	// 开始压缩
	jpeg_start_compress(&cinfo, TRUE);

	// 写入图像数据
	int row_stride = d_pData.cols * cinfo.input_components;
	JSAMPROW row_pointer[1];
	while (cinfo.next_scanline < cinfo.image_height) {
		JSAMPROW row_pointer[1];
		row_pointer[0] = &d_pData.data[cinfo.next_scanline * row_stride];
		jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	// 结束压缩
	jpeg_finish_compress(&cinfo);

	// 释放资源
	jpeg_destroy_compress(&cinfo);
	fclose(outfile);

	return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: libjpeg是一个流行的JPEG图像压缩和解压缩库,可以用于将JPEG图像转换为RGB888格式。 要使用libjpegJPEG图像转换为RGB888,首先需要安装libjpeg库并包含相关的头文件使用以下步骤可以实现此功能: 1. 打开JPEG图像文件使用libjpeg的函数`jpeg_stdio_src`。 2. 调用`jpeg_read_header`函数获取JPEG图像的头文件信息。 3. 设置解压缩参数,包括输出格式。在本例中,我们需要将JPEG图像解压缩为RGB888格式,因此可以使用`jpeg_set_decompress_parms`函数来设置输出格式。 4. 使用`jpeg_start_decompress`函数开始解压缩过程。 5. 创建一个指向放置解压缩后像素数据的缓冲区的指针。在本例中,我们需要将JPEG图像解压缩为RGB888格式,因此缓冲区的大小应为图像宽度乘以图像高度乘以3。 6. 使用`jpeg_read_scanlines`函数逐行读取JPEG图像的像素数据,存储在缓冲区中。 7. 解压缩完成后,调用`jpeg_finish_decompress`函数完成解压缩过程。 8. 将RGB888格式的像素数据存储在所需的格式中,例如,在C语言中,可以将像素数据存储在一个三维数组中。 9. 最后,使用`jpeg_destroy_decompress`函数销毁解压缩对象。 通过以上步骤,我们可以使用libjpegJPEG图像转换为RGB888格式。 需要注意的是,以上只是实现此功能的基本步骤,实际使用时还需要添加错误处理和其他必要的功能来确保程序的正确性和稳定性。 ### 回答2: libjpeg是一个非常常用的JPEG图像解码库,它可以将JPEG图像解码为其他不同的格式,包括RGB888格式。下面是使用libjpegJPEG转换为RGB888的步骤: 1. 首先,需要安装libjpeg库,并在代码中引入相关的头文件。 2. 创建一个jpeg_decompress_struct结构体对象,用于存储解码过程中的相关参数。 3. 调用jpeg_CreateDecompress函数初始化jpeg_decompress_struct对象。 4. 使用jpeg_stdio_src函数将源JPEG文件关联到jpeg_decompress_struct对象。 5. 调用jpeg_read_header函数读取JPEG文件的头部信息。 6. 设置解码参数,包括解码模式和输出格式。对于RGB888格式,可以通过设置jpeg_decompress_struct的输出颜色空间和输出全色彩标志来实现。 7. 调用jpeg_start_decompress函数开始解码过程。 8. 使用jpeg_read_scanlines函数逐行读取解码后的RGB像素数据。 9. 将得到的RGB像素数据存储到目标RGB888格式的缓冲区中。 10. 最后,调用jpeg_finish_decompress函数结束解码过程,并释放相关资源。 以上是使用libjpegJPEG图像转换为RGB888格式的简要步骤。具体的代码实现会更加复杂,需要进行各种错误处理和内存管理。但使用libjpeg库可以方便地完成这一任务,而无需自己从头开始实现JPEG解码算法。 ### 回答3: libjpeg是一个经典的JPEG图像压缩与解压缩库,可以用于将JPEG图像文件转换为RGB888格式。 使用libjpegJPEG图像转换为RGB888格式的过程如下: 首先,我们需要包含libjpeg库的头文件,并声明所需的变量。JPEG图像的压缩信息将存储在jpeg_decompress_struct结构体中,而解压缩的输出数据将存储在jpeg_decompress_struct结构体的jd_output_components变量中。RGB888格式的数据需要通过指针指向一个unsigned char型的一维数组。 ``` #include <stdio.h> #include <jpeglib.h> int main() { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buffer; unsigned char *rgbData; ... } ``` 接着,我们需要使用libjpeg提供的函数初始化并打开JPEG文件,进行解压缩准备工作。 ``` cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); FILE *infile = fopen("input.jpg", "rb"); if (!infile) { return 0; } jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1); rgbData = malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components); ``` 然后,我们需要使用libjpeg提供的函数逐行读取图像数据,并将其存储在我们之前声明的rgbData中。 ``` int row = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); memcpy(rgbData + row * cinfo.output_width * cinfo.output_components, buffer[0], cinfo.output_width * cinfo.output_components); row++; } ``` 最后,我们完成转换后需要进行一些清理工作,关闭文件,释放内存等。 ``` jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); free(rgbData); fclose(infile); ``` 通过以上步骤,我们就可以使用libjpegJPEG图像转换为RGB888格式,最终结果存储在rgbData数组中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值