我希望以temple.jpg 的压缩方式去压缩org.jpg 并保存为target.jpg

我希望以temple.jpg 的压缩方式去压缩org.jpg 并保存为target.jpg,希望做到的是target.jpg 与temle.jpg的hex代码(FFD8到FFDA之间)都一样,自己写了一段代码,已经可以复制相似的压缩方式,但不知道为何,我生成出来的图片的hex代码与参考图片的并不一致。
我也进行了详细的测试,测试结果如下:
1.在保存图片之前target.jpg的Huffman表Quantization与temple.jpg的已经确定一致;
2.如果temple.jpg本身是以ijg标准保存的,我可以直接从temple.jpg复制FFD8到FFDA之间的代码替换target.jpg的,并不会出错;但如果temple.jpg的压缩本身不是ijg标准的,target.jpg可以保存,如果直接从temple.jpg复制FFD8到FFDA之间的代码替换target.jpg的,会导致图片出错;
3.生成出来的target.jpg图片用libjpeg去分析Quantization与temple.jpg,发现他们读取的数据是一样的,但我直接用hex编辑器去看两张图片的hex代码并不一致;

我写的代码如下:



void copy_jpeg_file(const std::string& input_filename, const std::string& ref_filename, const std::string& output_filename) {
    // Open input and reference files
    FILE* input_file;
    FILE* ref_file;
    errno_t err;

    err = fopen_s(&input_file, input_filename.c_str(), "rb");
    err = fopen_s(&ref_file, ref_filename.c_str(), "rb");
    if (!input_file || !ref_file) {
        std::cerr << "Error opening files." << std::endl;
        exit(1);
    }

    // Input image decompression
    struct jpeg_decompress_struct srcinfo;
    struct jpeg_error_mgr srcerr;
    srcinfo.err = jpeg_std_error(&srcerr);
    jpeg_create_decompress(&srcinfo);

    jpeg_stdio_src(&srcinfo, input_file);
    jpeg_read_header(&srcinfo, TRUE);

    // Reference image decompression
    struct jpeg_decompress_struct refinfo;
    struct jpeg_error_mgr referr;
    refinfo.err = jpeg_std_error(&referr);
    jpeg_create_decompress(&refinfo);

    jpeg_stdio_src(&refinfo, ref_file);
    jpeg_read_header(&refinfo, TRUE);

    // Output image compression
    struct jpeg_compress_struct dstinfo;
    struct jpeg_error_mgr dsterr;
    dstinfo.err = jpeg_std_error(&dsterr);
    jpeg_create_compress(&dstinfo);

    FILE* output_file;
    err = fopen_s(&output_file, output_filename.c_str(), "wb");
    if (!output_file) {
        std::cerr << "Error opening output file." << std::endl;
        exit(1);
    }  

    jpeg_stdio_dest(&dstinfo, output_file);      
    custom_copy_critical_parameters(&refinfo, &dstinfo);

    // Set input color space for output image
    dstinfo.in_color_space = srcinfo.out_color_space;

    // Disable JFIF header
    dstinfo.write_JFIF_header = FALSE;

    //禁用数据优化
    dstinfo.optimize_coding = FALSE;
    dstinfo.smoothing_factor = 0;
    dstinfo.dct_method = JDCT_ISLOW;

    dstinfo.comp_info[0].h_samp_factor = refinfo.comp_info[0].h_samp_factor;
    dstinfo.comp_info[0].v_samp_factor = refinfo.comp_info[0].v_samp_factor;
    dstinfo.comp_info[1].h_samp_factor = refinfo.comp_info[1].h_samp_factor;
    dstinfo.comp_info[1].v_samp_factor = refinfo.comp_info[1].v_samp_factor;
    dstinfo.comp_info[2].h_samp_factor = refinfo.comp_info[2].h_samp_factor;
    dstinfo.comp_info[2].v_samp_factor = refinfo.comp_info[2].v_samp_factor;

    //调试信息
    //Debug_output_compress_Huffman_and_quantization(dstinfo, "dstinfo huff_table and quant_table before copied");

    // Copy DQT、SOF and DHT 
    for (int i = 0; i < NUM_QUANT_TBLS; i++) {
        if (refinfo.quant_tbl_ptrs[i] != nullptr) {
            if (dstinfo.quant_tbl_ptrs[i] == nullptr) {
                dstinfo.quant_tbl_ptrs[i] = jpeg_alloc_quant_table((j_common_ptr)&dstinfo);
            }
            copy_quant_table(refinfo.quant_tbl_ptrs[i], dstinfo.quant_tbl_ptrs[i]);
        }
    }

    for (int i = 0; i < NUM_HUFF_TBLS; i++) {
        if (refinfo.dc_huff_tbl_ptrs[i] != nullptr) {
            if (dstinfo.dc_huff_tbl_ptrs[i] == nullptr) {
                dstinfo.dc_huff_tbl_ptrs[i] = jpeg_alloc_huff_table((j_common_ptr)&dstinfo);
            }
            copy_huff_table(refinfo.dc_huff_tbl_ptrs[i], dstinfo.dc_huff_tbl_ptrs[i]);
        }
        if (refinfo.ac_huff_tbl_ptrs[i] != nullptr) {
            if (dstinfo.ac_huff_tbl_ptrs[i] == nullptr) {
                dstinfo.ac_huff_tbl_ptrs[i] = jpeg_alloc_huff_table((j_common_ptr)&dstinfo);
            }
            copy_huff_table(refinfo.ac_huff_tbl_ptrs[i], dstinfo.ac_huff_tbl_ptrs[i]);
        }
    }

/**** 调试信息
    Debug_output_decompress_Huffman_and_quantization(srcinfo, "srcinfo huff_table and quant_table after copied");
    Debug_output_compress_Huffman_and_quantization(dstinfo, "dstinfo huff_table and quant_table after copied");
    Debug_output_decompress_Huffman_and_quantization(refinfo, "refinfo huff_table and quant_table after copied");
     *****/

    // Start decompression of input image and compression of output image
    jpeg_start_decompress(&srcinfo);
    jpeg_start_compress(&dstinfo, TRUE);

    // Allocate memory for scanlines buffer
    JSAMPARRAY buffer = (*srcinfo.mem->alloc_sarray)((j_common_ptr)&srcinfo, JPOOL_IMAGE, srcinfo.output_width * srcinfo.output_components, 1);

    // Copy scanlines from input image to output image
    while (srcinfo.output_scanline < srcinfo.output_height) {
        jpeg_read_scanlines(&srcinfo, buffer, 1);
        jpeg_write_scanlines(&dstinfo, buffer, 1);
    }

    // Finish decompression and compression
    jpeg_finish_decompress(&srcinfo);
    jpeg_finish_compress(&dstinfo);

    // Destroy structures and close files
    jpeg_destroy_decompress(&srcinfo);
    jpeg_destroy_decompress(&refinfo);
    jpeg_destroy_compress(&dstinfo);

    fclose(input_file);
    fclose(ref_file);
    fclose(output_file);

    }

请求回答问题的时候不要直接用chatgpt的内容,我自己也有gpt4```实在不知道怎么办才来csdn的。希望是真正能懂这个逻辑的兄弟能帮忙一下,能解决会追加酬谢,感谢!

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,从一个JPEG文件复制压缩参数到另一个JPEG文件是一个复杂的操作。这通常涉及到复制量化表和Huffman表,因为这些参数对于JPEG压缩非常重要。

在您的代码中,您复制了量化表和Huffman表,但似乎部分功能仍有问题。问题通常可以出现在几个方面,包括:

  • 量化表的精度:JPEG文件的量化表通常被保存为8位,但在某些情况下,这可能会降低图像质量。如果您复制的量化表是8位的,则可能会出现此问题。您可以尝试使用更高精度的量化表来解决这个问题。
  • 不同的JPEG实现使用不同的量化表和Huffman表:这意味着即使您复制了量化表和Huffman表,也可能会导致不同的压缩结果,因为不同的JPEG实现可能会使用不同的表来进行压缩。
  • 传输的数据的格式:如果JPEG文件的数据格式不同,即使您复制了量化表和Huffman表,也可能会导致不同的压缩结果。在您的代码中,您可以尝试更改使用的压缩器的DCT方法和优化等级,并查看是否有所帮助。

如果您想尝试复制JPEG参数的其他方法,可以尝试使用jpegtran工具,它是JPEG库的一部分。它可以使用以下命令将一个JPEG文件的参数应用到另一个JPEG文件:

jpegtran -copy all -outfile target.jpg -optimize temple.jpg org.jpg

这将尝试将temple.jpg的参数应用到org.jpg中,并将结果保存到target.jpg中。注意,这不一定会导致完全相同的压缩结果,但它将确保参数是相同的。

最后,我注意到您的代码中没有调用jpeg_set_defaults函数,这是一个非常重要的函数,它将设置JPEG压缩器的默认参数。您可以尝试在复制量化表和Huffman表之前调用此函数,以确保所有参数都设置正确。例如:

jpeg_set_defaults(&dstinfo);
dstinfo.optimize_coding = FALSE;
dstinfo.smoothing_factor = 0;
dstinfo.dct_method = JDCT_ISLOW;
dstinfo.in_color_space = srcinfo.out_color_space;
dstinfo.write_JFIF_header = FALSE;
jpeg_set_quality(&dstinfo, 90, TRUE);

```
如果我的回答解决了您的问题,请采纳!