如何从Uri获取位图?

12 浏览
0 Comments

如何从Uri获取位图?

如何从Uri获取一个Bitmap对象(如果我成功将它存储在/data/data/MYFOLDER/myimage.pngfile:///data/data/MYFOLDER/myimage.png中),以便在我的应用程序中使用它?\n有人知道如何实现这一点吗?

0
0 Comments

如何从Uri获取位图?

在Android的API 29中,MediaStore.Images.Media.getBitmap方法被废弃了。推荐的方法是使用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方法则不行。

文档明确指出:“此方法应在工作线程中执行,而不是主线程中!”

然而,这种方法在较新的Android版本上无法正常工作。

问题的原因是在API 29中,Android废弃了MediaStore.Images.Media.getBitmap方法。为了替代这个方法,推荐使用ImageDecoder.createSource方法来获取位图。然而,仅仅替换方法是不够的,还需要注意ImageDecoder.decodeBitmap方法可以读取EXIF方向信息,而Media.getBitmap方法则不行。此外,根据文档的建议,获取位图的操作应该在工作线程中执行,而不是主线程中。

解决方法是根据Android版本的不同,使用不同的方法来获取位图。在API 28及更高版本中,可以使用ImageDecoder.createSource方法和ImageDecoder.decodeBitmap方法来获取位图。而在API 28以下的版本中,可以继续使用MediaStore.Images.Media.getBitmap方法。

需要注意的是,使用ImageDecoder.createSource方法和ImageDecoder.decodeBitmap方法获取位图时,需要在工作线程中执行,而不是主线程中。这样可以避免阻塞主线程,提高应用的性能和响应速度。

0
0 Comments

如何从Uri获取位图?

在上述代码中,我们可以看到这个问题的出现主要是因为需要从Uri获取位图。解决方法是使用getContentResolver().openInputStream(uri)方法打开Uri对应的输入流,然后使用BitmapFactory.decodeStream(input, null, options)方法将输入流解码为位图。在解码过程中,我们可以设置一些选项,如inJustDecodeBounds、inSampleSize等,以控制内存的使用和位图的大小。

在这段代码中,我们可以看到以下解决方法的步骤:

1. 在onActivityResult方法中,获取返回的Uri对象,并调用getThumbnail方法获取位图。

2. 在getThumbnail方法中,首先使用getContentResolver().openInputStream(uri)方法打开Uri对应的输入流。

3. 创建一个BitmapFactory.Options对象,并将其inJustDecodeBounds属性设置为true,以获取位图的原始尺寸。

4. 调用BitmapFactory.decodeStream(input, null, onlyBoundsOptions)方法,将输入流解码为位图,但不将其加载到内存中。

5. 关闭输入流。

6. 判断位图的宽度和高度是否为-1,如果是,则返回null。

7. 计算原始尺寸和缩略图大小之间的比例,并根据比例计算出inSampleSize值。

8. 创建一个新的BitmapFactory.Options对象,并将其inSampleSize属性设置为计算得到的值。

9. 再次打开输入流,并调用BitmapFactory.decodeStream(input, null, bitmapOptions)方法,将输入流解码为缩略图位图。

10. 关闭输入流,并返回缩略图位图。

此外,还有一些其他的注意事项和建议:

- 在静态方法中,无法直接使用this关键字,可以通过将其作为参数传递给方法来解决这个问题。

- THUMBNAIL_SIZE是缩略图的大小,可以根据需要进行调整。

- 需要关闭和重新打开输入流的原因是,第一次调用BitmapFactory.decodeStream(...)方法会将输入流的读取位置设置为末尾,所以第二次调用该方法时,如果不重新打开输入流,将无法正常工作。

- THUMBNAIL_SIZE应该是要显示缩略图的视图的大小。

- 不需要自己计算比例的两个幂,因为解码器本身会将采样大小舍入到最接近的两个幂。因此,可以跳过getPowerOfTwoForSampleRatio()方法的调用。

通过使用getContentResolver().openInputStream(uri)方法打开Uri对应的输入流,并使用BitmapFactory.decodeStream(input, null, options)方法将输入流解码为位图,我们可以从Uri获取位图。在解码过程中,可以使用一些选项来控制内存的使用和位图的大小。

0
0 Comments

如何从Uri获取Bitmap?

问题的出现原因:

- 问题最初是由于大图像加载而引起的内存溢出错误。getBitmap()方法调用decodeStream(),而后者在处理大图像时会导致OOM错误。

- 另一个问题是,如果只知道图像的路径而无法访问data.getData()方法,该如何获取Uri和Bitmap对象。

解决方法:

- 对于大图像加载,可以使用以下代码以瓦片的方式加载图像,避免大内存分配:

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

- 对于无法访问data.getData()方法的情况,可以参考这里的文档,并提出新的问题以获取解决方案。

- 代码中的try-catch块不是必需的,但在某些情况下,getBitmap()方法可能会抛出异常。

需要注意的是,MediaStore.Images.Media.getBitmap()方法已经被弃用,可以使用其他方法来获取Bitmap对象。

从Uri获取Bitmap的过程中,需要注意内存溢出错误和无法访问data.getData()方法的问题。在处理大图像时,可以使用瓦片加载的方法来避免内存溢出。如果无法访问data.getData()方法,可以通过提出新的问题来获取解决方案。另外,需要注意某些方法的弃用情况,可以使用其他方法来获取Bitmap对象。

0