我使用非常大的位图,并将数据存储在一个大 int[] 中。图像可能非常大,我无法对它们进行下采样(我通过网络获取位图并渲染它们)。
我遇到的问题是在非常大的位图上(位图大小 = 64MB),我尝试分配大小为 16384000 的 int 数组。我正在 Samsung Galaxy SII 上测试这个,它应该有足够的内存来处理这个问题,但堆大小似乎有一个“上限”。方法Runtime.getRuntime().maxMemory()
返回 64MB,因此这是该特定设备的最大堆大小。
API级别设置为10,所以我无法使用android:largeHeap
其他地方建议的属性(我什至不知道这是否有帮助)。
有什么办法可以分配超过64MB的空间吗?我尝试在 native 中分配数组(使用 JNI NewIntArray
函数),但也失败了。看起来好像它受到与jvm相同的限制。
但是,我可以使用 NewDirectByteBuffer
在 native 端分配内存,但由于该字节缓冲区不受数组支持,因此我无法访问 int[]
(在java中使用asIntBuffer().array()
,我需要使用setPixels
或createBitmap
来显示图像。我想OpenGL将是一种可行的方法,但我(到目前为止)有0个OpenGL经验。
有没有办法以某种方式访问我丢失的 int[] 分配的内存?
最佳答案
所以,到目前为止我发现的唯一方法是使用 NDK 分配图像。此外,由于 Bitmap 不使用现有的 Buffer 作为像素“存储”(方法 copyPixelsFromBuffer
也受到内存限制;并且从方法名称来看,它复制数据无论如何)。
解决方案(我只是大致原型(prototype)化了它)是 malloc
无论图像的大小是什么,并使用 c/c++ 填充它,然后在 Java 中使用 ByteBuffer OpenGLES .
当前的原型(prototype)创建了一个简单的平面,并将该图像作为纹理应用于它(幸运的是,OpenGLES 方法将 Buffer 作为输入,这似乎按预期工作)。我使用 glTexImage2D
将此缓冲区作为纹理应用于平面。这是一个示例,其中 mImageData 是在 native 端分配(并填充)的 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);
关于android - 在 Android 上处理大位图 - int[] 大于最大堆大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8037821/