[안드로이드] 이미지뷰에 사진 적용후 확대 축소후 선 그리기
조회수 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 답변
-
올려주신 코드에는 선을 그릴 때 확대/축소에 대한 고려가 되어있지 않습니다. 따라서 이미지만 확대가 되고, 캔버스는 최초의 이미지 크기를 유지한 상태이기 때문에 선이 엉뚱한 곳에 그려지는 현상이 나타나는 것이고요. 이미지가 확대 됐을 때, 캔버스도 좌표 및 스케일에 대한 처리가 되어야 기대하는 위치에 선이 그려집니다.
코드 레벨로 이를 처리하는 방법은 아래의 깃헙 소스 코드를 참고하는 것이 좋을 것 같습니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
-
댓글 입력