说我在磁盘上有一些大的(即不适合大多数手机的内存)位图。我想以一种不缩放的方式在屏幕上绘制部分内容(即inSampleSize == 1
)
有没有办法加载/绘制我想要的部分Rect
指定区域而不加载整个位图内容?
答案 0 :(得分:9)
我非常有信心这是可能的,因为你可以毫无问题地将一个非常大的位图文件加载到ImageView
中,因此必须有某种内置方式来处理大型位图......之后几次尝试,我找到了解决方案:
不是加载整个位图并自行手动绘制,而是将其作为Drawable
加载:
InputStream mapInput = getResources().openRawResource(
R.drawable.transit_map);
_map = Drawable.createFromStream(mapInput, "transit_map");
_map.setBounds(0, 0, _mapDimension.width(), _mapDimension.height());
我正在使用资源文件,但由于您可以使用Drawable.createFromStream
从任何InputStream
加载图片,因此它应该适用于任意位图。
然后,使用Drawable.draw
方法将其绘制到所需的画布上,如下所示:
int left = -(int) contentOffset.x;
int top = -(int) contentOffset.y;
int right = (int) (zoom * _mapDimension.width() - contentOffset.x);
int bottom = (int) (zoom * _mapDimension.height() - contentOffset.y);
_map.setBounds(left, top, right, bottom);
_map.draw(canvas);
与上述情况一样,您也可以通过操纵drawable的边界来缩放和转换位图,并且只会加载位图的相关部分并将其绘制到Canvas
上。强>
结果是只有一个200KB位图文件的可缩放缩放视图。我还使用22MB PNG文件对其进行了测试,当屏幕方向发生变化时,它仍然无法使用任何OutOfMemoryError
。
答案 1 :(得分:4)
现在它非常相关:BitmapRegionDecoder。
注意:自Android SDK 10起可用
答案 2 :(得分:3)
可以使用RapidDecoder轻松完成。
import rapid.decoder.BitmapDecoder;
Rect bounds = new Rect(10, 20, 30, 40);
Bitmap bitmap = BitmapDecoder.from("your-file.png")
.region(bounds)
.decode();
imageView.setImageBitmap(bitmap);
支持Android 2.2(API Level 8)。
答案 3 :(得分:1)
一般来说,这是不可能的,特别是因为大多数图像格式都是压缩的,因此在提取未压缩的表单之前,您甚至不知道要读取哪些字节。
将图像分解为小图块并仅加载需要覆盖要在运行时显示的区域的图块。为了避免抖动滚动,您可能还需要在后台线程上预加载看不见的图块(与可见图块边界的图块)。