IT_Programming/OpenGL

안드로이드 GL_MAX_TEXTURE_SIZE 값 구하기 / 이미지 크기 구하고 변경하기

JJun ™ 2013. 7. 26. 19:28

 


 출처: http://javacan.tistory.com/entry/TIP-Get-GLMAXTEXTURESIZE-value-in-android

         http://javacan.tistory.com/entry/tip-get-size-of-image-and-resize-in-android


 

안드로이드의 ImageView에 출력할 수 있는 이미지 크기에 제한이 있는데, 이 제한은 장치마다 다르다.

예를 들어, 넥서스7의 경우는 2048*2048 이내의 이미지를 출력할 수 있고, 갤럭시노트10.1의 경우

4096*4096 이내의 이미지를 출력할 수 있다.

 

만약 제한 크기를 넘는 이미지를 ImageView를 통해 보여주려고 하면 다음과 비슷한 메시지가 로그에

출력되면서 ImageView에 이미지가 출력되지 않게 된다.


W/OpenGLRenderer(6156): Bitmap too large to be uploaded into a texture (560x6076, max=2048x2048)


ImageView에 표시할 수 있는 이미지의 제한 크기를  알아내려면 OpenGL의 glGetIntegerv() 메서드를

사용하면 된다. 이 메서드를 사용하려면 OpenGL Context를 생성해주어야 하는데, SurfaceView를

이용하면 간단하게 알아낼 수 있다.


다음은 SurfaceView와 OpenGL을 이용해서 제한 크기를 알아내는 코드 예이다.

import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGL10;

import javax.microedition.khronos.egl.EGLContext;

import javax.microedition.khronos.opengles.GL10;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

...


public class SplashActivity extends Activity {


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.splash_layout);

LinearLayout layout = (LinearLayout) findViewById(R.id.body);

layout.addView(new GetMaxTextureSizeSurfaceView(this));

}


private void goHome() {

Intent intent = new Intent(this, HomeActivity.class);

startActivity(intent);

finish();

}


class GetMaxtextureSizeSurfaceView extends SurfaceView implements

SurfaceHolder.Callback {


public GetSizeSurfaceView(Context context) {

super(context);

SurfaceHolder holder = getHolder();

holder.addCallback(this);

}


@Override

public void surfaceCreated(SurfaceHolder holder) {

setMaxTextureSize();

goHome();

}


private void setMaxTextureSize() {

EGL10 egl = (EGL10) EGLContext.getEGL();

EGLContext ctx = egl.eglGetCurrentContext();

GL10 gl = (GL10) ctx.getGL();

IntBuffer val = IntBuffer.allocate(1);

gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, val);

int size = val.get(); // 최대 크기 구함

Constants.setMaxTextureSize(size); // Constants는 글로벌 변수 저장용

}


@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}


@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}


}

}


최초로 실행되는 Activity에서 위와 같이 glGetIntegerv() 함수를 이용해서 최대 크기 값을 글로별 변수에

저장하면, 이후 Activity에서는 글로벌 변수를 이용해서 Bitmap 크기가 최대 크기를 넘어섰는지 확인할 수 있다. 만약 최대 크기를 넘어섰다면 이미지를 허용까지 줄여서 출력하면 된다.


주의할 점은 SurfaceView가 화면에 반드시 보여야 한다는 점이다.

화면에 보이지 않게 되면 관련 콜백 메서드(surfaceCreated() 등)가 호출되지 않는다. 

GetSizeSurfaceView는 단순히 최대 크기를 알아내기 위해 만든 것이므로 1px 정도의 크기를 갖는

Layout에 SurfaceView를 추가하는 방법으로 SurfaceView를 생성하면 화면에 영향을 거의 안 주면서 SurfaceView를 이용해서 MAX_TEXTURE_SIZE 값을 구할 수 있을 것이다.


이미지 크기를 알아내고 크기를 변경하는 방법은 아래와 같다.

 

 

안드로이드에서 이미지를 ImageView에 출력할 때 발생할 수 있는 문제는 크게 다음의 두 가지가 있다.

 

 

이 두 가지 문제를 해소하려면 이미지 크기가 특정 크기를 넘어선 경우 이미지 크기를 줄여서 읽어오면 된다.

 

 


이미지 크기 구하기
 
이미지 크기를 구할 때에는 BitmapFactory.Options의 inJustDecodeBounds 값을 true로 지정해 주고,

이 옵션을 이용해서 BitmapFactory의 decode 메서드를 사용한다. 아래는 파일로부터 이미지 크기를
구할 때 사용되는 코드 예를 보여주고 있다.


 

private BitmapFactory.Options getBitmapSize(File imageFile) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);
return options;
}


BitmapFactory의 decode 메서드는 옵션의 inJustDecodeBounds 값이 true일 경우,

이미지의 크기만 구해서 옵션에 설정한다. 이 메서드 실행 후, 옵션의 

 

 

BitmapFactory.options option = getBitmapSize(imgFile);
// option.outWidth : 이미지 폭
// options.outHeight : 이미지 높이
 
if (option.outWidth > maxWidthSize || option.outHeight > maxHeightSize) {
    // 최대 크기를 벗어난 경우의 처리, 이미지 크기 변환 등
}
 
이 값을 이용해서 이미지가 제한된 크기를 벗어났는지의 여부를 알 수 있다.

 

 

이미지 크기 변경하기

이미지 크기를 변경할 때에는 옵션의 inSampleSize 값을 이용한다.

예를 들어, 아래 코드는 크기를 2배 축소시켜서 Bitmap을 생성해주는 코드이다.


 

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);

 

3000*2000 크기의 이미지가 있을 때, inSampleSize 값으로 2를 사용하면 생성되는 Bitmap의 크기는 1500*1000이 된다. inSampleSize의 값을 4로 주면 실제 폭/높이는 1/4로 줄고, 8을 주면 실페 폭/높이는 1/8로 준다. 
2의 거듭제곱을 inSampleSize의 값으로 주면 연산이 좀 더 빠르게 처리된다.

 

 


관련 자료