관리 메뉴

정상에서 IT를 외치다

[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (크롭 기능 추가) 본문

안드로이드

[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (크롭 기능 추가)

Black-Jin 2018. 10. 23. 13:47
728x90
반응형

안녕하세요. 블랙진입니다.!!


카메라와 갤러리에서 이미지 가져오기를 단계별로 포스팅을 진행하고 있습니다.


1. 카메라와 갤러리에서 이미지 가져오기

2. Nougat(Android OS 7) 대응하기

3. 카메라회전 각도를 고려한 이미지 가져오기

4. 가져온 이미지 크롭(Crop) 하기


이전 포스팅에 이어 크롭 기능을 추가해 보겠습니다. 


Chapter 4. 가져온 이미지 크롭하기



안드로이드 기기 내부에는 크롭 기능을 탑재하고 있습니다.


Intent intent = new Intent("com.android.camera.action.CROP");


인텐트를 통해 크롭을 사용하실 수 있습니다. 하지만! 일부 안드로이드 기기에서는 위 크롭 인텐트가 적용이 안되는 것을 확인할 수 있었습니다. ㅠㅜ

보다 많은 개발자분들에게 도움이 되기 위해, 저는 모든 기기에 적용 수 있는 크롭 라이브러리를 사용하여 포스팅을 진행하겠습니다.


혹시 탑재되어 있는 크롭을 사용하고 싶으신 분은 이 링크를 참고해서 작업해 주세요



1. App 단계의 build.gradle 에 Crop 라이브러리를 추가해 줍니다.


app/ build.gradle

//crop
implementation 'com.soundcloud.android:android-crop:1.0.1@aar'



2. AndroidManifest 에 CropImageActivity 를 추가해 줍니다.


AndroidManifest.xml

<!-- crop activity -->
<activity
android:name="com.soundcloud.android.crop.CropImageActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.NoActionBar" />

<application> .. </application> 사이에 추가해 줍니다.



3. onActivityResult 에서 크롭 로직을 추가해 줍니다.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
Toast.makeText(this, "취소 되었습니다.", Toast.LENGTH_SHORT).show();

if(tempFile != null) {
if (tempFile.exists()) {

if (tempFile.delete()) {
Log.e(TAG, tempFile.getAbsolutePath() + " 삭제 성공");
tempFile = null;
}
}
}

return;
}

switch (requestCode) {
case PICK_FROM_ALBUM: {

Uri photoUri = data.getData();
              
cropImage(photoUri);

break;
}
case PICK_FROM_CAMERA: {

Uri photoUri = Uri.fromFile(tempFile);

cropImage(photoUri);

break;
}
case Crop.REQUEST_CROP: {

setImage();
}
}
}

requestCode 에서 Crop.REQUEST_CROP 단계를 추가해 줍니다. 



4. 카메라 및 갤러리에서 가져온 이미지를 Crop 화면으로 보내줍니다.

private void cropImage(Uri photoUri) {

Log.d(TAG, "tempFile : " + tempFile);

/**
* 갤러리에서 선택한 경우에는 tempFile 이 없으므로 새로 생성해줍니다.
*/
if(tempFile == null) {
try {
tempFile = createImageFile();
} catch (IOException e) {
Toast.makeText(this, "이미지 처리 오류! 다시 시도해주세요.", Toast.LENGTH_SHORT).show();
finish();
e.printStackTrace();
}
}

//크롭 후 저장할 Uri
Uri savingUri = Uri.fromFile(tempFile);

Crop.of(photoUri, savingUri).asSquare().start(this);
}

사진촬영의 경우에는 tempFile 이 생성되어 있어 크롭된 이미지를 tempFile 에 넣어 저장할 수 있습니다. 하지만 갤러리에서 가져온 이미지는 크롭 후의 이미지를 저장할 파일이 없기 때문에 tempFile = createImageFIle() 을 추가로 작성해 주어야 합니다.



5. Crop 된 이미지 받기

case Crop.REQUEST_CROP: {

setImage();
}

크롭 후에는 onActivityResult 에서 Crop.REQUEST_CROP를 수행하게 됩니다. 우리는 위 4번에서 tempFile 에 크롭한 이미지를 이미 저장 했기 때문에 별다른 로직 없이 tempFile 를 크롭한 이미지라 생각하고 사용하시면 됩니다.


case Crop.REQUEST_CROP: {
File cropFile = new File(Crop.getOutput(data).getPath());
}

참고로 Crop.REQUEST_CROP 에서  크롭한 파일을 가져오는 방법은 위와 같습니다.


자! 이렇게 카메라와 갤러이에서 이미지 가져오기 포스팅을 모두 끝냈습니다. 따라오시면서 어려운 점이나 이해 안가는부분은 댓글로 질문 부탁드리겠습니다. 혹은 코드에서 잘못된 점이 있거나 더 좋은 방식이 있다면 얼마든지 댓글 달아 주시면 감사하겠습니다. 


제 나름대로 안드로이드 OS 와  기기 별 모두 호환될 수 있게 작성을 해봤습니다. 많은 개발자 분들에게 도움이 되었으면 좋겠습니다. :)


Capter4. 깃허브



관련 포스팅


1.  카메라와 갤러리에서 이미지 가져오기

2. Nougat(Android OS 7) 대응하기

3. 카메라회전 각도를 고려한 이미지 가져오기

4. 가져온 이미지 크롭(Crop) 하기

반응형
10 Comments
  • 프로필사진 안녕하세요 2019.04.15 18:52 안녕하세요. 사진첩이 좀 이상해서.. 질문좀 드리겠습니다.. 크롭 후에 사진앨범을 보면 ! 뜨면서 사진이 삭제되거나 크롭 된 채로 사진첩에 저장되는데요. 원본 파일은 원본파일대로 저장하는 방법이 없을까요?
  • 프로필사진 Black-Jin 2019.04.16 18:30 신고 안녕하세요. 현재 "카메라와 갤러리에서 이미지 가져오기" 4단계로 나눠서 포스팅을 진행하고 있습니다. 크롭기능이 없는 이전 단계 포스팅만 따라해 보세요 :)

    사진 앨범에 ! 로 뜨는 이미지는 createFile()로 생성한 파일에 가져온 이미지를 저장하지 않은 빈 파일입니다. 이러한 경우 파일 존재 여부를 확인 후 onActivityResult 에서 파일을 지워져야 되는데 1단계 포스팅에 '예외 사항 처리하기' 부분을 확인하시면 될 것 같습니다.
  • 프로필사진 감사합니다 2019.05.12 17:37 감사합니다 덕분에 많은 도움이 되었습니다.
    그런데 갤러리에서 이미지를 불러오고난 다음에 보면 ImageView에 사진이 90도 회전이 된 상태로 나타나는데
    원래 찍어놓은 사진 그대로 가져오는 방법은 없을까요 ?
  • 프로필사진 Black-Jin 2019.05.13 22:40 신고 안녕하세요. 글이 도움이 되었다니 다행입니다. 저는 카메라로 찍었을 경우에만 회전 각도가 적용되는줄 알았는데 일부 기기에서는 갤러리에서도 회전각도가 적용되나 봅니다 ㅠㅜ
    스태오버플로우의 이와 관련된 질문을 보니
    https://stackoverflow.com/questions/31925712/android-getting-an-image-from-gallery-comes-rotated
    ExifInterface 를 사용해서 문제를 해결하면 되는것 같습니다. 포스팅 3번 글인 카메라 회전 각도를 고려한 이미지 가져오기 코드를 갤러리에도 적용하면 문제가 해결되지 않을까 싶습니다 :)
  • 프로필사진 감사합니다 2019.05.15 00:35 ㅠ.ㅠ 제 머리로는 응용이 안되네요 ..
    좋은정보 감사합니다 !!
  • 프로필사진 YS 2019.07.01 15:50 안녕하세요 글 감사히 잘 보고 있습니다.
    마지막에 크롭 예제를 했는데 크롭을 하면 크롭된 이미지가 저장되거나 화면에 안떠서요 어떻게 해야할지 조언부탁드립니다.
  • 프로필사진 Black-Jin 2019.07.02 14:57 신고 안녕하세요. 예제에서 사용하고 있는 크롭 라이브러리의 설명을 보면
    Crop.of(inputUri, outputUri).asSquare().start(activity)
    이렇게 동작합니다.

    위 설명 4번에 있는 제 코드를 보면
    //크롭 후 저장할 Uri
    Uri savingUri = Uri.fromFile(tempFile);

    Crop.of(photoUri, savingUri).asSquare().start(this);

    이렇게 되어 있습니다. 크롭 된 결과를 전역 변수 tempFile 의 uri에 저장하기 때문에 이 tempFile에 이미지가 있어야 됩니다. 이전 예제까지 잘 따라 오셨다면 제가 사용한 Crop 라이브러리 사용법에 대해 테스트 해보고 비교 분석해 보시면서 안되는 부분을 수정하시면 좋을것 같습니다.
  • 프로필사진 감사합니다 2019.09.03 11:27 안녕하세요.덕분에 잘 공부하고 있습니다.
    4단계까지 무리없이 잘 진행했는데요.
    처음엔 앨범에 저장이 되는가 싶더니 내부저장소로 빠지더라구요ㅜ 그러다가 핸드폰 전원을 껐다가 켜니 앨범으로 잘 들어가집니다! 바로 적용이 안되고 전원을 껐다 켜야 그동안에 저장된 사진들이 앨범에 생겨요 ㅜㅜ 어떻게 해결해야할까요?
  • 프로필사진 Black-Jin 2019.09.03 16:59 신고 안녕하세요! 먼저 글이 도움이 되었다니 다행입니다:)

    Broadcast를 통해 갤러리를 새로 고침 해주시면 앨범에 저장된 사진들이 보입니다.

    갤러리 새로 고침
    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
    Uri.parse("file://" + Environment.getExternalStorageDirectory())));

    혹은 해당 파일만 새로고침 해주시면 됩니다.
    sendBroadcast(new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

    관련 링크
    https://codeday.me/ko/qa/20190509/501020.html
  • 프로필사진 hw00173@naver.com 2019.11.07 16:23 안녕하세요. 해당 게시물을 보고 잘 응용하고 있는 학생입니다. 한가지 문의 사항이 있어서 연락드립니다.

    Crop.of(photoUri, savingUri).asSquare().start(this);해당 부분ㄷ에서

    Crop.of(photoUri, savingUri).withMaxSize().start(this);를 사용하게 될 경우 이미지가 가로로 늘어지고 세로가 좁아지는 현상이 생기는데 혹시 어떠한 이유인지 알 수 있을까요?

댓글쓰기 폼