2012-09-02 59 views
1

我开始我的Android应用程序使用PNG文件的对象,需要alpha,但我很快意识到,所需的空间太简单了。所以,我写了一个程序,带了一个带有alpha的png,并创建了一个带有alpha蒙版的png文件和一个jpeg。这给我节省了大量的空间,但速度并不快。在Android应用程序中将ape应用于jpeg的更快方法?

以下是我的Android应用程序中的代码,它结合了jpg图像(代码中的origImgId)和png掩码(代码中的alphaImgId)。

虽然有效,但速度并不快。我已经缓存了结果,而且我正在研究在游戏开始之前将这些图像加载到菜单屏幕上的代码,但如果有办法加快这种速度,那将会很不错。

有没有人有任何建议?请注意,我稍微修改了代码以便易于理解。在游戏中,这实际上是一个精灵,它按需加载图像并缓存结果。在这里您只需看到加载图像和应用alpha的代码。

public class BitmapDrawableAlpha 
{ 
    public BitmapDrawableAlpha(int origImgId, int alphaImgId) { 
     this.origImgId = origImgId; 
     this.alphaImgId = alphaImgId; 
    } 

    protected BitmapDrawable loadDrawable(Activity a) { 
     Drawable d = a.getResources().getDrawable(origImgId); 
     Drawable da = a.getResources().getDrawable(alphaImgId); 

     Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(),d.getIntrinsicHeight(),Bitmap.Config.ARGB_8888); 
     { 
      Canvas c = new Canvas(b); 
      d.setBounds(0,0,d.getIntrinsicWidth()-1,d.getIntrinsicHeight()-1); 
      d.draw(c); 
     } 

     Bitmap ba = Bitmap.createBitmap(d.getIntrinsicWidth(),d.getIntrinsicHeight(),Bitmap.Config.ARGB_8888); 
     { 
      Canvas c = new Canvas(ba); 
      da.setBounds(0,0,d.getIntrinsicWidth()-1,d.getIntrinsicHeight()-1); 
      da.draw(c); 
     } 

     applyAlpha(b,ba); 

     return new BitmapDrawable(b); 
    } 

    /** Apply alpha to the specified bitmap b. */ 
    public static void applyAlpha(Bitmap b, Bitmap bAlpha) { 
     int w = b.getWidth(); 
     int h = b.getHeight(); 
     for(int y=0; y < h; ++y) { 
      for(int x=0; x < w; ++x) { 
       int pixel = b.getPixel(x,y); 
       int finalPixel = Color.argb(Color.alpha(bAlpha.getPixel(x,y)), Color.red(pixel), Color.green(pixel), Color.blue(pixel)); 
       b.setPixel(x,y,finalPixel); 
      } 
     } 
    } 

    private int origImgId; 
    private int alphaImgId; 
} 

回答

2

如果你想每多个像素被操纵,你可以打电话getPixels()setPixels(),让他们一下子。这会阻止循环中的其他方法调用和内存引用。

你可以做的另一件事是做像素添加按位或代替辅助方法。预防方法调用应该提高效率:

public static void applyAlpha(Bitmap b, Bitmap bAlpha) { 
    int w = b.getWidth(); 
    int h = b.getHeight(); 
    int[] colorPixels = new int[w*h]; 
    int[] alphaPixels = new int[w*h]; 
    b.getPixels(colorPixels, 0, w, 0, 0, w, h); 
    bAlpha.getPixels(alphaPixels, 0, w, 0, 0, w, h); 
    for(int j = 0; j < colorPixels.length;j++){ 
     colorPixels[j] = alphaPixels[j] | (0x00FFFFFF & colorPixels[j]); 
    } 
    b.setPixels(colorPixels, 0, w, 0, 0, w, h); 
} 

话虽这么说,你想承接过程相当简单,我无法想象这些将提供巨大的性能提升。从这一点来看,我可以提供的唯一建议是使用NDK实现本机实现。

编辑:此外,由于位图不必是可变的使用getPixels()getPixel()你可以BitmapFactory.decodeResource()获取alpha位图:

Bitmap ba = BitmapFactory.decodeResource(a.getResources(), alphaImgId); 
+0

哇!我没想到会得到这样一个完美的答案!我不知道你的答案的哪一部分有所不同,但是游戏级别的启动明显更快。我没有计算出差异,但我认为你从3秒或4秒的启动时间到1秒或2秒启动。谢谢! – HappyEngineer

+1

有趣的是,我没有预料到会有重大改进,所以我会好奇哪个部分做得最多。我认为这是'getPixels()'的使用,因为它是本地实现的。这或可能是因为循环运行时没有任何方法调用,JIT编译器可以对其执行更多优化。如果我以后得到时间,我会测试它并尝试弄清楚。 – Fr33dan

+0

那么考虑到肯定会发生一些不可思议的事情,我不认为我能够确定哪些因素会对变化产生最大的影响,但它引发了一个有趣的讨论:http://stackoverflow.com/questions/ 12240472/why-do-if-statement-inside-a-loop-slow-it-down-so-drastically – Fr33dan

相关问题