我正在尝试根据 EXIF 元数据中存在的“方向”参数,使用 libjpeg v9 在 C++ 中旋转 JPEG 图像。我能够获取“方向”参数,并在此基础上,我还能够将图像旋转到另一个文件中,以便旋转后的图像对应于“方向”值 1。
请参阅我从“jpegtran.c”文件中获取的代码并且工作正常(不存在读取 EXIF 元数据代码):
#include <iostream>
#include <jpeglib.h>
#include <jerror.h>
#include "transupp.h"
void setTransformation(jpeg_transform_info *transformObj, JXFORM_CODE transformation){
transformObj->perfect = FALSE;
transformObj->trim = FALSE;
transformObj->force_grayscale = FALSE;
transformObj->crop = FALSE;
transformObj->transform = transformation;
}
void releaseRes(j_decompress_ptr srcPtr, j_compress_ptr destPtr){
jpeg_finish_compress(destPtr);
jpeg_destroy_compress(destPtr);
(void) jpeg_finish_decompress(srcPtr);
jpeg_destroy_decompress(srcPtr);
}
void rotateImage(const char *inputFilename, const char *outputFilename, JXFORM_CODE transformVal){
FILE *inputFile = fopen(inputFilename, "r");
if(inputFile==NULL){
std::cerr<<"ERROR: cannot open input file\n";
return;
}
struct jpeg_decompress_struct srcObj;
struct jpeg_error_mgr srcErrMgr;
struct jpeg_compress_struct destObj;
struct jpeg_error_mgr destErrMgr;
jvirt_barray_ptr *srcCoefArr;
jvirt_barray_ptr *destCoefArr;
//transformation object
jpeg_transform_info transformObj;
//set error handler
srcObj.err = jpeg_std_error(&srcErrMgr);
jpeg_create_decompress(&srcObj);
destObj.err = jpeg_std_error(&destErrMgr);
jpeg_create_compress(&destObj);
//set the transformation properties
setTransformation(&transformObj, transformVal);
jpeg_stdio_src(&srcObj, inputFile);
JCOPY_OPTION copyOpt = JCOPYOPT_DEFAULT;
jcopy_markers_setup(&srcObj, copyOpt);
(void) jpeg_read_header(&srcObj, TRUE);
if(!jtransform_request_workspace(&srcObj, &transformObj)){
std::cerr<<"Transformation is not perfect\n";
return;
}
srcCoefArr = jpeg_read_coefficients(&srcObj);
jpeg_copy_critical_parameters(&srcObj, &destObj);
destCoefArr = jtransform_adjust_parameters(&srcObj, &destObj, srcCoefArr, &transformObj);
FILE *outputFile = fopen(outputFilename, "wb");
if(outputFile==NULL){
std::cerr<<"ERROR: cannot open output file\n";
fclose(inputFile);
releaseRes(&srcObj, &destObj);
return;
}
jpeg_stdio_dest(&destObj, outputFile);
jpeg_write_coefficients(&destObj, destCoefArr);
jcopy_markers_execute(&srcObj, &destObj, copyOpt);
jtransform_execute_transformation(&srcObj, &destObj, srcCoefArr, &transformObj);
releaseRes(&srcObj, &destObj);
//close files
fclose(inputFile);
fclose(outputFile);
}
但是,我不想将旋转图像存储到另一个文件中,而是想就地旋转到缓冲区或使用临时缓冲区,但不进行压缩,如上面的代码所示。
下面是将解压后的数据放入缓冲区的代码:
void rotateImage(const char *filename){
FILE *file = fopen(filename, "r");
if(!file){
std::cerr<<"Error in reading file\n";
return;
}
struct jpeg_decompress_struct info;
struct jpeg_error_mgr jerr;
info.err = jpeg_std_error(&jerr);
jpeg_CreateDecompress(&info, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
jpeg_stdio_src(&info, file);
(void) jpeg_read_header(&info, TRUE);
jpeg_start_decompress(&info);
uint32_t channels = 3;
uint32_t rowStride = info.output_width * channels;
uint64_t dataSize = rowStride * info.output_height;
unsigned char *buffer = new unsigned char[dataSize];
unsigned char *rowData[1];
while(info.output_scanline < info.output_height){
//initial value of output_Scanline state var is 0
rowData[0] = buffer + info.output_scanline * rowStride;
jpeg_read_scanlines(&info, rowData, 1);
}
/*Now, i want to rotate this buffer (or with other temp buffer without compression as in
first code) as per "orientation", either 90, 180, 270*/
/* here */
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
fclose(file);
delete buffer;
}
不过,我尝试使用临时缓冲区(类似于非方矩阵的矩阵旋转)通过以下代码旋转缓冲区 90 度:
//90 degree clockwise
unsigned char *tmpBuf = new unsigned char[dataSize];
int row = info.output_height;
int col = info.output_width;
for(int i=0; i<row; i+=1){
for(int j=0;j<col; j+=1){
//copied 3 bytes as each pixed takes 3 bytes for RGB
memcpy(tmpBuf + (j*row + row-i-1)*3, buffer + (i*col + j)*3, 3);
}
}
但是,我相信,这不是旋转 JPEG 的正确方法,因为我将此数据发送到的应用程序不接受旋转的数据(仅供参考,我按照应用程序尊重的“方向”旋转它)。这让我相信这不是旋转 JPEG 图像的正确方法。与第一种方法一样,我要向其发送数据的应用程序接受首先旋转为压缩数据,然后再次解压缩到缓冲区。但是,我认为,这不是更好的方法。
所以,我需要你的帮助。请让我知道实现它所需的步骤。任何代码示例或教程也会有所帮助。
Thanks