android - 位图创建和绘制速度慢...但快

标签 android performance bitmap drawing

这在一小部分是一个问题(因为我不明白为什么它会产生影响),在很大程度上是一个帖子,希望能帮助其他一些可怜的程序员。

我有一个代码库,是我在 5-7 年前第一次开始 Android 编程时编写的,它具有将文件读入内存的函数(可用于很多事情),以及一个加载函数.png 文件中的位图。后一个函数使用“读取文件”函数将文件中的字节读取到字节数组中,然后从中创建位图。我知道这不是真正干净的代码,也可能不是最好的方法,但它有效,为什么要破坏有效的东西呢?

除了... Android(尤其是 Oreo)的最后几个版本导致我的应用程序中的绘图(来自位图)确实减慢了速度。我挣扎了好几天,试图弄清楚发生了什么,最后偶然发现了一个解决方案......我不明白。

这是“将 .png 文件加载到位图”功能的核心(原样)。请注意,整个“if-for-for”透明度内容可能可以完全忽略,这是将一种或两种颜色的像素转换为透明像素的特殊情况。在进入该 block 时,.png 文件已被读入“位”。

BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inPreferredConfig = Bitmap.Config.valueOf("ARGB_8888");
Bitmap imbm = BitmapFactory.decodeByteArray(bits, 0, flen, bfo);// this makes an IMmutable bitmap
bits = null;
System.gc();
Bitmap bm = imbm.copy(Bitmap.Config.valueOf("ARGB_8888"), true);// convert it to a MUTABLE bitmap
imbm.recycle();
imbm = null;
w = bm.getWidth();
h = bm.getHeight();
// do transparency stuff
if (transX1 >= 0 && transX1 < w && transY1 >= 0 && transY1 < h) {
    clr1 = bm.getPixel(transX1, transY1);
    clr2 = bm.getPixel(transX2, transY2);
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            clr = bm.getPixel(x, y);
            // convert any 0x00818181 (middle-gray) pixels to 0x00808080
            // so that 0x00818181 is guaranteed to never be used in customer-created bitmaps
            if (clr1 != 0xFF818181 && clr == 0xFF818181) bm.setPixel(x, y, 0xFF808080);
            else if (clr == clr1 || clr == clr2) bm.setPixel(x, y, clr & 0x00000000);
        }
    }
}
System.gc();    // request garbage-collection to try to avoid out-of-memory when loading/creating bitmap
return bm;

然后将返回的位图用作源,使用 dC.drawBitmap(bm, sRect, dRect, kPaint) 将位图和 fragment 绘制到上下文中。然而,Android 的变化导致速度减慢。修复结果是用以下代码替换上面的最终“return bm”:

Bitmap tBM = Bitmap.createBitmap(w, h, Bitmap.Config.valueOf("ARGB_8888"));
Rect sRect = new Rect();
Rect dRect = new Rect();
sRect.set(0, 0, w, h);
dRect.set(0, 0, w, h);
Canvas dC = new Canvas(tBM);
dC.drawBitmap(bm, sRect, dRect, kPaint);
dC = null;
bm = null;
return tBM;

换句话说,它只是采用先前版本生成的“bm”位图,创建另一个相同大小的位图,将“bm”绘制到新位图中,然后返回新位图而不是先前版本。

关于以前构造位图的方法似乎使其处于“不良形式”,这使得从它进行绘制非常慢,同时对它执行 createBitmap() 和 drawBitmap() 会产生一个您可以使用的位图绘制速度非常快。

有什么想法吗? (是的,我尝试了所有常见的 RGB_565 等)这很有效。但如果我明白为什么会发生这种情况,那就太好了,就像我说的,我的痛苦可能对 future 的某人有用。

最佳答案

我的怀疑是正确的,速度减慢是由decodeByteArray()(某种程度上)引起的。

首先,随着更多的研究(以及高龄和知识),我意识到通过设置 BitmapFactory.Options.inMutable=true 可以更轻松地解决不可变/可变问题。

但是,问题的真正解决方案是将代码的“核心”更改为:

BitmapFactory.Options   bfo = new BitmapFactory.Options();
bfo.inPreferredConfig = Bitmap.Config.valueOf("ARGB_8888");
bfo.inMutable = true;   // this makes an mutable bitmap
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    bfo.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
}
Bitmap  bm = BitmapFactory.decodeByteArray(bits, 0, flen, bfo);
bits = null;
换句话说,我摆脱了上面提到的不可变/可变位图副本,然后测试是否在 Oreo 或更高版本上运行,如果是这样,则设置 inPreferredColorSpace 成员。这是在 Oreo (API 26) 中添加的。我想当他们添加类似的东西时,它会被设置为合理的默认值,我想它是,只是显然不能很好地将位图绘制到显示器上。默认值是“null”,但是将其更改为 SRGB 足以使我从生成的位图快速绘制到显示器,因此我假设(总是危险的)这个颜色空间问题是通过拼凑解决的我在原始帖子中制作的位图的副本。

关于android - 位图创建和绘制速度慢...但快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48835147/

相关文章:

javascript - 如何自动检测是否需要iScroll?

java - 添加 Google Play 服务和 Proguard 时出现警告?

python - 检查数据框元组中的值是否

Android:OnActivityResult 中的 Intent 给出了错误的路径

java - 获取错误 : cannot resolve symbol for 'compress' for bitmap. 压缩(Bitmap.CompressFormat.PNG,0,流);

android - 位图文本与 native 缓存的比较

android - 可扩展面板布局

javascript - 错误 :com. 重复条目 : com/google/android/gms/internal/zzfj. 类

performance - ChromeDriver - 网络性能日志记录 : Understanding timing section of Network. 响应已接收

c++ - vector 或 map ,使用哪一个?