我试着遵循另一个答案,但似乎不能得到这个正确的。我有大约8mb的RBGX位图在内存中使用libjpeg-turbo转换为jpeg。如果我用jpeg_stdio_dest
,我可以把所有的东西都写到一个文件里,然后再把文件读回来,这样就没事了。然而,试图使用jpeg_mem_dest
一直是一个难题。我有所有相同的设置作为jpeg_stdio_dest
,但使用mem
似乎只做一个分配4KiB,然后从不分配任何更多的空间。
我找不到关于如何使用jpeg_mem_dest
的进一步指导文档,并且真的可以使用一些指导。
void compress(std::vector<unsigned char>& input) {
jpeg_compress_struct cinfo{};
jpeg_error_mgr err{};
cinfo.err = jpeg_std_error(&err);
jpeg_create_compress(&cinfo);
#if 0 // using this with an open FILE* out works
jpeg_stdio_dest(&cinfo, out);
#endif
cinfo.image_width = kWidth; // constants defined somewhere
cinfo.image_height = kHeight;
cinfo.input_components = 4;
cinfo.in_color_space = JCS_EXT_RGBX;
// what's wrong with this?
unsigned char* buf{};
unsigned long buf_sz{};
jpeg_mem_dest(&cinfo, &buf, &buf_sz);
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 70, true);
jpeg_start_compress(&cinfo, true);
while (cinfo.next_scanline < cinfo.image_height) {
auto row = static_cast<JSAMPROW>(&input[cinfo.next_scanline * 4 * kWidth]);
jpeg_write_scanlines(&cinfo, &row, 1);
// Always prints 4096, and buf never changes
std::cout << "buf_sz: " << buf_sz
<< " buf: " << static_cast<void*>(buf) << 'n';
}
jpeg_finish_compress(&cinfo);
// ...
// in reality, return the compressed data
}
是的,这一点都不直观。提出jpeg_mem_dest()调整的程序员没有太多选择,当现有api的设计初衷不是支持某个特性时,扩展它并不容易。完全不明显的是,变量直到jpeg_finish_compress()调用之后的才得到更新。库中的相关代码为:
METHODDEF(void)
term_mem_destination (j_compress_ptr cinfo)
{
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
*dest->outbuffer = dest->buffer;
*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
}
注意"term"这个词。该函数通过函数指针间接调用:
GLOBAL(void)
jpeg_finish_compress (j_compress_ptr cinfo)
{
//...
/* Write EOI, do final cleanup */
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
//...
}
你对此无能为力。只需调整std::cout代码,将其移动到循环之后,以适应库的工作方式。
注意这个函数的其他粗糙的细节,也不明显。您必须使用free()方法来创建缓冲区。在提供的cjpeg.c示例程序中可见,main()的end .