相关疑难解决方法(0)

如何在使用大图像时使用JNI位图操作来帮助避免OOM?

背景

大多数时候,在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

46
推荐指数
1
解决办法
3万
查看次数

如何将位图缓存到本机内存中

对于我的10,000点,我决定用这个很酷的网站来点缀一些东西:一种在本机内存上缓存位图的机制.

背景

Android设备的每个应用程序的内存量非常有限 - 堆的范围从16MB到128MB,具体取决于各种参数.

如果您通过此限制,则会获得OOM,当您使用位图时,这可能会发生多次.

很多时候,应用程序可能需要克服这些限制,对巨大的位图执行繁重的操作,或者只是存储它们以供以后使用,并且您需要

我想出的是一个简单的java类,它可以使事情变得更容易.

它使用JNI来存储位图数据,并能够在需要时恢复它.

为了支持该类的多个实例,我必须使用我发现的技巧(这里).

重要笔记

  • 数据仍然存储在RAM中,因此如果设备没有足够的RAM,应用程序可能会被杀死.

  • 记得尽快释放记忆.它不仅可以避免内存泄漏,而且还可以避免在您的应用程序到达后台时首先被系统优先处理.

  • 如果您不想忘记释放内存,可以在每次还原位图时释放它,或者使类实现Closable.

  • 作为一种安全措施,我已经使它在finalize()方法中自动释放其本机内存,但不要让它负责这项工作.风险太大了.当这样的事情发生时,我也写了它写入日志.

  • 它的工作方式是将整个数据复制到JNI对象中,为了还原,它从头开始创建位图并将数据放入其中.

  • 正在使用和恢复的位图采用ARGB_8888格式.当然,您可以将其更改为您想要的任何内容,只是不要忘记更改代码...

  • 大位图可能需要一些时间来存储和恢复,因此在后台线程上执行它可能是明智的.

  • 这不是一个完整的OOM解决方案,但它可能有所帮助.例如,您可以将它与您自己的LruCache结合使用,同时避免将堆内存用于缓存本身.

  • 代码仅用于存储和恢复.如果您需要执行某些操作,则需要进行一些研究.openCV可能就是答案,但是如果你想要执行一些基本的东西,你可以自己实现它们(这里是使用JNI旋转大图像的例子).如果你知道其他选择,请在这里告诉我.

希望这对某些人有用.请写下你的意见.

此外,如果您发现代码有任何问题或建议填补,请告知我们.


好的解决方案

如果您希望在JNI端执行更多操作,您可以使用我所做的这篇文章.它基于我在这里编写的代码,但允许您进行更多操作,您可以轻松添加更多自己的代码.

java-native-interface android caching native bitmap

38
推荐指数
1
解决办法
2万
查看次数

快速跨平台C/C++图像处理库

什么是用于图像处理的一些跨平台和高性能图像库(调整大小和查找颜色/色调直方图).不需要gui.这适用于C/C++.

到目前为止,我一直在寻找

  • OpenCV的
  • GIL是Boost的一部分
  • 魔鬼
  • CIMG

我的问题

  • 我上面列出的那些表现如何
  • 还有什么其他的图书馆

您的意见非常感谢.

c c++ performance cross-platform image-processing

27
推荐指数
2
解决办法
3万
查看次数

C++图像处理库

我正在寻找一个用于图像处理的C++库.我需要图书馆来限制PPM照片(彩色照片).我应该写自己的代码吗?你们有什么感想?

c++ image-processing

17
推荐指数
5
解决办法
5万
查看次数

libjpeg-turbo for android

我需要libjpeg-turbo for android ndk.有没有人设法将其编译为.a(静态)lib?我试过几次,但它只给了我很多错误.

android jpeg android-ndk libjpeg-turbo

16
推荐指数
2
解决办法
2万
查看次数

使用JNI和NDK旋转位图

背景:

我已经决定,由于位图会占用大量内存,而这些内存很容易导致内存不足错误,因此我会对C/C++代码进行大量内存消耗.

我用来旋转位图的步骤是:

  1. 读取位图信息(宽度,高度)
  2. 将位图像素存储到数组中.
  3. 回收位图.
  4. 创建一个相反大小的新位图.
  5. 将像素放入新的位图.
  6. 释放像素并返回位图.

问题:

即使一切似乎都没有任何错误,输出图像也不是原始的旋转.事实上,它完全毁了它.

旋转应该是逆时针方向,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

11
推荐指数
1
解决办法
2万
查看次数