티스토리 뷰

Bitmap 객체는 메모리에 만들어지는 이미지라고 할 수 있다. 컴퓨터 내에 저장되는 대부분의 이미지 파일을 읽어 들이면 메모리에 비트맵 객체로 만들 수 있다. 그리고 비트맵 객체를 이용하면 화면에 이미지를 수정하거나 그릴 수 있다. 

 

비트맵은 그래픽을 그릴 수 있는 메모리 공간을 제공한다. 흔히 Double Buffering 이라고 불리는 방법인데, 별도의 메모리 공간에 미리 그래픽을 그린 후 뷰가 다시 그려져야 할 필요가 있을 때, 미리 그려놓은 비트맵을 화면에 표시하는 방법이다. 

 


◎CustomViewImage.java

package com.example.customviewimage;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;

public class CustomViewImage extends View {

    // 메모리에 만들어질  Bitmap 객체 선언
    private Bitmap cacheBitmap;

    // 메모리에 만들어질 Bitmap 객체에 그리기 위한 Canvas 객체 선언
    private Canvas cacheCanvas;


    private Paint mPaint;

    public CustomViewImage(Context context) {
        super(context);
        init(context);
    }

    public CustomViewImage(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public void init(Context context) {
        mPaint = new Paint();
    }

    // 뷰가 화면에 보이기 전에 Bitmap 객체를 생성한 뒤 그리기
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        createCacheBitmap(w, h);
        testDrawing();
    }

    // 메모리에 Bitmap 객체를 만들고 Canvas 객체 설정
    private void createCacheBitmap(int w, int h) {
        cacheBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        cacheCanvas = new Canvas();
        cacheCanvas.setBitmap(cacheBitmap);
    }

    // 빨간 사각형 그리기
    private void testDrawing() {
        cacheCanvas.drawColor(Color.WHITE);
        mPaint.setColor(Color.RED);
        cacheCanvas.drawRect(100, 100, 200, 200, mPaint);
    }

    // 메모리의 Bitmap을 이용해 화면에 그리기
    protected void onDraw(Canvas canvas) {
        if(cacheBitmap != null) {
            canvas.drawBitmap(cacheBitmap, 0, 0, null);
        }
    }
}

 

위 코드에서 뷰가 새로 그려질 때 호출되는 onDraw() 메서드를 보면 단순히 메모리에 만들어 두었던 cacheBitmap을 그리는 코드만 들어가 있다.

 

실제 그래픽을 그리는 시점은 testDrawing() 메서드가 호출되었을 때이며, createBitmap() 메서드를 이용해 만들어지는 비트맵 객체는 뷰의 onSizeChanges() 메서드가 호출되었을 때 초기화된 후, testDrawing() 메서드에 의해 그려지게 된다. 

 

또한 위 코드처럼 비트맵을 메모리에 만들면 다양한 그리기 방법이나 그래픽 효과를 적용할 수 있고 화면에 보여줄 수 있다.

BitmapFactory Class 는 비트맵 이미지를 만들기 위한 클래스 메서드들을 제공하며, 이 메서드들은 이미지를 메모리에 비트맵 객체로 만들 수 있는 방법을 제공한다.

 

BitmapFactory Class에 정의된 대표적인 메서드들은 다음과 같다.

 

파일에서 읽기 파일 path를 지정하면 해당 위치의 이미지 파일을 읽어온다.
=> public static Bitmap decodeFile(String pathName)
리소스에서 읽기 리소스에 저장한 이미지 파일을 읽어온다.
=> public static Bitmap decodeResource(Resources res, int id)
바이트에서 배열에서 읽기 바이트 배열로 되어 있는 이미지 파일을 읽어온다.
=> public static Bitmap decodeByteArray(byte[] data, int offset, int length)
스트림에서 읽기 입력 스트림에서 이미지 파일을 읽어온다.
=> public static Bitmap decodeStream(InputStream is)

 


또한 Matrix나 Mask 객체를 이용하여 비트맵 이미지에 다양한 효과를 넣을 수도 있다.

 

◎CustomViewImage.java

package com.example.customviewimage;

import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;

public class CustomViewImage extends View {

    // 메모리에 만들어질  Bitmap 객체 선언
    private Bitmap cacheBitmap;

    // 메모리에 만들어질 Bitmap 객체에 그리기 위한 Canvas 객체 선언
    private Canvas cacheCanvas;


    private Paint mPaint;

    public CustomViewImage(Context context) {
        super(context);
        init(context);
    }

    public CustomViewImage(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public void init(Context context) {
        mPaint = new Paint();
    }

    // 뷰가 화면에 보이기 전에 Bitmap 객체를 생성한 뒤 그리기
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        createCacheBitmap(w, h);
        testDrawing();
    }

    // 메모리에 Bitmap 객체를 만들고 Canvas 객체 설정
    private void createCacheBitmap(int w, int h) {
        cacheBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        cacheCanvas = new Canvas();
        cacheCanvas.setBitmap(cacheBitmap);
    }

    // 빨간 사각형 그리기
    private void testDrawing() {
        cacheCanvas.drawColor(Color.WHITE);
        mPaint.setColor(Color.RED);
        cacheCanvas.drawRect(100, 100, 200, 200, mPaint);

        // 리소스 이미지 파일 Read
        Bitmap srcImg = BitmapFactory.decodeResource(getResources(), R.drawable.waterdrop);
        cacheCanvas.drawBitmap(srcImg, 30, 30, mPaint);

        // Matrix 객체를 이용해 좌우 대칭이 되거나 상하 대칭이 되는 비트맵 이미지를 만들어 그려준다.
        // 이미지를 다른 형태로 바꾸는 이미지 변환을 위해 Matrix 클래스가 사용된다.
        Matrix horInverseMatrix = new Matrix();
        // 대칭 이미지 생성 (-1, 1): 좌우 대칭, (1, -1): 상하 대칭
        horInverseMatrix.setScale(-1, 1);
        Bitmap horInverseImg = Bitmap.createBitmap(srcImg, 0, 0,
                srcImg.getWidth(), srcImg.getHeight(), horInverseMatrix, false);
        cacheCanvas.drawBitmap(horInverseImg, 30, 130, mPaint);

        Matrix verInverseMatrix = new Matrix();
        verInverseMatrix.setScale(1, -1);
        Bitmap verInverseImg = Bitmap.createBitmap(srcImg, 0, 0,
                srcImg.getWidth(), srcImg.getHeight(), verInverseMatrix, false);
        cacheCanvas.drawBitmap(verInverseImg, 30, 230, mPaint);


        // Mask 객체를 사용하여 이미지에 효과 추가
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
        // 이미지 확대
        Bitmap scaledImg = Bitmap.createScaledBitmap(srcImg,
                srcImg.getWidth()*3, srcImg.getHeight()*3, false);
        cacheCanvas.drawBitmap(scaledImg, 30, 300, mPaint);
    }

    // 메모리의 Bitmap을 이용해 화면에 그리기
    protected void onDraw(Canvas canvas) {
        if(cacheBitmap != null) {
            canvas.drawBitmap(cacheBitmap, 0, 0, null);
        }
    }
}

Comments