하나의 안드로이드 앱에서 다룰 수 있는 메모리의 한계 때문에 큰 사이즈 이미지는 OutofMemory exception이나 퍼포먼스 문제가 생길 수 있다. 작은 뷰의 크기에 맞지 않는 고해상도의 이미지를 불러오는 것은 괜한 리소스를 낭비하게 만든다.
=== BitMap.java ===
|
import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.view.View;
public class BitMap extends View { public BitMap(Context context) { super(context); }
protected void onDraw(Canvas canvas){ canvas.drawColor(Color.CYAN);
// Resource 폴더에 저장된 그림파일을 Bitmap 으로 만들어 리턴해준다 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.car1); // 이미지가 너무 크면 화면에서 잘려서 보임 canvas.drawBitmap(bitmap,10,10,null); // 비트맵 이미지를 캔버스에 출력하는 함수 } } |
Bitmap myImage = BitmapFactory.decodeFile(“/sdcard/car1.jpg”); BitmapFactory.decodeFile() : 로컬에 존재하는 파일을 그대로 읽어올 때 쓴다. 파일경로를 파라미터로 넘겨주면 FileInputStream 을 만들어서 decodeStream 을 한다.
Canvas.drawBitmap() 은 비트맵 이미지를 캔버스에 출력하는 함수 - 1번째 파라미터는 비트맵 이미지 객체, 2번째 파라미터는 원본 이미지의 영역좌표, - 3번째 파라미터는 이미지가 표시되는 화면상의 영역좌표, 4번째 파라미터는 Paint 객체 - 2번째와 4번째파라미터는 생략 가능하다.
|
=== MainActivity.java ===
|
import android.support.v7.app.AppCompatActivity; import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);
BitMap myView = new BitMap(this); setContentView(myView); } } |
https://ringsterz.wordpress.com/2014/11/27/imageview%EC%97%90-%EB%8C%80%EC%9A%A9%EB%9F%89-bitmap-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%A1%9C%EB%94%A9%ED%95%98%EA%B8%B0/
에 자동으로 줄이는 함수가 있어서 이걸 이용해서 테스트 해봤다.
BitmapFactory.Options : BitmapFactory 가 사용하는 옵션클래스이다.
Options 객체를 생성하고 설정하고자 하는 옵션을 넣은후 BitmapFactory 의 함수 실행시 파라미터로 넘기면된다.
inSampleSize : decode 시 얼마나 줄일지 설정하는 옵션인데 1보다 작을때는 1이 된다.
1보다 큰값일 때 1/N 만큼 이미지를 줄여서 decoding 하게 된다. 보통 2의 배수로 설정한다.
import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.view.View;
public class BitMap extends View { public BitMap(Context context) { super(context); }
protected void onDraw(Canvas canvas){ canvas.drawColor(Color.CYAN);
// Resource 폴더에 저장된 그림파일을 Bitmap 으로 만들어 리턴해준다 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.car2); // 이미지가 너무 크면 화면에서 잘려서 보임 canvas.drawBitmap(bitmap,10,10,null);
Bitmap resize = resize_decodeResource(getResources(), R.drawable.car2, 100, 100); canvas.drawBitmap(resize,10,900,null); // 비트맵 이미지를 캔버스에 출력하는 함수 }
public static Bitmap resize_decodeResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } } |
이미지 출력 결과
![](https://t1.daumcdn.net/cfile/tistory/227CAF4B58DF08981A)
Bitmap resize = resize_decodeResource(getResources(), R.drawable.car2, 100, 100);
에서 width 와 height 지정된 크기로 이미지가 줄어드는게 아니라 원래 이미지 크기가 width 와 height 중에서 작은 것 기준으로 맞춰서 줄여진다.
그래서 높이 기준으로 줄여주는 걸로 수정을 했다.
protected void onDraw(Canvas canvas){ canvas.drawColor(Color.CYAN);
Bitmap resize = autoresize_decodeResource(getResources(), R.drawable.car2, 100); canvas.drawBitmap(resize,10,300,null); // 비트맵 이미지를 캔버스에 출력하는 함수 }
public static Bitmap autoresize_decodeResource(Resources res, int resId, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize options.inSampleSize = calculateInAutoSize(options, reqHeight);
// Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
public static int calculateInAutoSize(BitmapFactory.Options options, int reqHeight) { // 원본 이미지의 높이와 너비 final int height = options.outHeight; final int width = options.outWidth;
float ratio = width / height; int reqWidth = Math.round((float) ratio * width);
int inSampleSize = 1; if (height > reqHeight) { final int halfHeight = height / 2; while ((halfHeight / inSampleSize) > reqHeight) { inSampleSize *= 2; } } return inSampleSize; } |