Uri에서 비트 맵을 얻는 방법?


209

응용 프로그램에서 사용하기 위해 Uri에서 비트 맵 객체를 가져 오는 방법 ( /data/data/MYFOLDER/myimage.png또는 에 저장 한 경우 file///data/data/MYFOLDER/myimage.png)은 어떻게됩니까?

누구든지 이것을 달성하는 방법에 대한 아이디어가 있습니까?


30
내 것보다 더 나은 답변이 있기 때문에이 게시물에서 수락 된 답변을 업데이트해야합니다.
Vidar Vestnes

1
번째 답변 이 옳고 세 번째 답변 이 더 완벽합니다.
IgniteCoders

@VidarVestnes 왜 삭제하지 않습니까?
Carlos López Marí

답변:


-35

. . 중요 : 더 나은 솔루션을 보려면 아래 @Mark Ingram 및 @pjv의 답변을 참조하십시오. . .

당신은 이것을 시도 할 수 있습니다 :

public Bitmap loadBitmap(String url)
{
    Bitmap bm = null;
    InputStream is = null;
    BufferedInputStream bis = null;
    try 
    {
        URLConnection conn = new URL(url).openConnection();
        conn.connect();
        is = conn.getInputStream();
        bis = new BufferedInputStream(is, 8192);
        bm = BitmapFactory.decodeStream(bis);
    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }
    finally {
        if (bis != null) 
        {
            try 
            {
                bis.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
        if (is != null) 
        {
            try 
            {
                is.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }
    return bm;
}

그러나이 메소드는 스레드 내에서만 호출해야합니다 (GUI 스레드는 아님). 나는 AsyncTask입니다.


2
예를 들어 yourUri.toURL ()을 사용하여 URI를 URL로 변환하는 것은 어떻습니까?
Vidar Vestnes

7
@VidarVestnes 친구, 어떻게 파일 경로가 URL로 변환 될 수 있습니까?
dharam 2016 년

7
이 답변이 어떻게 선택되는지 이해가되지 않습니다
Nick Cardoso

11
이 답변을 최고로 받아 들여서는 안된다는 데 동의합니다. 첫 번째 답변 이었기 때문에 선택되었을 수도 있습니다. 오래된 게시물입니다. 어쨌든 더 나은 솔루션을 위해 아래 답변을 참조하십시오.
Vidar Vestnes

8
@VidarVestnes는 답을 삭제합니다
winklerrr

564

올바른 방법은 다음과 같습니다.

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK)
    {
        Uri imageUri = data.getData();
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
    }
}

매우 큰 이미지를로드해야하는 경우 다음 코드는 이미지를 타일에로드합니다 (큰 메모리 할당 방지).

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);  
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);

여기 에 답을 보십시오


3
이 코드는 더 큰 이미지 (기본적으로 벽지 크기)를 처리하지 않습니다. getBitmap ()은 stackoverflow.com/questions/2220949/handling-large-bitmaps 에서 OOM 오류로 실패하는 decodeStream ()을 호출합니다 . 다른 조언이 있습니까? MediaStore.Images.Thumbnails.getThumbnail ()은 분명히 contentURI를 사용하지 않습니다.
pjv 2016 년

1
여기에 답변을 참조하십시오 : stackoverflow.com/questions/4753013/...
마크 잉그램

@MarkIngram 로컬 이미지 또는 카메라 이미지에서만 작동합니까?
Narendra Singh

@MarkIngram data.getData ()에 액세스 할 수 없다면 갤러리에서 이미지를 단순히 열면 경로에 관한 것입니다. 우리는 어떻게 URI와 비트 맵을 얻을 수 있습니까?
Umair

@Umair 당신은 답변의 의견을 묻는 대신 새로운 질문을해야합니다. 그건 그렇고 : 여기를보십시오 developer.android.com/reference/android/net/Uri.html
winklerrr

111

메모리 사용에 대한 탭을 유지하면서 올바른 작업 방법이 있습니다.

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
  super.onActivityResult(requestCode, resultCode, data);
  if (resultCode == RESULT_OK)
  {
    Uri imageUri = data.getData();
    Bitmap bitmap = getThumbnail(imageUri);
  }
}

public static Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException{
  InputStream input = this.getContentResolver().openInputStream(uri);

  BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
  onlyBoundsOptions.inJustDecodeBounds = true;
  onlyBoundsOptions.inDither=true;//optional
  onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
  BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
  input.close();

  if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
    return null;
  }

  int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;

  double ratio = (originalSize > THUMBNAIL_SIZE) ? (originalSize / THUMBNAIL_SIZE) : 1.0;

  BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
  bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
  bitmapOptions.inDither = true; //optional
  bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//
  input = this.getContentResolver().openInputStream(uri);
  Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
  input.close();
  return bitmap;
}

private static int getPowerOfTwoForSampleRatio(double ratio){
  int k = Integer.highestOneBit((int)Math.floor(ratio));
  if(k==0) return 1;
  else return k;
}

Mark Ingram의 게시물에서 getBitmap () 호출은 또한 decodeStream ()을 호출하므로 기능을 잃지 않습니다.

참고 문헌 :


1
this 키워드를 정적 컨텍스트에서 사용할 수 없다는 점을 언급 할 가치가 있다고 생각하지만 실제로 도움이되었습니다. 인수로 getThumbnail 메소드에 전달했으며 매력처럼 작동합니다.
MacKinley Smith

8
누구든지 THUMBNAILSIZE에 어떤 가치를 주어야하는지 말해 줄 수 있습니까
Abid

2
첫 번째 BitmapFactory.decodeStream (...) 호출은 스트림의 읽기 위치를 끝으로 설정하므로 스트림을 다시 열지 않으면 메소드의 두 번째 호출이 더 이상 작동하지 않으므로 InputStream을 닫고 다시 여는 것이 실제로 필요합니다!
DominicM

3
THUMBNAILSIZE의 가치
Mightian

3
디코더 자체는 샘플 크기로 가장 가까운 2의 거듭 제곱으로 반올림하므로 비율을 2의 거듭 제곱으로 계산할 필요는 없습니다. 따라서 메소드 호출 getPowerOfTwoForSampleRatio()을 건너 뛸 수 있습니다. 참조 : developer.android.com/reference/android/graphics/…
winklerrr

42
try
{
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e) 
{
    //handle exception
}

그리고 예 경로는 다음과 같은 형식이어야합니다

file:///mnt/sdcard/filename.jpg


1
덕분에 Itay이 유 경로가있는 경우 u는 단지 U에 희망이 .. 시도 .. 나를 위해 노력하고, 해당 경로를 전달하고 비트 맵을 얻을 수 있고, 간단하다
DJP

2
@Dhananjay 감사합니다. 힌트로 하루를 절약 할 수 있으며 콘텐츠 제공 업체에서 썸네일 비트 맵을로드 할 수 있습니다.
Nezneika

2
또한 Uri.parse ()Uri.parse ( "file : ///mnt/sdcard/filename.jpg") 와 같이 URI 형식을 포함해야합니다 . 그렇지 않으면 java.io.FileNotFoundException : No content가 표시됩니다. 공급자 .
Nezneika

일부 편집은 훌륭하지만 대부분의 경우 작동하는 OP 질문에 대한 간결한 답변입니다. 이것은 OP 질문에 직접 답변하는 다른 답변을 증류 제거하기 위해 페이지에 가지고있는 좋은 답변입니다.
umassthrower

1
@AndroidNewBee c는 컨텍스트 객체입니다.
DjP

17

이것이 가장 쉬운 해결책입니다.

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

16
private void uriToBitmap(Uri selectedFileUri) {
    try {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(selectedFileUri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);

        parcelFileDescriptor.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3
모든 SDK에서 작동합니다. 감사합니다. 그것은 대안의 방법입니다Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel

가장 정품 대답 모든 SDK는 만족
Noaman 아크람에게

13

MediaStore.Images.Media.getBitmap에서 더 이상 사용되지 않는 것 같습니다 API 29. 권장되는 방법은 ImageDecoder.createSource에 추가 된를 사용 하는 것입니다 API 28.

비트 맵을 얻는 방법은 다음과 같습니다.

val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    ImageDecoder.decodeBitmap(ImageDecoder.createSource(requireContext().contentResolver, imageUri))
} else {
    MediaStore.Images.Media.getBitmap(requireContext().contentResolver, imageUri)
}

11

이처럼 URI에서 비트 맵을 검색 할 수 있습니다

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}

10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);

2
이 코드의 작동 방식과 질문에 대한 답변에 대해 자세히 설명해 주시겠습니까?
마이클 도드

2

아래와 같이 startActivityForResult metod 사용

        startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);

그리고 당신은 다음과 같은 결과를 얻을 수 있습니다 :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_OK) {
        return;
    }
    switch (requestCode) {
        case PICK_IMAGE:
            Uri imageUri = data.getData();
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
            } catch (IOException e) {
                e.printStackTrace();
            }
         break;
    }
}

2

나는 많은 방법을 시도했다. 이것은 나를 위해 완벽하게 작동합니다.

갤러리에서 pictrue를 선택하면 당신은 점점의 도자기 할 필요 Uri에서 intent.clipdata또는 intent.data그 중 하나는 다른 버전에서 null이 될 수 있기 때문에.

  private fun onChoosePicture(data: Intent?):Bitmap {
        data?.let {
            var fileUri:Uri? = null

              data.clipData?.let {clip->
                  if(clip.itemCount>0){
                      fileUri = clip.getItemAt(0).uri
                  }
              }
            it.data?.let {uri->
                fileUri = uri
            }


               return MediaStore.Images.Media.getBitmap(this.contentResolver, fileUri )
}

1

이 구조를 수행 할 수 있습니다 :

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    switch(requestCode) {
        case 0:
            if(resultCode == RESULT_OK){
                    Uri selectedImage = imageReturnedIntent.getData();
                    Bundle extras = imageReturnedIntent.getExtras();
                    bitmap = extras.getParcelable("data");
            }
            break;
   }

이를 통해 URI를 비트 맵으로 쉽게 변환 할 수 있습니다. 희망 u.


1
이것은 안드로이드 누가 7.1.1 버전에서 작동하지 않습니다. 이 extras.getParcelable ( "data"); is null 반환
Developer_vaibhav

1

삽입 된은으로 getBitmap된 지금은 코 틀린에 다음과 같은 방법을 사용 depricated한다

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }

1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);

1

(KOTLIN) 따라서 2020 년 4 월 7 일부터 위에서 언급 한 옵션 중 어느 것도 효과가 없었지만 다음은 저에게 효과적이었습니다.

  1. 비트 맵을 val에 저장하고 imageView를 설정하려면 다음을 사용하십시오.

    val bitmap = BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }

  2. 비트 맵을 and imageView로 설정하려면 다음을 사용하십시오.

    BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }


0

모바일 갤러리에서 이미지 URI를 얻는 전체 방법.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

  if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
                Uri filePath = data.getData();

     try { //Getting the Bitmap from Gallery
           Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
           rbitmap = getResizedBitmap(bitmap, 250);//Setting the Bitmap to ImageView
           serImage = getStringImage(rbitmap);
           imageViewUserImage.setImageBitmap(rbitmap);
      } catch (IOException e) {
           e.printStackTrace();
      }


   }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.