본문 바로가기
안드로이드 자바

[Android][Java] 비트맵 합치기 PorterDuff.Mode

by teamnova 2023. 9. 23.

오늘은 안드로이드 PorterDuff.Mode 를 사용하여 비트맵 두개를 합치는 코드를 구현해보겠습니다.

 

PorterDuff.Mode은 안드로이드에서 그래픽 처리를 위한 모드를 지정하는 열거형(enum)입니다. 이 모드는 두 그림을 합성(composite)할 때 사용됩니다. 일반적으로 두 그림이 겹쳐질 때 어떻게 합성할지를 결정하는데 사용됩니다.

  1. SRC_OVER:
    • 첫 번째 그림 위에 두 번째 그림을 덮습니다.
  2. SRC_IN:
    • 첫 번째 그림과 두 번째 그림의 겹치는 부분만 보여줍니다.
  3. SRC_OUT:
    • 첫 번째 그림에서 두 번째 그림의 겹치지 않는 부분만 보여줍니다.
  4. SRC_ATOP:
    • 두 번째 그림을 첫 번째 그림 위에 놓고, 두 그림이 겹치는 부분만 보여줍니다.
  5. DST_OVER:
    • 두 번째 그림 위에 첫 번째 그림을 덮습니다.
  6. DST_IN:
    • 두 번째 그림과 첫 번째 그림의 겹치는 부분만 보여줍니다.
  7. DST_OUT:
    • 두 번째 그림에서 첫 번째 그림의 겹치지 않는 부분만 보여줍니다.
  8. DST_ATOP:
    • 첫 번째 그림을 두 번째 그림 위에 놓고, 두 그림이 겹치는 부분만 보여줍니다.
  9. CLEAR:
    • 겹치는 부분을 완전히 투명하게 만듭니다.
  10. XOR:
    • 겹치는 부분을 제외한 나머지 부분만 보여줍니다.
  11. DARKEN:
    • 두 그림 중 어두운 부분을 표시합니다.
  12. LIGHTEN:
    • 두 그림 중 밝은 부분을 표시합니다.

등등 다양한 모드가 있으며, 이들을 조합하면 다양한 그래픽 효과를 얻을 있습니다. PorterDuff.Mode 주로 그림이나 이미지를 합성하는 작업에서 사용되며, 그래픽 처리와 관련된 다양한 시나리오에서 유용하게 활용됩니다.

 

안드로이드 공식 문서에서 해당 내용을 확인하시고 다양한 예를 한번 보시면 좋습니다.

https://developer.android.com/reference/android/graphics/PorterDuff.Mode

 

PorterDuff.Mode  |  Android Developers

 

developer.android.com

이제 코드를 작성해보겠습니다.

먼저

레이아웃 xml 파일입니다.

activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:srcCompat="@tools:sample/avatars" />

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        tools:srcCompat="@tools:sample/avatars" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:srcCompat="@tools:sample/avatars" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

다음은 자바 코드입니다.

MainActivity
package com.example.stickcodeex;

import static android.graphics.Bitmap.*;

import androidx.appcompat.app.AppCompatActivity;


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;


public class MainActivity extends AppCompatActivity {
    // 필요한 뷰 및 비트맵 변수 선언
    ImageView imageView, imageView2, imageView3;
    Bitmap bitmap1, bitmap2;
    Button button;
    // 액티비티 생성 시 호출되는 메서드
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 레이아웃 설정
        setContentView(R.layout.activity_main);
        // 뷰와 버튼 초기화
        imageView = findViewById(R.id.imageView);
        imageView2 = findViewById(R.id.imageView2);
        imageView3 = findViewById(R.id.imageView3);
        button = findViewById(R.id.button);

        // 첫 번째 이미지뷰에 비트맵 설정
        bitmap1 = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.img_1);
        imageView.setImageBitmap(bitmap1);

        // 두 번째 이미지뷰에 비트맵 설정
        bitmap2 = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.img);
        imageView2.setImageBitmap(bitmap2);

        // 버튼에 클릭 리스너 등록
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ImageCombine();
            }
        });
    }
    private void ImageCombine() {
// 첫 번째 이미지뷰에서 비트맵 가져오기
        BitmapDrawable drawable1 = (BitmapDrawable) imageView.getDrawable();
        Bitmap dst = drawable1.getBitmap();

        // 두 번째 이미지뷰에서 비트맵 가져오기
        BitmapDrawable drawable2 = (BitmapDrawable) imageView2.getDrawable();
        Bitmap src = drawable2.getBitmap();

        // 새로운 비트맵 생성
        Bitmap bitmap = Bitmap.createBitmap(dst.getWidth(), dst.getWidth(), Config.ARGB_8888);

        // 비트맵을 그릴 캔버스 생성
        Canvas canvas = new Canvas(bitmap);

        // 페인트 객체 생성
        Paint paint = new Paint();

        // 첫 번째 이미지 그리기
        canvas.drawBitmap(dst, 0, 0, paint);

        // 포터더프 모드를 이용하여 두 번째 이미지를 그리기
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        canvas.drawBitmap(src, 0, 0, paint);

        // 세 번째 이미지뷰에 새로운 비트맵 설정
        imageView3.setImageBitmap(bitmap);
    }
}

실행 결과 입니다.