2012-11-14 2 views
1

OpenGL ES 2에서 수정 한 카메라의 출력을 JNI를 통해 내 태블릿에 저장하려고합니다.SurfaceTexture를 JPEG로 저장

이 작업을 수행하기 위해 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는 배와 중복에서 보인다 왼쪽에서 오른쪽으로.

Scaled image (original size is 1210x648)

내가 무슨 일을 했는가?

답변

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

편집 : 지금 원인이 확인되어, 더 간단한 수정이있을 수 있습니다. 경고

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

그리고 하나 더 조각 : 올바른 형식으로 GL 픽셀 버퍼에서 데이터를 얻을 수있을이 컴파일하면되지만 출력은 는이 있음을 의미를 기울이면 당신의 화면 너비는 4의 배수가 아니지만 OpenGL은 각각의 새 행을 dword 경계에서 시작하려고합니다. 그러나이 경우에는 충돌 가능성이 있습니다.이 경우 l_size은 예상보다 1,2 또는 3 바이트 커야합니다.

+0

'cinfo.input_components = 4; cinfo.in_color_space = JCS_RGBA_8888;을 사용하면'jpeg_set_defaults (& cinfo);에 크래시가 발생합니다. –

+0

많은 감사합니다. glReadPixels (...) 후에 코드를 추가하면 문제가 해결됩니다. 이 솔루션이 내 태블릿에만 해당합니까? –

+0

타블렛과 관련이 없다고 생각합니다. 하지만 어쨌든 세 구성 요소 이미지에 대해 4 바이트 형식을 허용하는 libjpeg의 구성이 있어야합니다. –