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으로 바꾼 것이 아니라
RawResource를 InputStream으로 얻어와서 BitmapFactory로 decode한 것이었죠.
하지만 위의 코드는 계속 BitmapFactory를 호출 하기 때문에
잠재적인 위험을 가지고 있습니다.
그렇다면 리소스로 부터 Bitmap을 얻어내고 싶다면 어떻게 해야 할까요?
[Googling...]
일단 포스팅 하기전에 구글링을 좀 해봤습니다.
상위 몇개의 검색 결과를 살펴보니...
구글링으로 살펴본 결과들은 대부분 아래와 같이 되어있었습니다.
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, 즉, 변경 불가입니다.
만약 위와 같은 시도를 한다면, 아래와 같은 Exception이 발생 할겁니다.
3. 절대 recycle() 메소드를 호출 해서는 안됩니다!
Bitmap을 얻어와서 그릴거 다 그렸다고 무의식적으로 recycle() 메소드를 호출 했다...
그럼 아래와 같은 메세지를 볼 수 있습니다.
위의 상황은 ImageView 같은데서 사용하고 있던 Drawable의 Bitmap 객체를 얻어와서
그 Bitmap 객체에 recycle() 메소드를 호출 한 상황입니다.
한마디로 Bitmap 객체를 공유해서 사용한다고 볼 수 있겠죠.
[One more Tip - Bitmap copy]
그렇다면 BitmapDrawable로 부터 얻어낸 Bitmap 객체를
마음대로 바꾸고, 쓰고, 버리고 싶다면 어떻게 해야 할까요?
그냥 copy() 하면 됩니다.
Mutable로 복사하면 마음대로 변경해서 사용 할 수 있습니다!
[Outro]
이번에는 BitmapDrawable과 Bitmap에 대해서 살짝 살펴보았습니다.
앞에서는 BitmapDrawable을 Bitmap으로 바꾸는 이야기만 했었지만,
반대로 Bimap을 Drawable로 바꾸고 싶다면
BitmapDrawable의 생성자를 사용하면 간단히 Drawable로 만들 수 있습니다.
물론 구글링해서 찾은 방법이 틀린 방법은 아닙니다.
이미지와 관련이 없는 Drawable을 다루고자 할 때는
번거롭게도 draw() 메소드를 이용 해야 하는것이 맞지만,
이미지와 관련된 Drawable을 다루고자 할 때는 분명 BitmapDrawable을 사용하는 것이 더 편합니다.
네... 제가 하고 싶은말은 그겁니다.
이미지 파일 힘들게 바꾸지 맙시다!
URL : http://blog.vizpei.kr/105116344
[Intro]
보통 BitmapFactory의 decode 함수들은 메모리 Leak이 존재한다고 알려져 있습니다.
(2.1에서 수정이 되었는지 아직도 그대로인지는 잘 모르겠습니다.)
실제로 안그럴지 몰라도,
decode를 하면 할 수록 메모리 Leak의 위험부담은 더 커지기 마련이죠.
제가 처음에 Drawable을 Bitmap으로 바꿀 때 BitmapFactory를 사용 했었습니다.
정확히 말하면 Drawable을 Bitmap으로 바꾼 것이 아니라
RawResource를 InputStream으로 얻어와서 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
|
댓글목록
등록된 댓글이 없습니다.