首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >位图创建和绘图速度慢..。又快

位图创建和绘图速度慢..。又快
EN

Stack Overflow用户
提问于 2018-02-16 21:31:31
回答 1查看 1.5K关注 0票数 2

这在很小程度上是一个问题(因为我不明白为什么会有所不同),在很大程度上是为了帮助其他一些糟糕的程序员。

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

除了..。Android (尤其是奥利奥)的最后几次变化导致我的应用程序中的绘图(从位图中)缓慢下来。我挣扎了几天,试图弄清楚到底是怎么回事,最后偶然发现了一个办法.但我不明白。

这里是“将.png文件加载到位图”函数的核心(按原样)。请注意,整个"if- for -for“透明内容可能会被完全忽略,这是将一两种颜色的像素转换为透明像素的特例。在进入这个块时,.png文件已经被读取到“bits”中。

代码语言:javascript
复制
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)绘制到上下文中的比特和片段的源。然而,Android系统的变化导致了这一趋势的放缓。修复结果是用以下代码替换上面最后的“返回bm”:

代码语言:javascript
复制
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工具,等等)这件事做得很好。但如果我明白为什么会发生这种情况,那就很好了,就像我说过的,我的苦痛可能会对未来的人有用。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-18 17:20:24

我的猜测是,慢下来是由decodeByteArray() (某种程度上)造成的。

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

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

代码语言:javascript
复制
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;

换句话说,我去掉了上面提到的不可变/可变位图副本,然后测试是否运行在奥利奥或更高版本上,如果是这样的话,设置inPreferredColorSpace成员。这是在Oreo (API 26)中添加的。我会想,当他们添加这样的东西时,它会被设置为一个合理的缺省值,我认为是这样的,只是不太适合将位图绘制到显示上。默认值为'null',但将其更改为SRGB就足以使我的绘图快速从所产生的位图闪电到显示,因此我假设(总是危险的)这个颜色空间问题是由我在最初的文章中所做的位图的拼接副本所纠正的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48835147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档