简体   繁体   English

如何使用jpeg_mem_dest使用libjpeg-turbo压缩到内存

[英]How to compress to memory with libjpeg-turbo using jpeg_mem_dest

I've tried following another answer but just can't seem to get this right. 我尝试过另一个答案,但似乎无法做到这一点。 I have about 8MiB of RBGX bitmap to convert to a jpeg in memory using libjpeg-turbo. 我有大约8MiB的RBGX位图使用libjpeg-turbo转换为内存中的jpeg。 If I use jpeg_stdio_dest I can write the whole thing to a file, then read the file back in, and it's all right. 如果我使用jpeg_stdio_dest我可以将整个文件写入文件,然后重新读取文件,就可以了。 However, trying to use jpeg_mem_dest has been a puzzle. 但是,尝试使用jpeg_mem_dest一直是个难题。 I have all the same set up as jpeg_stdio_dest , but using mem seems to only do one allocation of 4KiB and then never allocate any more space. 我有与jpeg_stdio_dest相同的设置,但是使用mem似乎只进行一次4KiB分配,然后再也不再分配任何空间。

I can't find docs with further instruction on how to use jpeg_mem_dest , and could really use some direction. 我找不到有关如何使用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
}

Yeah, that is not intuitive at all. 是的,这根本不直观。 The programmer that proposed the jpeg_mem_dest() tweak did not have much choice, extending an existing api is not that easy when it wasn't designed to support a feature in the first place. 提出jpeg_mem_dest()调整的程序员没有太多选择,扩展现有的api并不是那么容易,因为它不是为了首先支持一个功能而设计的。 What is completely unobvious is that your variables don't get updated until after the jpeg_finish_compress() call. 什么是完全不明显的是你的变量直到jpeg_finish_compress()调用之后才会更新。 Relevant code in the library is: 库中的相关代码是:

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);
}

Note the word "term". 请注意“术语”一词。 This function is called indirectly through a function pointer: 通过函数指针间接调用此函数:

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);
  //...
}

Nothing much you can do about it. 你无能为力。 Just tweak your std::cout code, move it after the loop to accommodate the way the library works. 只需调整你的std :: cout代码,在循环之后移动它以适应库的工作方式。

Beware the other gritty detail of this function, also not obvious. 要注意这个功能的其他细节,也不是很明显。 You have to free() the buffer that it created. 你必须释放()它创建的缓冲区。 Visible in the provided cjpeg.c sample program, end of main(). 在提供的cjpeg.c示例程序中可见,main()结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM