Recent Posts
Recent Comments
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
관리 메뉴

Dev.

효과적인 사진 크롭 (크롭사진 화질향상의 기초) 본문

Android

효과적인 사진 크롭 (크롭사진 화질향상의 기초)

Pppdw 2015. 7. 21. 13:59

앱 개발을 진행하다 보면, 사진에 대한 크롭기능이 꼭 필요할 경우가 생긴다. 

보통 번들로 데이터를 받는 식의 구현을 하게되는데 이럴경우 가장 큰 문제는, 

번들에 들어가는 해당 크롭된 데이터가 100kb를 넘어가면 받지 못하는 경우가 생기게된다. 

outputX,outputY가 필연적으로 존재해야하는 구조이기 때문에, 크롭으로인해 사진이 뒤틀리고,

픽셀이 어긋나는 단점이 생기므로, 실제 출시해야 하는앱에서는 맞지않는 구조다.

아래 코드를 보자.(! 해당 ActivityResult를 호출하는 구문을 입맛에 따라서 리스너에 붙여주면된다.)




 

Uri mImageCaptureUri ;
String strPhotoName;
ImageView imgAdd;

@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case RequestCode.CODE_CALLED_PHOTO_SEL:
			if(resultCode == RESULT_OK){
				int selectedType = data.getExtras().getInt("SELECTTYPE");
				if(selectedType == 0){ //앨범을 선택했을때
					Intent in = new Intent(Intent.ACTION_PICK);
					in.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
					startActivityForResult(in, RequestCode.CODE_CALLED_PICK_FROM_ALBUM);
				}else if(selectedType == 1){ //촬영을 선택했을때
					Uri photoUri = null;
					File file = new File("/sdcard/test/");
					if (!file.isDirectory()) {
						file.mkdir();
					}
					
					Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
					mImageCaptureUri = createSaveCropFile();
					intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
					startActivityForResult(intent, RequestCode.CODE_CALLED_PICK_FROM_CAMERA);
				}
			}
			break;
		case RequestCode.CODE_CALLED_PICK_FROM_ALBUM:
			if(resultCode == RESULT_OK){
				
				mImageCaptureUri = data.getData();
				
	            File original_file = getImageFile(mImageCaptureUri);
	             
	            mImageCaptureUri = createSaveCropFile();
	            File cpoy_file = new File(mImageCaptureUri.getPath()); 
	            
	            copyFile(original_file , cpoy_file);
				
				Intent intent = new Intent("com.android.camera.action.CROP");
				intent.setDataAndType(mImageCaptureUri, "image/*");
				intent.putExtra( "output", mImageCaptureUri);
				startActivityForResult( intent, RequestCode.CODE_CALLED_PHOTO_CROP );
			}
			break;
		case RequestCode.CODE_CALLED_PICK_FROM_CAMERA:
			if(resultCode == RESULT_OK){
				
				Intent intent = new Intent("com.android.camera.action.CROP");
				intent.setDataAndType(mImageCaptureUri, "image/*");
				intent.putExtra( "output", mImageCaptureUri);
				startActivityForResult( intent, RequestCode.CODE_CALLED_PHOTO_CROP );
			}
			break;
		case RequestCode.CODE_CALLED_PHOTO_CROP:
			if(resultCode == RESULT_OK){
	            String full_path = mImageCaptureUri.getPath();
				
				bmp = BitmapFactory.decodeFile(full_path);
				imgAdd.setImageBitmap(bmp);

			}
			break;
		default:
			break;
		}
	}

/**
     * @author : pppdw
     * @param : Crop된 이미지가 저장될 파일을 만든다.선언된 url로 파일이 네이밍되며, 선언된 uri에 파일이 저장된다.
     * @return : Uri
     */
    private Uri createSaveCropFile(){
        Uri uri;
        String url = "test" + String.valueOf(System.currentTimeMillis()) + ".jpg";
        strPhotoName = url;
        uri = Uri.fromFile(new File("/sdcard/test/", url));
        return uri;
    }

/**
     * @author pppdw
     * @param 사진 경로를 얻는다,Uri가 널이되는 경우엔, 가장최근(라스트인덱스) 사진을 가지고온다.
     * @return File (해당사진)
     */
    private File getImageFile(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        if (uri == null) {
            uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        }
 
        Cursor mCursor = getContentResolver().query(uri, projection, null, null, 
                MediaStore.Images.Media.DATE_MODIFIED + " desc");
        if(mCursor == null || mCursor.getCount() < 1) {
            return null; // no cursor or no record
        }
        int column_index = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        mCursor.moveToFirst();
 
        String path = mCursor.getString(column_index);
 
        if (mCursor !=null ) {
            mCursor.close();
            mCursor = null;
        }
 
        return new File(path);
    }

/**
     * @author pppdw
     * @description 크롭을 위해 사진을 복사한다.
     * @return
     */
    public static boolean copyFile(File srcFile, File destFile) {
        boolean result = false;
        try {
            InputStream in = new FileInputStream(srcFile);
            try {
                result = copyToFile(in, destFile);
            } finally  {
                in.close();
            }
        } catch (IOException e) {
            result = false;
        }
        return result;
    }

/**
     * @author : pppdw
     * @description : DestFile을 소스스트림에 복사한다 (데이터밸류)
     */
    private static boolean copyToFile(InputStream inputStream, File destFile) {
        try {
            OutputStream out = new FileOutputStream(destFile);
            try {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) >= 0) {
                    out.write(buffer, 0, bytesRead);
                }
            } finally {
                out.close();
            }
            return true;
        } catch (IOException e) {
            return false;
        }
    }

이런식으로 선언을 한뒤 사용하게되면, 포토 크롭시 크롭된 해당이미지가 mkDir로 생성된 폴더에

저장되게된다. 저장된 이미지의 경로는 strPhotoName에 담기게되며, 추후 사진을 업로드 한다던가

그런 작업을 할땐 strPhotoName에 담긴 경로를 기반으로 작업하면 된다.

출처 : StackOverFlow 여러 곳 짜집기

http://www.stackoverflow.com/

Comments