출처 : http://lsit81.tistory.com/33

 

며칠전 BitmapFactory.Options.inPurgeable에 대한 내용을 올렸는데요.
BitmapFactory.Options에 대한 정리가 필요할 것 같아 주요 옵션에 대하여 정리를 해보았습니다.


1. Image Width, Height 정보만 가져오기.
: BitmapFactory.Options.inJustDecodeBounds = true
이렇게 사용할 경우 Image를 메모리로 로드하지 않은 상태로 Image의 width, height 정보만을 가져올 수 있습니다.

1
2
3
4
5
6
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile("[경로]", opts);
Log.d("bitmap", "image width = " + opts.outWidth
+ ", height = " + opts.outHeight + ", mime type = " + opts.outMimeType);

public boolean inJustDecodeBounds

If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.





2. 메모리 최적화하여 화면 크기에 맞게 Image Load하기.
안드로이드는 기본적으로 JVM Heap Memory가 얼마되지 않습니다.
구글에서는 최소 16MByte로 정하고 있으나, 제조사 별로 디바이스별로 Heap영역의 크기는 다르게 정하여 사용하고 있습니다.

그러나 제조사별로 좀더 많은 양의 heap 영역을 셋팅을 하였다 하여도 32Mbyte를 넘는 디바이스는 흔치 않으며, 많은 양의 그래픽 작업을 해야 하는 경우 heap 메모리는 여전히 부족합니다.

그래서 Image를 load할때는 필요한 만큼만 이미지를 sampling 하여 로드를 할 필요가 있습니다.

이를 지원해 주는 것이 BitmapFactory.Options.inSampleSize 옵션입니다.
구글 Developer Site에 가보시면 아래와 같이 정의가 되어 있습니다.

public int inSampleSize

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder will try to fulfill this request, but the resulting bitmap may have different dimensions that precisely what has been requested. Also, powers of 2 are often faster/easier for the decoder to honor.



그리고 아래와 같이 화면(또는 이미지 뷰) 크기에 따라서 이미지를 sampling하여 사용하면 더욱 효과적으로 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static Bitmap readImageWithSampling(String imagePath, int targetWidth, int targetHeight,
Bitmap.Config bmConfig) {
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoWidth = bmOptions.outWidth;
int photoHeight = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoWidth / targetWidth, photoHeight / targetHeight);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inPreferredConfig = bmConfig;
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap orgImage = BitmapFactory.decodeFile(imagePath, bmOptions);
return image;
}



3. 빠르게 Image load하기?
: BitmapFactory.Options.inDither = false

inDither는 이미지를 깔끔하게 처리해주는 옵션이라고 하는데...
테스트해본 결과 제가 보기에는 false 옵션을 주는 것이 이미지는 더 이뻐 보이는 건 저만의 착각일까요???

참고로 이미지를 loading하는 속도 또한 false로 주었을 경우 이미지에 따라 최대 약 2배까지 빠른 것을 보았습니다.

아래는 테스트한 샘플 사진을 첨부합니다.
자세히 보시면 약간의 차이를 느끼실 수 있습니다.


위쪽 사진이 false 옵션을 주어 이미지를 로드한 상태고

아래 사진이 true 옵션을 주어 이미지를 로드한 상태 입니다.


이미지 로딩 시간은 각각 623ms, 542ms가 걸렸습니다.


 




4. Drawable-hdpi, mdpi 에 있는 리소스 이미지 크기 변환 없이 원본 load 하기.

안드로이드에서는 drawable에 있는 이미지를 load시 해당 dpi에 맞춰 이미지를 자동으로 resize하여 이미지를 로드하게 됩니다.
그런데 간혹 resize 없이 이미지를 로드하고 싶은 경우가 생기는데요..

그럴 경우 inScaled 옵션을 false로 설정하여 이미지를 불러오면 resize 없이 이미지를 불러올 수 있습니다.

public boolean inScaled

When this flag is set, if inDensity and inTargetDensity are not 0, the bitmap will be scaled to match inTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas.

This flag is turned on by default and should be turned off if you need a non-scaled version of the bitmap. Nine-patch bitmaps ignore this flag and are always scaled.

+ Recent posts