4

私は別の答えに従ってみましたが、これを正しく理解できないようです。libjpeg-turbo を使用して、約 8MiB の RBGX ビットマップをメモリ内の jpeg に変換します。私が使用する場合jpeg_stdio_dest、すべてをファイルに書き込んでから、ファイルを読み戻すことができます。それで問題ありません。しかし、使おうとするjpeg_mem_destのはパズルでした。私は とすべて同じ設定をしていますjpeg_stdio_destが、使用するmemと 4KiB の割り当てが 1 回しか行われず、それ以上のスペースが割り当てられないようです。

の使用方法に関する詳細な説明が記載されたドキュメントを見つけることができず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
}
4

1 に答える 1

5

ええ、それはまったく直感的ではありません。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() の最後に表示されます。

于 2016-11-14T00:31:00.860 に答える