[안드로이드] 이미지뷰에 사진 적용후 확대 축소후 선 그리기

조회수 3137회

갤러리에서 이미지를 가져와 ImageVeiw에 뿌려주고 손가락 드레그하면 선 그어주는 어플을 만들고 있는데요, 이미지를 가져와서 선을 긋는거는 잘되는데 확대나 축소후에 그으면 엉뚱한곳에 선이 그어지네요, 혹시 왜그런지 도움좀 받을 수 있을까요?

아래는 해당 어플 전체 소스코드(java만) 입니다.

package com.example.imageviewtest;



import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore.Images;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import uk.co.senab.photoview.PhotoViewAttacher;

public class MainActivity extends Activity {

private static String tag = "[MainActivity]";

final int REQ_CODE_SELECT_IMAGE=100;

Bitmap copyBitmap;
ImageView imageView;
PhotoViewAttacher mAttacher;

Button findBtn1;    //갤러리 여는 버튼
Button saveBtn1;    //이미지 저장 버튼

Canvas canvas;  //캔버스
Paint paint;    //페인트
Path path;      //페스

float downx = 0, downy = 0, upx = 0, upy = 0;

String mode = "none";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void initJob()
{
    paint = new Paint();
    paint.setColor(Color.RED); 
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(15F);

    path = new Path();

    imageView = (ImageView)findViewById(R.id.imageView1);

    findBtn1 = (Button) findViewById(R.id.findBtn1);
    saveBtn1 = (Button) findViewById(R.id.saveBtn1);

    //갤러리 열기
    findBtn1.setOnClickListener(new Button.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(Intent.ACTION_PICK);                
            intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
            intent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, REQ_CODE_SELECT_IMAGE); 
        }
    });

    //이미지 저장하기
    saveBtn1.setOnClickListener(new Button.OnClickListener() {
          @Override
            public void onClick(View view) {
            String extStorageDirectory  = Environment.getExternalStorageDirectory().getAbsolutePath().toString();

            Toast.makeText(getApplicationContext(), extStorageDirectory, Toast.LENGTH_SHORT).show();

            File mDir = new File(extStorageDirectory+"/DCIM/hyhTest");
            if(!mDir.exists())
            {
                mDir.mkdir();
            }

            SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd_hhMMss",Locale.KOREA);
            Date current = new Date();
            String date = formater.format(current);

            String saveFile = mDir.toString()+"/test_"+date+".png";

            FileOutputStream out = null;
            try {
                out = new FileOutputStream(saveFile);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 

            copyBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);

            Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            File f = new File(saveFile);
            Uri contentUri = Uri.fromFile(f);
            mediaScanIntent.setData(contentUri);
            sendBroadcast(mediaScanIntent);

            try {
                out.flush();
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Toast.makeText(getApplicationContext(), "저장완료", Toast.LENGTH_SHORT).show();
          } 
    });
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    //초기 작업
    initJob();
}


@SuppressWarnings("deprecation")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    //앨범 선택 리턴
    if(requestCode == REQ_CODE_SELECT_IMAGE) 
    { 
        if(resultCode==Activity.RESULT_OK) 
        {     
            try { 

                Bitmap bitmap1 = Images.Media.getBitmap(getContentResolver(), data.getData());
                Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap1, imageView.getWidth(), imageView.getHeight(), false);

                copyBitmap = bitmap2.copy(Bitmap.Config.ARGB_8888,true);

                canvas = new Canvas(copyBitmap);

                imageView.setImageBitmap(copyBitmap);

                //줌 인 아웃
                mAttacher = new PhotoViewAttacher(imageView);

                //이미지뷰 터치 이벤트
                imageView.setOnTouchListener(new View.OnTouchListener() {

                    public boolean onTouch (View v, MotionEvent event) {

                        float x = event.getX(); 
                        float y = event.getY();

                        int pointerCount = event.getPointerCount();

                        //두손가락 으로 터치시 줌 인 아웃 적용
                        if(pointerCount >= 2)
                        {
                            mAttacher.onTouch(v, event);
                        }  

                        int action = event.getAction();

                        switch (action) {
                            case MotionEvent.ACTION_DOWN:
                                path.reset();
                                path.moveTo(x, y);
                            break;

                            case MotionEvent.ACTION_POINTER_1_DOWN:
                                mode = "zoom";
                            break;

                            case MotionEvent.ACTION_POINTER_2_DOWN:
                                mode = "zoom";
                            break; 

                            case MotionEvent.ACTION_MOVE:
                                upx = event.getX(); 
                                upy = event.getY();

                                //줌 인 아웃이 아닐때, 손가락 드레그 선 그리기
                                if((upx>=4 || upy>=4) && mode.equalsIgnoreCase("none"))
                                {  
                                    path.lineTo(x, y);
                                    canvas.drawPath(path, paint);
                                    imageView.invalidate();
                                }
                              break;

                            case MotionEvent.ACTION_UP:
                                pointerCount = -1;
                                mode = "none";
                              break;

                            case MotionEvent.ACTION_CANCEL: 
                                mode = "none";
                              break;

                            default:
                              break;
                        } 
                        return true;
                    }

                });

            } catch (FileNotFoundException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } catch (IOException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace();

            }

            catch (Exception e)
            {
                e.printStackTrace();
            } 
        }      
    }

}

}

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 올려주신 코드에는 선을 그릴 때 확대/축소에 대한 고려가 되어있지 않습니다. 따라서 이미지만 확대가 되고, 캔버스는 최초의 이미지 크기를 유지한 상태이기 때문에 선이 엉뚱한 곳에 그려지는 현상이 나타나는 것이고요. 이미지가 확대 됐을 때, 캔버스도 좌표 및 스케일에 대한 처리가 되어야 기대하는 위치에 선이 그려집니다.

    코드 레벨로 이를 처리하는 방법은 아래의 깃헙 소스 코드를 참고하는 것이 좋을 것 같습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 먼저 정성스러운 답변에 감사드립니다. 지금은 제가 다른일을 하고있어서 나중에 알려주신 대로 실행해 보겠습니다 알 수 없는 사용자 2017.4.17 09:25

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)