相关疑难解决方法(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万
查看次数

如何正确下采样图像?

背景

创建一个具有大量高质量图像的应用程序,我决定将图像缩小到所需的大小(这意味着如果图像大于屏幕,我会缩小它的尺寸).

问题

我注意到在某些设备上,如果图像缩小,它们变得模糊/像素化,但在同一设备上,对于相同的目标imageView大小,如果图像没有缩小尺寸,它们看起来很好.

我试过的

我已经决定进一步检查这个问题,并创建了一个显示问题的小型POC应用程序.

在向您展示代码之前,这里是我正在谈论的演示:

在此输入图像描述

看到差异有点难,但你可以看到第二个有点像素化.这可以在任何图像上显示.

public class MainActivity extends Activity
  {
  @Override
  protected void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ImageView originalImageView=(ImageView)findViewById(R.id.originalImageView);
    final ImageView halvedImageView=(ImageView)findViewById(R.id.halvedImageView);
    final ImageView halvedBitmapImageView=(ImageView)findViewById(R.id.halvedBitmapImageView);
    //
    final Bitmap originalBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.test);
    originalImageView.setImageBitmap(originalBitmap);
    halvedImageView.setImageBitmap(originalBitmap);
    //
    final LayoutParams layoutParams=halvedImageView.getLayoutParams();
    layoutParams.width=originalBitmap.getWidth()/2;
    layoutParams.height=originalBitmap.getHeight()/2;
    halvedImageView.setLayoutParams(layoutParams);
    //
    final Options options=new Options();
    options.inSampleSize=2;
    // options.inDither=true; //didn't help
    // options.inPreferQualityOverSpeed=true; //didn't help
    final Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.test,options);
    halvedBitmapImageView.setImageBitmap(bitmap);
    }
  }
Run Code Online (Sandbox Code Playgroud)

XML:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
  android:layout_height="match_parent" tools:context=".MainActivity"
  android:fillViewport="true">
  <HorizontalScrollView android:layout_width="match_parent"
    android:fillViewport="true" android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent"
      android:layout_height="match_parent" …
Run Code Online (Sandbox Code Playgroud)

android decode bitmap downsampling pixelate

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

java Android - 以编程方式处理图像缩放/裁剪

好吧,这一切折磨了我好几个星期,我将图像设置为 227 像素高,将其缩放到 170 像素,即使我希望它在任何时候都是 wrap_content。

好的。在这里,我采用了 1950 像素长的我的图像(我把它的一部分放在这里,这样你就可以理解它应该是什么样子)。

在此处输入图片说明

首先,我想将其缩放回 227 像素高,因为这就是它的设计方式以及应该如何

Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.ver_bottom_panel_tiled_long);
            int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();
        int newWidth = 200; //this should be parent's whdth later
        int newHeight = 227;

        // calculate the scale
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        // create a matrix for the manipulation
        Matrix matrix = new Matrix();
        // resize the bit map
        matrix.postScale(scaleWidth, scaleHeight);

        // recreate the new Bitmap …
Run Code Online (Sandbox Code Playgroud)

java android image crop

1
推荐指数
1
解决办法
9369
查看次数