有没有办法从 Android 中的文件加载并部分绘制位图?
假设我在磁盘上有一个有点大(即不适合大多数手机的内存)的位图。我只想以不缩放的方式在屏幕上绘制它的一部分(即 inSampleSize == 1
)
有没有办法加载/绘制我想要的部分给定 Rect
指定区域而不加载整个位图内容?
Say I have a somewhat large (i.e. not fit in most phones' memory) bitmap on disk. I want to draw only parts of it on the screen in a way that isn't scaled (i.e. inSampleSize == 1
)
Is there a way to load/draw just the part I want given a Rect
specifying the area without loading the entire bitmap content?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我非常有信心这是可能的,因为您可以毫无问题地将一个非常大的位图文件加载到 ImageView 中,因此必须有某种内置方法来处理大位图......然后经过几次尝试,我找到了一个解决方案:
不要加载整个位图并自己手动绘制它,而是将其加载为
Drawable
:我正在使用资源文件,但由于您可以使用 Drawable.createFromStream 从任何 InputStream 加载图像,因此它应该适用于任意位图。
然后,使用
Drawable.draw
方法将其绘制到所需的画布上,如下所示:如上例所示,您还可以通过操作可绘制对象的边界来缩放和平移位图仅位图的相关部分会被加载并绘制到
Canvas
上。结果是仅从一个 200KB 位图文件中获得可捏缩放视图。我还使用 22MB PNG 文件对此进行了测试,它仍然可以正常工作,没有任何
OutOfMemoryError
,包括当屏幕方向发生变化时。I'm quite confident this is possible since you can load a really large bitmap file into an
ImageView
without problems so there must be some sort of a built-in way to handle large bitmaps... and after a few attempts, I've found a solution:Instead of loading the entire bitmap and manually draw it yourself, load it as a
Drawable
instead:I'm using a resource file but since you can use
Drawable.createFromStream
to load image from anyInputStream
, it should works with arbitrary bitmap.Then, use the
Drawable.draw
method to draw it onto the desired canvas like so:As in the above case, You can also scale and translate the bitmap as well by manipulating the drawable's bounds and only the relevant parts of the bitmap will be loaded and drawn onto the
Canvas
.The result is a pinch-zoomable view from just one single 200KB bitmap file. I've also tested this with a 22MB PNG file and it still works without any
OutOfMemoryError
including when screen orientation changes.现在它非常相关:BitmapRegionDecoder。
注意:自 Android SDK 10 起可用
Now it's very relevant: BitmapRegionDecoder.
Note: available since Android SDK 10
使用 RapidDecoder 可以轻松完成此操作。
它支持低至 Android 2.2(API 级别 8)。
It can easily be done by using RapidDecoder.
It supports down to Android 2.2 (API Level 8).
一般来说,这是不可能的,特别是因为大多数图像格式都是压缩的,因此在提取未压缩的形式之前,您甚至不知道要读取哪些字节。
将图像分成小图块,然后仅加载覆盖要在运行时显示的区域所需的图块。为了避免滚动抖动,您可能还需要在后台线程上预加载刚刚看不见的图块(与可见图块接壤的图块)。
Generally speaking, that isn't possible, particularly since most image formats are compressed, so you don't even know which bytes to read until you've extracted the uncompressed form.
Break your image up into small tiles and load just the tiles you need to cover the region you want to display at runtime. To avoid jittery scrolling, you might also want to preload tiles that are just out of sight (the ones that border the visible tiles) on a background thread.