2012-09-02 2 views
1

알파가 필요한 객체에 대해 png 파일을 사용하여 안드로이드 응용 프로그램을 시작했지만 필요한 공간이 너무 많다는 것을 빨리 알게되었습니다. 그래서, 나는 알파와 함께 png를 취한 프로그램을 작성했고 & 알파 마스크 png 파일과 jpeg를 만들었습니다. 이것은 엄청난 양의 공간을 절약 해 주지만 속도는 그리 좋지 않습니다.안드로이드 앱에서 jpeg에 알파를 적용하는 더 빠른 방법은 무엇입니까?

다음은 jpg 이미지 (코드의 origImgId)와 png 마스크 (코드의 alphaImgId)를 결합한 Android 앱의 코드입니다.

작동하지만 빠른 것은 아닙니다. 이미 결과를 캐싱하고 게임을 시작하기 전에 메뉴 화면에 이러한 이미지를로드하는 코드를 작성하고 있지만 속도를 높이는 방법이 있으면 좋을 것입니다.

누구에게 의견이 있습니까? 코드를 쉽게 이해할 수 있도록 약간 수정했습니다. 게임에서 이것은 실제로 요청에 따라 이미지를로드하고 결과를 캐시하는 스프라이트입니다. 여기서 이미지를로드하고 알파를 적용하는 코드를 볼 수 있습니다. 당신은 모든 여러 픽셀을 조작 할하려는 경우

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()와 알파 비트 맵을 얻을 수 있습니다 :

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

와우! 나는 완벽한 완벽한 대답을 기대하지 않았다! 나는 당신의 대답 중 어떤 부분이 차이를 만들 었는지 모르지만, 게임 레벨은 인식 할 수 없을 정도로 빨리 시작됩니다. 차이점은 시간을 잰 적이 없지만 3 ~ 4 초 시동에서 1 ~ 2 초 시동으로 전환했다고 생각합니다. 감사! – HappyEngineer

+1

재미있는 점은 어떤 부분이 가장 잘했는지 궁금 할 정도로 중요한 개선이 기대되는 것이 아니 었습니다. 내 생각에 그것은'getPixels()'이 기본적으로 구현 되었기 때문에 사용하는 것입니다. 루프가 JIT 컴파일러를 호출하지 않고 실행되기 때문에 JIT 컴파일러가 더 많은 최적화를 수행 할 수 있습니다. 나중에 시간을 얻으면 나는 그것을 시험해보고 시도해 볼 것입니다. – Fr33dan

+0

잘 주어진 거기에 분명히 어떤 우승이 최적화와 함께 일어난 나는 가장 큰 변화에 기여 결정할 수있을 것이라고 생각하지 않지만, 여기에 흥미로운 disscussion을 산란 : http://stackoverflow.com/questions/ 12240472/why-does-if-if-statement-inside-a-loop-slow-it-down-so-drastically – Fr33dan

관련 문제