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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值