YesYo.com MintState Forums
뒤로    YesYo.com MintState BBS > Tech > Android
검색
멤버이름    오토
비밀번호 
 

BitmapDrawable과 Bitmap

페이지 정보

작성자 MintState 댓글 0건 조회 10,720회 작성일 11-06-09 10:26

본문

BitmapDrawable과 Bitmap

[Intro]

보통 BitmapFactory의 decode 함수들은 메모리 Leak이 존재한다고 알려져 있습니다.
(2.1에서 수정이 되었는지 아직도 그대로인지는 잘 모르겠습니다.)

실제로 안그럴지 몰라도,
decode를 하면 할 수록 메모리 Leak의 위험부담은 더 커지기 마련이죠.
제가 처음에 Drawable을 Bitmap으로 바꿀 때 BitmapFactory를 사용 했었습니다.

정확히 말하면 Drawable을 Bitmap으로 바꾼 것이 아니라
RawResourceInputStream으로 얻어와서 BitmapFactory로 decode한 것이었죠.

Bitmap bitmap;
InputStream stream;
stream = context.getResources().openRawResource(resource);
try {
    bitmap = BitmapFactory.decodeStream(stream);
} 
finally {
    try { stream.close(); } 
    catch(IOException e) {}
} 


하지만 위의 코드는 계속 BitmapFactory를 호출 하기 때문에
잠재적인 위험을 가지고 있습니다.

그렇다면 리소스로 부터 Bitmap을 얻어내고 싶다면 어떻게 해야 할까요?


[Googling...]

일단 포스팅 하기전에 구글링을 좀 해봤습니다.
상위 몇개의 검색 결과를 살펴보니... 

구글링으로 살펴본 결과들은 대부분 아래와 같이 되어있었습니다.

Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas); 


1. 빈 Bitmap을 만들고
2. Canvas를 연결 한 뒤
3. Drawable의 draw메소드를 통해 Bitmap과 연결된 Canvas에 Drawable의 내용을 그립니다.

물론 이 방법이 틀린 것은 아닙니다.
하지만 만들어 줘야 하는것이,

1. Drawable 크기만한 빈 Bitmap
2. Bitmap에 연결할 Canvas
3. 크기를 가지는 Width, Height 변수

Drawable 객체를 제외하고 두개의 객체두개의 변수를 더 만들어야 합니다.
중간에 setBounds() 메소드도 호출 해야 겠죠.

근데 여기서 한가지 잘 생각해 봐야 할 것이 있습니다.
View안에서는 Drawable을 잘 사용해서 이미지를 표시해 주고 있다는 점입니다.
Layout XML 파일 안에서 ImageView의 이미지를 지정해 줄 때
Drawable을 잘~ 사용해왔다는 것이 하나의 예가 될 수 있겠네요.

그렇다면 Drawable이 당연히 Bitmap을 가지고 있어야 하지 않을까요?


[BitmapDrawable]

질문에 대한 답은 바로 BitmapDrawable에 담겨있습니다.
아래의 코드를 보시죠!

BitmapDrawable drawable =
            (BitmapDrawable) getResources().getDrawable(R.drawable.icon);
Bitmap bitmap = drawable.getBitmap();


읭...? 이게 끝입니다.
BitmapDrawable을 사용하면 Bitmap을 손쉽게 얻어 올 수 있습니다.
위의 길고 긴 코드가 단 두 줄로 줄어 들었습니다.

따로 Bitmap을 만들지 않아도 됩니다.
그냥 Drawable안에 있는 Bitmap을 사용하기만 하면 됩니다.
 

[주의사항!]

BitmapDrawable을 사용하면 손쉽게 Bitmap을 얻을 수는 있지만,
Drawable이 꼭 BitmapDrawable만 존재 하는 것은 아닙니다.
대표적인 예로 ShapeDrawable이 있을 수 있겠네요.
ShapeDrawable을 사용하면 원하는 도형(Shape 객체)을 Drawable로 사용 할 수 있습니다.

하지만 getBitmap() 메소드가 없기 때문에
ShapeDrawable로 부터 Bitmap을 얻어 올 수는 없습니다.
굳이 도형을 Bitmap으로 바꾸고 싶다면 위에서 봤던 빈 Bitmap과 Canvas를 만들어서
draw() 메소드를 통해 그리는 방법 밖에는 없습니다.

아마도 대부분의 경우 drawable 디렉토리에 있는 이미지들을 Bitmap으로 사용하려고 하지,
Shape을 Bitmap으로 사용하려고 하지는 않을 거라 생각합니다.
네네... 그럴겁니다...


[BitmapDrawable Bitmap의 특징]

BitmapDrawable에서 얻어온 Bitmap 객체는 보통녀석이 아닙니다.
특징을 한번 살펴 봅시다.

1. 우선, Bitmap을 얻어 올 때는 final 입니다.
 레퍼런스에 보면 final로 선언되어 있습니다.
즉, 변경하지 않겠다는 의지를 표현 한 것이죠.
사실 리턴에 final을 붙여봤자 대입되는 변수와는 아무 상관이 없습니다... 네... 넘어가죠.

2. Immutable 입니다.
좀 더 강력한 녀석이 나왔습니다. Immutable, 즉, 변경 불가입니다.
Canvas canvas = new Canvas(bitmap); 

만약 위와 같은 시도를 한다면, 아래와 같은 Exception이 발생 할겁니다.


3. 절대 recycle() 메소드를 호출 해서는 안됩니다!
Bitmap을 얻어와서 그릴거 다 그렸다고 무의식적으로 recycle() 메소드를 호출 했다...
그럼 아래와 같은 메세지를 볼 수 있습니다.

위의 상황은 ImageView 같은데서 사용하고 있던 Drawable의 Bitmap 객체를 얻어와서
그 Bitmap 객체에 recycle() 메소드를 호출 한 상황입니다.
한마디로 Bitmap 객체를 공유해서 사용한다고 볼 수 있겠죠.


[One more Tip - Bitmap copy]

그렇다면 BitmapDrawable로 부터 얻어낸 Bitmap 객체를
마음대로 바꾸고, 쓰고, 버리고 싶다면 어떻게 해야 할까요?

그냥 copy() 하면 됩니다.

Bitmap bitmap = drawable.getBitmap().copy(Config.ARGB_8888, true);


Mutable로 복사하면 마음대로 변경해서 사용 할 수 있습니다!


[Outro]

이번에는 BitmapDrawable과 Bitmap에 대해서 살짝 살펴보았습니다.
앞에서는 BitmapDrawable을 Bitmap으로 바꾸는 이야기만 했었지만,
반대로 Bimap을 Drawable로 바꾸고 싶다면
BitmapDrawable의 생성자를 사용하면 간단히 Drawable로 만들 수 있습니다.

물론 구글링해서 찾은 방법이 틀린 방법은 아닙니다.
이미지와 관련이 없는 Drawable을 다루고자 할 때는
번거롭게도 draw() 메소드를 이용 해야 하는것이 맞지만,
이미지와 관련된 Drawable을 다루고자 할 때는 분명 BitmapDrawable을 사용하는 것이 더 편합니다.

네... 제가 하고 싶은말은 그겁니다.
이미지 파일 힘들게 바꾸지 맙시다!


URL : http://blog.vizpei.kr/105116344

댓글목록

등록된 댓글이 없습니다.

Total 18건 1 페이지
게시물 검색
모바일 버전으로 보기
CopyRight ©2004 - 2024, YesYo.com MintState. ™