안드로이드에는 이미지크기를 줄일때 Bitmap.createScaledBitmap() 이라는 유용한 함수를 제공해 줍니다.
함수원형을 보면 아래와 같습니다.


public static Bitmap createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)

여기서 문제는 Bitmap 소스가 들어가야 한다는 것입니다.
결국 저 함수를 쓰기위해서는 미리 디코딩 작업을해서 이미지소스를 메모리에 올려야 한다는 것이죠.


Bitmap tempBitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, resizeOpts);
Bitmap finalBitmap = Bitmap.createScaledBitmap(tempBitmap, dimen[0], dimen[1], false);
위와 같이 사용해야 합니다.
이러한 형태라면 소스 이미지가 커진다면 메모리도 그만큼 커야하는데 모바일 환경이라 그만큼 큰 가용메모리를 가진디바이스가 별로 없습니다.
결국 OutOfMemoryError 를 벹어내면서 크래시가 나게 되는것이죠.

그래서 있는것이 inSampleSize 라는 옵션입니다.
이것은 decodeStream 을 이용해 이미지를 디코딩할때 애초에 줄여서 디코딩해주는 역할을 하죠.
단점은 정확한 크기를 지정할수 없다는것입니다.
사용법은 아래와 같습니다.

BitmapFactory.Options resizeOpts = new Options();
resizeOpts.inSampleSize = 2;
Bitmap tempBitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, resizeOpts);
Bitmap finalBitmap = Bitmap.createScaledBitmap(tempBitmap, dimen[0], dimen[1], false);
이것은 디코딩을 할때 원본크기의 1/2 로 디코딩하라는 말입니다.
즉 inSampleSize 의 역수만큼의 크기로 사이즈를 줄입니다.
예를들어 4 라면 1/4 로 이미지가 줄어서 디코딩 되게 되죠.

어차피 사이즈를 줄일껀데 소스이미지 전체를 메모리에 올릴필요가 없습니다.
결국 이미지를 줄이기 위해서는 inSampleSize 를 이용하여 줄이고자하는 크기의 최대한 근접한 값으로 줄인후에 createScaledBitmap 함수를 호출해서 정확하게 줄이는것이 OutOfMemoryError 를 피하는 방법입니다.

신고
by cranix 2011.10.20 17:58
"안드로이드는 그냥 프레임워크이고 OS 는 리눅스다."
이런말 들어보셨나요?
저는 인터넷을 돌아다니다보면 몇번 보이는군요.
제가 안드로이드를 하는 입장에서 좀 거슬리는군요.^^

사실 OS 가 linux 가 아니라 커널이 linux 인거죠.
뭐.. 이런 논리라면.. unix 계열 커널을쓴 iOS 는 그냥 unix OS 라고 불러야 맞는거겠군요.

OS는 좀더 포괄적인 개념입니다.
사용자와의 상호작용까지 고려해야 하는것이죠.

그러나 안드로이드에서 쓰인 linux 커널은 운영체제가 하는 최소한의 역할만을 수행합니다.
스캐쥴링, 자원관리, 메모리관리 등을 커널에서 해주죠.
이것만으로 안드로이드가 linux 운영체제라고 불리울수 있을까요?

전혀 아니라고 생각합니다.
일단 가장 중요한 사용자와의 상호작용이 빠져있습니다.
커널에서 스캐쥴링 자원관리 메모리관리를 해 준다고 쳐도 어떤 자원을 관리할겄이면 어떤 프로세스를 스캐쥴링할지... 이런것은 어떻게 커널에 던져주나요?
설마 모든 사용자가 C 언어를 배워서 코딩해서 넘겨줘야 한다는 말은 아니겠죠?ㅋㅋ

이 모든것을 커널 위에있는 안드로이드 프레임워크단에서 처리합니다.

좀 쉽게 비교하자면 ubuntu 리눅스를 들수 있습니다.
이 역시 리눅스 커널을쓴 리눅스 OS 의 일종인데 사용자와의 상호작용을 대부분 xwindows UI 로 합니다.
안드로이드는 이 xwindows 를 쓰지 않고 새로 만들어버렸다고 생각하시면 됩니다.

게다가 기본언어를 C 언어가 아니라 접근성을 위해 java 를 채택했습니다.
안드로이드 프레임워크에서는 그래서 최상위단의 java 에서 내려오는 명령을 JNI 를 통해서 C 언어로 내려서 처리하고 이를 다시 java 로 올리고, 또 필요하다면 커널과 통신하고.. 이러한 모든 작업을 시스템화 시킨것입니다.
결과적으로 APP 개발자는 java 만 어느정도 알면 프로그램을 짤 수 있는 환경을 구축해 놓은것이죠.
만약 iOS 처럼 C 기반의 언어를 기본언어로 채택했다면 vm 이 필요없을 테니까 이보다는 훨씬 간단한 구조의 프레임워크가 나왔겠죠.

또 안드로이드는 리눅스 커널을 그냥 쓴게 아닙니다.
안드로이드에 맞게 커스토마이징 했는데 예를들자면 커널에 로우메모리킬러 라는 기능을 추가하였습니다.
이 외에도 몇가지 기능이 추가되거나 수정되었습니다.

결론적으로 저는 안드로이드는 그냥 플랫폼이 아니라 OS 라고 생각합니다.
사실 구글에서 발표한 안드로이드 자료에 자기들이 직접 안드로이드를 플랫폼이라고 써놓았던데.
이것은 구글의 지나친 겸손 이라고 생각합니다.

이걸 그냥 플랫폼 이라고 한다면 세상에 OS 는 리눅스,유닉스,윈도우 빼고는 없겠군요.
신고
by cranix 2010.07.06 14:02
| 1 |