大多数时候,在Android上获取OOM是由于使用了太多位图和/或创建大位图.
最近我决定试用JNI,以便通过将数据本身存储在JNI端来避免OOM.
在与JNI搞砸了一段时间后,我在SO上创建了一些帖子,寻求帮助并分享我的知识,现在我决定与你分享更多代码.如果有人有兴趣阅读调查结果或做出贡献,这里有帖子:
这一次,我添加了存储,恢复,裁剪和旋转位图的功能.它应该很容易添加更多选项,如果其他人在这里将自己的代码添加到更有用的功能,我会很高兴.
所以我要展示的代码实际上是合并了我创造的所有东西.
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
final int width=bitmap.getWidth(),height=bitmap.getHeight();
// store the bitmap in the JNI "world"
final JniBitmapHolder bitmapHolder=new JniBitmapHolder(bitmap);
// no need for the bitmap on the java "world", since the operations are done on the JNI "world"
bitmap.recycle();
// crop a center square from the bitmap, from (0.25,0.25) to (0.75,0.75) of the bitmap.
bitmapHolder.cropBitmap(width/4,height/4,width*3/4,height*3/4);
//rotate the bitmap:
bitmapHolder.rotateBitmapCcw90();
//get the output java bitmap , …Run Code Online (Sandbox Code Playgroud) java-native-interface android bitmap out-of-memory android-ndk
对于我的10,000点,我决定用这个很酷的网站来点缀一些东西:一种在本机内存上缓存位图的机制.
Android设备的每个应用程序的内存量非常有限 - 堆的范围从16MB到128MB,具体取决于各种参数.
如果您通过此限制,则会获得OOM,当您使用位图时,这可能会发生多次.
很多时候,应用程序可能需要克服这些限制,对巨大的位图执行繁重的操作,或者只是存储它们以供以后使用,并且您需要
我想出的是一个简单的java类,它可以使事情变得更容易.
它使用JNI来存储位图数据,并能够在需要时恢复它.
为了支持该类的多个实例,我必须使用我发现的技巧(这里).
数据仍然存储在RAM中,因此如果设备没有足够的RAM,应用程序可能会被杀死.
记得尽快释放记忆.它不仅可以避免内存泄漏,而且还可以避免在您的应用程序到达后台时首先被系统优先处理.
如果您不想忘记释放内存,可以在每次还原位图时释放它,或者使类实现Closable.
作为一种安全措施,我已经使它在finalize()方法中自动释放其本机内存,但不要让它负责这项工作.风险太大了.当这样的事情发生时,我也写了它写入日志.
它的工作方式是将整个数据复制到JNI对象中,为了还原,它从头开始创建位图并将数据放入其中.
正在使用和恢复的位图采用ARGB_8888格式.当然,您可以将其更改为您想要的任何内容,只是不要忘记更改代码...
大位图可能需要一些时间来存储和恢复,因此在后台线程上执行它可能是明智的.
这不是一个完整的OOM解决方案,但它可能有所帮助.例如,您可以将它与您自己的LruCache结合使用,同时避免将堆内存用于缓存本身.
代码仅用于存储和恢复.如果您需要执行某些操作,则需要进行一些研究.openCV可能就是答案,但是如果你想要执行一些基本的东西,你可以自己实现它们(这里是使用JNI旋转大图像的例子).如果你知道其他选择,请在这里告诉我.
希望这对某些人有用.请写下你的意见.
此外,如果您发现代码有任何问题或建议填补,请告知我们.
如果您希望在JNI端执行更多操作,您可以使用我所做的这篇文章.它基于我在这里编写的代码,但允许您进行更多操作,您可以轻松添加更多自己的代码.
什么是用于图像处理的一些跨平台和高性能图像库(调整大小和查找颜色/色调直方图).不需要gui.这适用于C/C++.
到目前为止,我一直在寻找
我的问题
您的意见非常感谢.
我正在寻找一个用于图像处理的C++库.我需要图书馆来限制PPM照片(彩色照片).我应该写自己的代码吗?你们有什么感想?
我需要libjpeg-turbo for android ndk.有没有人设法将其编译为.a(静态)lib?我试过几次,但它只给了我很多错误.
我已经决定,由于位图会占用大量内存,而这些内存很容易导致内存不足错误,因此我会对C/C++代码进行大量内存消耗.
即使一切似乎都没有任何错误,输出图像也不是原始的旋转.事实上,它完全毁了它.
旋转应该是逆时针方向,90度.

所以你可以看到,不仅颜色变得怪异,而且尺寸与我设定的尺寸不符.这里真的很奇怪.
也许我没有正确读取/放置数据?
当然这只是一个例子.代码应该可以在任何位图上正常工作,只要设备有足够的内存来容纳它.另外,我可能想在位图上执行其他操作而不是旋转它.
Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniTest
LOCAL_SRC_FILES := JniTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g
Run Code Online (Sandbox Code Playgroud)
cpp文件:
#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>
#define LOG_TAG "DEBUG"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
extern "C"
{
JNIEXPORT jobject JNICALL Java_com_example_jnitest_MainActivity_rotateBitmapCcw90(JNIEnv * env, jobject obj, jobject …Run Code Online (Sandbox Code Playgroud) java-native-interface android bitmap image-rotation android-ndk