【问题标题】:How to compress to memory with libjpeg-turbo using jpeg_mem_dest如何使用 jpeg_mem_dest 使用 libjpeg-turbo 压缩到内存
【发布时间】:2016-11-10 23:57:10
【问题描述】:

我已尝试关注another answer,但似乎无法做到这一点。我有大约 8MiB 的 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
}

【问题讨论】:

    标签: c++ libjpeg libjpeg-turbo


    【解决方案1】:

    是的,这根本不直观。提出 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);
    }
    

    注意“术语”这个词。这个函数是通过函数指针间接调用的:

    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() 结束。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多