Обработка больших растровых изображений на Android - int [] больше максимального размера кучи - PullRequest
2 голосов
/ 07 ноября 2011

Я использую очень большие растровые изображения и храню данные в большом int [].Изображения могут быть очень большими, и я не могу их уменьшить (я получаю растровые изображения по проводам и отрисовываю их).

Проблема, с которой я сталкиваюсь, связана с очень большими растровыми изображениями (размер растрового изображения = 64 МБ), где я пытаюсь выделить массив int размером 16384000. Я тестирую это на Samsung Galaxy SII, у которого должно быть достаточно памяти, чтобы справиться с этим, но, похоже, есть «ограничение» на размер кучи.Метод Runtime.getRuntime().maxMemory() возвращает 64 МБ, поэтому это максимальный размер кучи для данного конкретного устройства.

Уровень API установлен на 10, поэтому я не могу использовать атрибут android:largeHeap, предложенный в другом месте (и я недаже не знаю, поможет ли это).

Есть ли способ выделить более 64 МБ?Я попытался выделить массив в нативном режиме (используя функцию JNI NewIntArray), но это также не удалось.Кажется, что он ограничен тем же пределом, что и jvm.

Однако я мог бы выделить память на собственной стороне, используя NewDirectByteBuffer, но, поскольку этот байтовый буфер не поддерживается массивом, я не могу получитьдоступ к int[] (используя asIntBuffer().array() в Java, который мне нужен для отображения изображения с использованием setPixels или createBitmap. Я думаю, OpenGL был бы подходящим вариантом, но у меня (пока) 0 опыта работы сOpenGL.

Есть ли способ как-то получить доступ к выделенной памяти как int [], который мне не хватает?

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Итак, единственный способ, который я нашел, - это выделить изображение с помощью NDK. Кроме того, поскольку Bitmap не использует существующий буфер в качестве «хранилища» пикселей (метод copyPixelsFromBuffer также связан с пределами памяти; и, судя по названию метода, он все равно копирует данных).

Решение (я только приблизительно его прототипировал) состоит в том, чтобы malloc независимо от размера изображения заполнить его с помощью c / c ++, а затем использовать ByteBuffer в Java с OpenGLES .

Текущий прототип создает простую плоскость и применяет к ней это изображение в качестве текстуры (к счастью, методы OpenGLES принимают в качестве входных данных буфер, который, кажется, работает как положено). Я использую 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);
0 голосов
/ 04 июля 2016

Я полагаю, что OP уже решил эту проблему, но если у вас есть Stream, вы можете передать растровое изображение в файл и прочитать этот файл, используя inSampleSize

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...