【问题标题】:How to get Bitmap from an Uri?如何从 Uri 获取位图?
【发布时间】:2011-04-22 06:06:07
【问题描述】:

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

有没有人知道如何做到这一点?

【问题讨论】:

    标签: android uri android-image android-bitmap


    【解决方案1】:

    这是正确的做法:

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

    查看答案here

    【讨论】:

    • 此代码不处理更大的图像(基本上任何壁纸尺寸)。 getBitmap() 调用 decodeStream() 失败并出现来自stackoverflow.com/questions/2220949/handling-large-bitmaps 的 OOM 错误。还有什么建议吗? MediaStore.Images.Thumbnails.getThumbnail() 显然不接受 contentURI。
    • 在这里查看答案:stackoverflow.com/questions/4753013/…
    • @MarkIngram 这适用​​于任何本地图像还是仅适用于相机图像?
    • @MarkIngram 如果我们无法访问 data.getData() 怎么办,我的意思是如果我只是从图库中打开一些图像并且我都知道它的路径,我怎样才能获得 uri 和位图?
    • MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);现已弃用
    【解决方案2】:

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

    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(),因此您不会丢失任何功能。

    参考资料:

    【讨论】:

    • 这对我很有帮助,尽管我认为值得一提的是 this 关键字不能在静态上下文中使用。我将它作为参数传递给 getThumbnail 方法,它就像一个魅力。
    • 谁能告诉我应该给THUMBNAILSIZE什么值
    • 关闭再重新打开 InputStream 实际上是必要的,因为第一次 BitmapFactory.decodeStream(...) 调用将流的读取位置设置到末尾,因此该方法的第二次调用不起作用不再重新打开流!
    • THUMBNAILSIZE ,顾名思义是要显示为缩略图的图像的大小,即。缩略图显示尺寸
    • 不需要自己计算比率为 2 的幂,因为解码器本身会将样本大小四舍五入到最接近的 2 的幂。因此可以跳过方法调用getPowerOfTwoForSampleRatio()。见:developer.android.com/reference/android/graphics/…
    【解决方案3】:
    try
    {
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
    }
    catch (Exception e) 
    {
        //handle exception
    }
    

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

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

    【讨论】:

    • @Dhananjay 谢谢,您的提示节省了我的时间,它可以从 Content Provider 加载缩略图位图。
    • 另外,Uri.parse()必须包含URI格式,如:Uri.parse("file:///mnt/sdcard/filename .jpg"),否则我们会得到 java.io.FileNotFoundException: No content provider.
    • 一些社论会很好,但这是对大多数情况下有效的 OP 问题的一个很好的简洁答案。这是一个很好的答案,可以在页面上提取出直接回答 OP 问题的其他答案。
    • @AndroidNewBee c 是上下文对象。
    • 在我的情况下无法正常工作导致异常原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'java.lang.String android.net.Uri.getScheme()'
    【解决方案4】:

    似乎MediaStore.Images.Media.getBitmapAPI 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)
    }
    

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

    【讨论】:

    • 文档清楚地写着“这个方法应该在工作线程中完成,而不是在主线程中完成!”
    【解决方案5】:
    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();
        }
    }
    

    【讨论】:

    • 它适用于所有 sdk .. 谢谢。这是Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri); 的替代方式
    • MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri) 已弃用
    【解决方案6】:

    这是最简单的解决方案:

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

    【讨论】:

      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:
        Uri imgUri = data.getData();
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
        

        【讨论】:

        • 您能否详细说明此代码的工作原理以及它如何回答问题?
        【解决方案9】:
          InputStream imageStream = null;
            try {
                imageStream = getContext().getContentResolver().openInputStream(uri);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
        

        【讨论】:

          【解决方案10】:
          private fun setImage(view: ImageView, uri: Uri) {
                  val stream = contentResolver.openInputStream(uri)
                  val bitmap = BitmapFactory.decodeStream(stream)
                  view.setImageBitmap(bitmap)
          }
          

          【讨论】:

            【解决方案11】:

            使用 startActivityForResult 方法,如下所示

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

            【讨论】:

              【解决方案12】:

              getBitmap 的插图现在已被贬低,我在 Kotlin 中使用以下方法

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

              【讨论】:

                【解决方案13】:

                我尝试了很多方法。这对我来说很完美。

                如果您从图库中选择图片。您需要注意从intent.clipdataintent.data 获取Uri,因为其中一个在不同版本中可能为空。

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

                【讨论】:

                  【解决方案14】:

                  你可以这样做:

                  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 转换为位图。 希望能帮到你。

                  【讨论】:

                  • 这不适用于 android nougat 7.1.1 版本。这个 extras.getParcelable("data");正在返回 null
                  【解决方案15】:

                  (科特林) 因此,截至 2020 年 4 月 7 日,上述选项均无效,但以下是对我有效的方法:

                  1. 如果要将位图存储在 val 中并使用它设置 imageView,请使用:

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

                  2. 如果你只想设置位图和imageView,使用这个:

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

                  【讨论】:

                    【解决方案16】:
                    * For getting bitmap from uri. Work for me perfectly.
                        
                        
                        public static Bitmap decodeUriToBitmap(Context mContext, Uri sendUri) {
                              Bitmap getBitmap = null;
                              try {
                                InputStream image_stream;
                                try {
                                  image_stream = mContext.getContentResolver().openInputStream(sendUri);
                                  getBitmap = BitmapFactory.decodeStream(image_stream);
                                } catch (FileNotFoundException e) {
                                  e.printStackTrace();
                                }
                              } catch (Exception e) {
                                e.printStackTrace();
                              }
                              return getBitmap;
                            }
                    

                    【讨论】:

                      【解决方案17】:

                      通过使用 glide 库,您可以从uri 获取位图,

                      几乎在三星设备中图像旋转时我们必须使用exifinterface检查旋转

                      但使用 glide 不需要检查旋转,图像总是正确接收。

                      在 kotlin 中你可以得到bitmap

                      CoroutineScope(Dispatchers.IO).launch {
                         var bitmap = Glide.with(context).asBitmap().load(imageUri).submit().get()//this is synchronous approach                  
                      }
                      

                      我正在使用这个依赖项

                      api 'com.github.bumptech.glide:glide:4.12.0'
                      kapt 'com.github.bumptech.glide:compiler:4.12.0'
                      

                      【讨论】:

                        【解决方案18】:

                        从手机图库中获取图片 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();
                              }
                        
                        
                           }
                        }
                        

                        【讨论】:

                          【解决方案19】:
                          ContentResolver cr = context.getContentResolver();
                          try (InputStream input = cr.openInputStream(url)) {
                              Bitmap bitmap = BitmapFactory.decodeStream(input);
                          }
                          

                          【讨论】:

                          • 考虑稍微解释一下你的答案。尤其是 cr (contentResolver) 部分。
                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2019-12-24
                          • 2012-09-15
                          • 1970-01-01
                          • 1970-01-01
                          • 2022-06-13
                          • 1970-01-01
                          相关资源
                          最近更新 更多