본문 바로가기

안드로이드

[안드로이드] 간단한 포토샵 앱 만들기

728x90

# 간단한 포토샵 기능

안드로이드 스튜디오에서 구현할 수 있는 이미지 편집 기능 중 7가지를 알아보겠습니다.

# 준비물

  • 버튼으로 사용할 이미지 7종
    1. 사이즈+, 사이즈-, 밝기+, 밝기-, 그레이스케일, 블러, 엠보싱을 의미하는 32*32 사이즈의 이미지 7장
    2. 편집 대상이 될 이미지 1장. 사이즈 300*300 정도 적당한 것.

  • AndroidManifest.xml
  • activity_main.xml
  • MainActivity.java

 

# Android manifest.xml

android:hardwareAccelerated="false"

1. 블러링과 엠보싱 기능을 위해 하드웨어 가속을 꺼줍니다.

AndroidManifest.xml 의 <application "여기에" > </application>에 넣어줍니다.

 

# activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"	// 이미지버튼 부분과 이미지 부분을 세로로 배치
    >

    <LinearLayout
        android:id="@+id/iconLayout"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"	// 이미지버튼 레이아웃 1:9 이미지 레이아웃
        android:gravity="center">
        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibZoomin"
            android:src="@drawable/icon_sp"/>	// 줌인 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibZoomout"
            android:src="@drawable/icon_sm"/>	// 줌 아웃 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibBright"
            android:src="@drawable/icon_bp"/>	// 밝게 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibDark"
            android:src="@drawable/icon_bm"/>	// 어둡게 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibGray"
            android:src="@drawable/icon_g"/>	// 회색처리 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibBlur"
            android:src="@drawable/icon_br"/>	// 블러링 버튼

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ibEmboss"
            android:src="@drawable/icon_eb"/>	// 엠보싱 버튼
    </LinearLayout>

    <LinearLayout		// 편집될 이미지가 출력될 부분
        android:id="@+id/pictureLayout"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="9"	// // 이미지버튼 레이아웃 1:9 이미지 레이아웃
        android:gravity="center">

    </LinearLayout>

</LinearLayout>

메인 화면을 구성하는 소스 코드입니다.

 

# MainActivity.java

package com.sikuroku.p9_2_photoshop;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.EmbossMaskFilter;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {
    
    // 7가지 이미지 버튼 변수
    ImageButton ibZoomin, ibZoomout, ibBright, ibDark, ibGray, ibBlur, ibEmboss;
    
    MyGraphicView grapicView;		// 사용자 정의한 클래스의 객체
    static float scaleX=1, scaleY=1;	// 사이즈 변경 관련 변수
    static float color = 1;		// 밝기 관련 변수
    static float satur = 1;		// 회색처리 관련 변수
    static boolean isBlur = false;	// 블러 변수
    static boolean isEmboss = false;	// 엠보싱 변수

    
    // ### 앱이 생성되면 실행되는 부분 ###
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("미니 포토샵");

        LinearLayout pictureLayout = findViewById(R.id.pictureLayout);
        grapicView = new MyGraphicView(this);
        pictureLayout.addView(grapicView);

        clickIcon();
    }


	// ### 버튼 리스너들을 모아놓은 함수 ###
    private void clickIcon(){
        
        // 이미지 버튼 변수에 activiti_main.xml 에서 생성한 이미지버튼의 id를 설정
        ibZoomin = findViewById(R.id.ibZoomin);
        
        // 버튼을 누르게 되면
        ibZoomin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
                // 버튼에 따라 이미지 조작에 필요한 변수를 조정한 후
                scaleX = scaleX + 0.2f;
                scaleY = scaleY + 0.2f;
                
                // 현재 출력된 이미지를 무효화하여
                // OnDraw 함수로 하여금 재출력하게 한다.
                grapicView.invalidate();
            }
        });

        ibZoomout = findViewById(R.id.ibZoomout);
        ibZoomout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                scaleX = scaleX - 0.2f;
                scaleY = scaleY - 0.2f;
                grapicView.invalidate();
            }
        });

        ibBright = findViewById(R.id.ibBright);
        ibBright.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                color = color + 0.2f;
                grapicView.invalidate();
            }
        });

        ibDark = findViewById(R.id.ibDark);
        ibDark.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                color = color - 0.2f;
                grapicView.invalidate();
            }
        });

        ibGray = findViewById(R.id.ibGray);
        ibGray.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(satur==0) satur = 1;
                else satur=0;
                grapicView.invalidate();
            }
        });

        ibBlur = findViewById(R.id.ibBlur);
        ibBlur.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(isBlur) isBlur = false;
                else isBlur = true;
                grapicView.invalidate();
            }
        });

        ibEmboss = findViewById(R.id.ibEmboss);
        ibEmboss.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(isEmboss) isEmboss = false;
                else isEmboss = true;
                grapicView.invalidate();
            }
        });

    }


	// ### 사용자 정의한 클래스 ###
    // View 클래스를 상속하였고 레이아웃에 출력할 수 있다.
    private static class MyGraphicView extends View{
        public MyGraphicView(Context context){
            super(context);
        }
        
        // 이미지 버튼을 누르면 그 안에 Invalidate()함수가 호출되고
        // Invalidate()함수는 현재 보이는 이미지를 무효처리하고
        // onDraw() 함수를 재실행하게 합니다.
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
			
            // 사이즈 변경
            int cenX = this.getWidth()/2;
            int cenY = this.getHeight()/2;
            canvas.scale(scaleX, scaleY, cenX, cenY);
			
            // canvas에 그려질 paint를 생성
            Paint paint = new Paint();
			
            // 밝기 변경
            float[] array = {color, 0,0,0,0,
                             0,color,0,0,0,
                             0,0,color,0,0,
                             0,0,0,1,0};
            ColorMatrix cm = new ColorMatrix(array);
            
            // 회색 처리
            if(satur==0) cm.setSaturation(satur);
            
            // 밝기변경과 회색처리가 같은 변수 cm을 통하기 때문에
            // 회색 처리가 커져있으면 밝기가 적용되지 않습니다.
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            
            // 블러 처리
            if(isBlur){
                BlurMaskFilter bMask;
                bMask = new BlurMaskFilter(30, BlurMaskFilter.Blur.NORMAL);
                paint.setMaskFilter(bMask);
            }

            // 엠보싱 처리
            // 엠보싱 코드가 블러 코드보다 아래쪽에 있고
            // 같은 paint.setMaskFilter 명령어를 통하기 때문에
            // 엠보싱이 켜져있으면 블러 명령어가 무시됩니다.
            if(isEmboss){
                EmbossMaskFilter eMask;
                eMask = new EmbossMaskFilter(new float[] {3,3,3}, 0.5f, 5, 30);
                paint.setMaskFilter(eMask);
            }
			
            // 편집될 대상이 될 이미지를 불러옵니다.
            Bitmap picture = BitmapFactory.decodeResource(getResources(), R.drawable.lovelow);
            
            // 이미지를 중앙에 출력하기 위한 좌표 계산
            int picX = (this.getWidth() - picture.getWidth())/2;
            int picY = (this.getHeight() - picture.getHeight())/2;

            // 크기가 변경된 캔버스에
            // 편집될 대상이 될 이미지를
            // 캔버스 중앙에
            // 요청대로 설정된 paint를 이용해서 출력합니다.
            canvas.drawBitmap(picture, picX,picY,paint);
            
            // 캔버스로 이미지를 내보낸 비트맵의 저장공간을 비워줍니다.
            picture.recycle();
        }
    }
}

 

728x90