这可能听起来非常具体......而且它有点像。
我真的需要在Android 2.3上加载一个2048x2048的32位图像(特别是Nexus One和Xperia Play,其当前形式的应用程序完全崩溃并出现内存不足错误)。
Android 2.2加载它很好,2.3之后的所有机器人也加载它,并且一些2.3设备(通常有大堆)也加载它。
Xperia Play特别报告(通过OpenGL)它可以加载高达4096x4096的图像,并且使用Marmalade SDK我真的可以加载疯狂的巨大图像,其中很多,很容易使用150mb的内存。
但我无法想象如何在该设备上加载带有Java的2048x2048图像,它只是抛出了这个错误:
05-07 17:41:25.202:E / GraphicsJNI(27847):VM不允许我们分配30965760字节
编辑:不要告诉我使用较低的分辨率,我会自己引用:我真的需要在Android 2.3上加载2048x2048 32位图像
较低的样本图像不是2048x2048,也不是更高的图像,或缩放的图像,或mipmap版本,或其他任何东西......我需要加载这些图像的方式,期间。
答案 0 :(得分:4)
修改强>
由于您不想缩小图像(这是可以理解的),您可能需要考虑减少要加载到内存中的图像的质量/ sizeInMbs。
例如,你说你的图像是2048 * 2048,大约需要30 mb,这对于大小的图像来说非常大。
看看这个demo from Romain Guy,他使用的图像是1280 * 752但是只有几百kbs。尽管尺寸很小,但working demo上的图像看起来非常清晰明快。
首先,将2048 * 2048图像加载到小型设备屏幕(例如您提到的那些设备)是浪费资源。这是指向如何有效扩展和加载大型图像的fully detailed tutorial的链接。
请记住,您应尽可能尝试缩小图像,Android开发者网站提到:"分辨率较高的图像不会提供任何明显的好处,但仍占用宝贵的内存和由于额外的动态扩展,会产生额外的性能开销。"
第一步,首先使用BitmapFactory.Options获取图像尺寸:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
第二步,找出一个采样因子:向下缩放图像的数量
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
最后,您可以使用以下方式缩小它:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
答案 1 :(得分:1)
30965760 字节听起来相当大,分辨率为2048x2048。
图像是每通道32位而不是每通道8位吗?当我要求人们使用32位PNG时,常见的错误是他们在Photoshop等程序中选择了32位/通道(128位图像)模式。
红色( 8位)+绿色( 8位)+蓝色( 8位)+ Alpha( 8位)= 32位图像。
答案 2 :(得分:0)
使用BitmapRegionDecoder来查看仅在任何给定时间可见(或将很快可见)的位图部分。请参阅:Using BitmapRegionDecoder to load large images
答案 3 :(得分:-1)
您必须缩小位图以减少内存消耗。 我建议你查看关于Loading Large Bitmaps Efficiently的这个问题的官方文档。
作为额外的建议,不要忘记回收所有未使用的位图。这将有助于GC更快地释放内存。
答案 4 :(得分:-1)
如果您因任何原因需要全分辨率(而不是降低daniel_c05答案中的分辨率)并且您不能使用OpenGL(为什么不呢?它是完美的),
但实际上,如果您正在以这种规模工作并且想要速度,那么您应该使用OpenGL。