我希望以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参数的其他方法,可以尝试使用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);
```
如果我的回答解决了您的问题,请采纳!