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

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

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



답변

. .
중요 : 더 나은 솔루션을 보려면 아래 @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입니다.


답변

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

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);

여기 에 답을 보십시오


답변

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

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 ()을 호출하므로 기능을 잃지 않습니다.

참고 문헌 :


답변

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

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

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


답변

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

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


답변

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();
    }
}


답변

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)
}