使用libjpeg

问题描述

我正在尝试根据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,copyOpt);

    jtransform_execute_transformation(&srcObj,&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的方法不正确,因为应用程序不接受旋转的数据,我正在将该数据发送到(FYI,我按照应用程序对它的“方向”进行旋转)。这使我相信这不是旋转JPEG图像的正确方法。与第一种方法一样,我要向其发送数据的应用程序首先接受压缩数据,然后再次将其解压缩为缓冲区。但是,我认为这不是更好的方法。

因此,我需要您的帮助。请让我知道实现它所需的步骤。任何代码示例或教程也将有所帮助。

谢谢

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...