0

libjpegを使用してopenglバッファからスクリーンショットを保存しようとしています。

私が使っている機能はこれです

void OnKeyPress(unsigned char key, int x, int y) {
  if (key != static_cast<unsigned char>('p'))
    return;

  int width = g_current_width;
  int height = g_current_height;
  boost::scoped_array<boost::uint8_t> buffer(new boost::uint8_t[3 * width * height]);

  glReadBuffer(GL_FRONT);
  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
              reinterpret_cast<GLvoid *>(buffer.get()));
  glReadBuffer(GL_BACK);

  FlipImage(buffer.get(), width, height);

  // Generate a BMP files for testing purposes
  SaveRGB("screenshot.bmp", buffer.get(), width, height);

  boost::shared_ptr<FILE> outfile(fopen("screenshot.jpeg", "wb"), fclose);
  if (!outfile)
    return;

  jpeg_compress_struct cinfo;
  jpeg_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr);
  jerr.trace_level = 10;
  jpeg_create_compress(&cinfo);
  jpeg_stdio_dest(&cinfo, outfile.get());

  cinfo.image_width = width;
  cinfo.image_height = height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;
  jpeg_set_defaults(&cinfo);

  jpeg_set_quality(&cinfo, 100, true);
  jpeg_start_compress(&cinfo, true);
  int row_stride = width * 3;
  JSAMPROW row_pointer[1];
  int counter = 0;
  std::cout << boost::format("height: %d\n") % height;
  boost::uint8_t *r_buffer = buffer.get();
  while (cinfo.next_scanline < cinfo.image_height) {
    row_pointer[0] = &r_buffer[cinfo.next_scanline * row_stride];
    jpeg_write_scanlines(&cinfo, row_pointer, 1);
    std::cout << boost::format("current line: %d\n") % (counter++);
  }
  jpeg_finish_compress(&cinfo); // never reaches this point
  outfile.reset();
  jpeg_destroy_compress(&cinfo);
}

この関数は開始しますが、いくつかの反復(約100〜150)の後、関数はファイルに何も書き込まず、警告やエラーを生成せずに戻ります。

メモリエンコーディング(実際に必要なもの)を使用すると、関数は終了しますが、結果は意味がありません。さらに、バッファを解放しようとすると、エラーが発生します。これがメモリの宛先バージョンです

void OnKeyPress(unsigned char key, int x, int y) {
  if (key != static_cast<unsigned char>('p'))
    return;

  int width = g_current_width;
  int height = g_current_height;
  boost::scoped_array<boost::uint8_t> buffer(new boost::uint8_t[3 * width * height]);

  glReadBuffer(GL_FRONT);
  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
              reinterpret_cast<GLvoid *>(buffer.get()));
  glReadBuffer(GL_BACK);

  FlipImage(buffer.get(), width, height);

  // Generate a BMP files for testing purposes
  SaveRGB("screenshot.bmp", buffer.get(), width, height);

  jpeg_compress_struct cinfo;
  jpeg_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr);
  jerr.trace_level = 10;
  jpeg_create_compress(&cinfo);
  boost::uint8_t *jpeg_buffer_raw = NULL;
  unsigned long outbuffer_size = 0;
  jpeg_mem_dest(&cinfo, &jpeg_buffer_raw, &outbuffer_size);

  cinfo.image_width = width;
  cinfo.image_height = height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;
  jpeg_set_defaults(&cinfo);

  jpeg_set_quality(&cinfo, 100, true);
  jpeg_start_compress(&cinfo, true);
  int row_stride = width * 3;
  JSAMPROW row_pointer[1];
  int counter = 0;
  std::cout << boost::format("height: %d\n") % height;
  boost::uint8_t *r_buffer = buffer.get();
  while (cinfo.next_scanline < cinfo.image_height) {
    row_pointer[0] = &r_buffer[cinfo.next_scanline * row_stride];
    jpeg_write_scanlines(&cinfo, row_pointer, 1);
    std::cout << boost::format("current line: %d\n") % (counter++);
  }
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);
  std::ofstream jpegfile("screenshot.jpg");
  jpegfile.write(reinterpret_cast<const char*>(jpeg_buffer_raw), outbuffer_size);
  jpegfile.flush();
  // calling free(jpeg_buffer_raw); or delete[] jpeg_buffer_raw; generates an error
}

この関数は、次のjpeg画像を生成します。

ここに画像の説明を入力してください

比較すると、ビットマップファイルを保存する行は次のファイルを生成します。

ここに画像の説明を入力してください

4

1 に答える 1

0

問題は、FILE *ハンドラーがdll間で移植できないことです。ライブラリの静的バージョンを使用すると、問題が解決します。

インメモリバージョンは、次のようにファイルを開くことで解決できます。

std::ofstream jpegfile("screenshot.jpg", std::ios_base::out | std::ios_base::binary);
于 2012-05-08T06:48:28.567 に答える