在Android上处理大型位图 - int []大于最大堆大小

时间:2011-11-07 14:29:55

标签: android memory android-ndk

我正在使用非常大的位图,我将数据存储在一个大的int []中。图像可能非常大,我无法对它们进行下采样(我在线上获取位图并渲染它们)。

我遇到的问题是非常大的位图(位图大小= 64MB),我尝试分配大小为16384000的int数组。我在三星Galaxy SII上测试它,它应该有足够的内存来处理这个,但似乎堆大小有一个“上限”。方法Runtime.getRuntime().maxMemory()返回64MB,因此这是此特定设备的最大堆大小。

API级别设置为10,因此我无法在其他位置使用android:largeHeap属性(我甚至不知道这是否会有所帮助)。

有没有办法分配超过64MB?我尝试在本机中分配数组(使用JNI NewIntArray函数),但也失败了。似乎它受到与jvm相同的限制。

但是我可以使用NewDirectByteBuffer在本机端分配内存,但由于此字节缓冲区没有数组支持,因此我无法访问int[](使用asIntBuffer().array()为了使用setPixelscreateBitmap显示图像我需要的java。我想OpenGL是一种方法,但我(迄今为止)有过使用OpenGL的经验。

有没有办法以某种方式将分配的内存作为int []访问我错过了?

2 个答案:

答案 0 :(得分:3)

所以,到目前为止我找到的唯一方法是使用NDK分配图像。此外,由于Bitmap不使用现有的Buffer作为像素“存储”(方法copyPixelsFromBuffer也绑定到内存限制;并且通过方法名称判断,它复制数据)。

解决方案(我只是大致原型)是malloc无论图像的大小是什么,并使用c / c ++填充它,然后在Java中使用ByteBuffer OpenGLES。< / p>

当前原型创建一个简单的平面并将此图像作为纹理应用于它(幸运的是,OpenGLES方法将Buffer作为输入,这似乎按预期工作)。我正在使用glTexImage2D将此缓冲区作为纹理应用于平面。这是一个示例,其中mImageData是ByteBuffer在本机端分配(和填充)。

int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureId = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, 4000, 4096, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, mImageData);

答案 1 :(得分:0)

我认为OP已经解决了这个问题,但是如果你有一个Stream,你可以将位图流式传输到一个文件中并使用inSampleSize

读取该文件