如何从Uri获取位图?

ilr*_*web 187 android uri android-image android-bitmap

如何从Uri中获取Bitmap对象(如果我成功将其存储在 /data/data/MYFOLDER/myimage.png或中file///data/data/MYFOLDER/myimage.png)以在我的应用程序中使用它?

有没有人知道如何实现这一目标?

Mar*_*ram 527

这是正确的做法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您需要加载非常大的图像,以下代码将在tile中加载它(避免大量内存分配):

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);  
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);
Run Code Online (Sandbox Code Playgroud)

这里看到答案

  • MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri); 现在已被贬值 (4认同)
  • 此代码不处理更大的图像(基本上任何壁纸大小).getBitmap()调用decodeStream(),它因http://stackoverflow.com/questions/2220949/handling-large-bitmaps中的OOM错误而失败.还有其他建议吗?MediaStore.Images.Thumbnails.getThumbnail()显然不采用contentURI. (3认同)

pjv*_*pjv 105

这是正确的做法,同时关注内存使用情况:

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;
}
Run Code Online (Sandbox Code Playgroud)

Mark Ingram的帖子中的getBitmap()调用也调用了decodeStream(),因此您不会丢失任何功能.

参考文献:

  • 谁能告诉我应该给THUMBNAILSIZE的价值 (7认同)
  • 关闭并重新打开 InputStream 实际上是必要的,因为第一个 BitmapFactory.decodeStream(...) 调用将流的读取位置设置为末尾,因此如果不重新打开流,该方法的第二次调用将不再起作用! (2认同)
  • 请告诉THUMBNAILSIZE的价值 (2认同)
  • 没有必要自己计算比率作为2的幂,因为解码器本身将样本大小舍入到最接近的2的幂.因此可以跳过方法调用`getPowerOfTwoForSampleRatio()`.请参阅:https://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize (2认同)

Ika*_*Ika 39

似乎MediaStore.Images.Media.getBitmapAPI 29. 推荐的方法是使用ImageDecoder.createSourceAPI 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)
}
Run Code Online (Sandbox Code Playgroud)

重要提示:ImageDecoder.decodeBitmap读取 EXIF 方向,Media.getBitmap

  • 文档明确指出“此方法应该在工作线程中完成,而不是在主线程中!” (2认同)

DjP*_*DjP 38

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

是的路径必须是这样的格式

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

  • @Dhananjay谢谢你,你的提示节省了我的一天,它可以从Content Provider加载缩略图位图. (2认同)
  • 另外,_Uri.parse()_必须包含URI格式,就像:_Uri.parse("file:///mnt/sdcard/filename.jpg")_,如果不是,我们将得到*java.io.FileNotFoundException :没有内容提供商*. (2认同)
  • @AndroidNewBee c 是 Context 对象。 (2认同)

Has*_*ter 14

解决方案太简单了:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Run Code Online (Sandbox Code Playgroud)


Del*_*019 11

 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 它适用于所有SDK。这是“位图位图= MediaStore.Images.Media.getBitmap(context.getContentResolver(),uri);”的另一种方法。 (2认同)

小智 11

你可以像这样从uri中检索位图

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


小智 10

Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Run Code Online (Sandbox Code Playgroud)

  • 您能否详细说明该代码如何工作以及如何回答该问题? (2认同)

小智 6

Bitmap bitmap = null;
ContentResolver contentResolver = getContentResolver(); 
try {
    if(Build.VERSION.SDK_INT < 28) {
        bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri);
    } else {
        ImageDecoder.Source source = ImageDecoder.createSource(contentResolver, imageUri);
        bitmap = ImageDecoder.decodeBitmap(source);
    }
} catch (Exception e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)


小智 5

private fun setImage(view: ImageView, uri: Uri) {
        val stream = contentResolver.openInputStream(uri)
        val bitmap = BitmapFactory.decodeStream(stream)
        view.setImageBitmap(bitmap)
}
Run Code Online (Sandbox Code Playgroud)