1

JNI を使用して、OpenGL ES 2 によって変更されたカメラの出力をタブレットに保存しようとしています。

これを実現するために、NDK-r8b でコンパイルされた libjpeg ライブラリを使用します。

次のコードを使用します。

レンダリング関数では:

renderImage();
if (iIsPictureRequired)
{
  savePicture();
  iIsPictureRequired=false;
}

保存手順:

bool Image::savePicture()
{
 bool l_res =false;
char p_filename[]={"/sdcard/Pictures/testPic.jpg"};
// Allocates the image buffer (RGBA)
int l_size = iWidth*iHeight*4*sizeof(GLubyte);
GLubyte *l_image = (GLubyte*)malloc(l_size);
if (l_image==NULL)
{
  LOGE("Image::savePicture:could not allocate %d bytes",l_size);
  return l_res;
}
// Reads pixels from the color buffer (byte-aligned)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
checkGlError("glPixelStorei");
// Saves the pixel buffer
glReadPixels(0,0,iWidth,iHeight,GL_RGBA,GL_UNSIGNED_BYTE,l_image);
checkGlError("glReadPixels");
// Stores the file
FILE* l_file  = fopen(p_filename, "wb");
if (l_file==NULL)
 {
   LOGE("Image::savePicture:could not create %s:errno=%d",p_filename,errno);
   free(l_image);
   return l_res;
 }
 // JPEG structures
 struct jpeg_compress_struct cinfo;
 struct jpeg_error_mgr       jerr;

 cinfo.err = jpeg_std_error(&jerr);
 jerr.trace_level = 10;

 jpeg_create_compress(&cinfo);
 jpeg_stdio_dest(&cinfo, l_file);
 cinfo.image_width      = iWidth;
 cinfo.image_height     = iHeight;
 cinfo.input_components = 3;
 cinfo.in_color_space   = JCS_RGB;
 jpeg_set_defaults(&cinfo);

 // Image quality [0..100]
 jpeg_set_quality (&cinfo, 70, true);
 jpeg_start_compress(&cinfo, true);

 // Saves the buffer
 JSAMPROW row_pointer[1];          // pointer to a single row

 // JPEG stores the image from top to bottom (OpenGL does the opposite)
 while (cinfo.next_scanline < cinfo.image_height)
{
  row_pointer[0] = (JSAMPROW)&l_image[(cinfo.image_height-1-cinfo.next_scanline)* (cinfo.input_components)*iWidth];
  jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
// End of the process
jpeg_finish_compress(&cinfo);
fclose(l_file);
free(l_image);
l_res =true;
return l_res;

}

表示は正しいのですが、生成された JPEG が 3 倍になり、左から右に重なっているように見えます。

スケーリングされた画像 (元のサイズは 1210x648)

私は何を間違えましたか?

4

1 に答える 1

0

jpeg lib とキャンバスの内部フォーマットが一致していないようです。その他は RGBRGBRGB、その他は RGBARGBARGBA で読み取り/エンコードするように見えます。

他のすべてが失敗した場合は、画像データを再配置できる場合があります...

 char *dst_ptr = l_image; char *src_ptr = l_image;
 for (i=0;i<width*height;i++) { *dst_ptr++=*src_ptr++;
  *dst_ptr++=*src_ptr++; *dst_ptr++=*src_ptr++; src_ptr++; }

編集: 原因が確認されたので、さらに簡単な変更があるかもしれません。正しい形式で gl ピクセル バッファからデータを取得できる場合があります。

 int l_size = iWidth*iHeight*3*sizeof(GLubyte);
 ...
 glReadPixels(0,0,iWidth,iHeight,GL_RGB,GL_UNSIGNED_BYTE,l_image);

もう 1 つ警告があります。これがコンパイルされても、出力が傾斜している場合は、画面の幅が 4 の倍数ではなく、opengl が dword 境界で新しい行を開始しようとしていることを意味します。しかし、その場合、l_size予想よりも 1、2、または 3 バイト大きくなるはずなので、クラッシュの可能性が高くなります。

于 2012-11-14T18:57:52.003 に答える