2014-02-17 49 views
5

我最近注意到這些例外(被發現,但登錄logcat中):在新的Android 4.4警告

W/System.err(2612): java.lang.RuntimeException: Canvas: trying to use a non-premultiplied bitmap [email protected] 
W/System.err(2612): at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1088) 
W/System.err(2612): at android.graphics.Canvas.<init>(Canvas.java:139) 
System.err(2612): at com.example.imaging.ImageHelper.addShadow(ImageHelper.java:553) 

我試圖理解這是什麼異常的手段(以及非預乘的位圖) ,但我不確定可能會導致此異常。我們從服務器獲得的圖像是否存在問題,還是我們在本地進行的? (這不只是這條線導致異常,但它是其中之一)。

僅供參考,我在這裏補充問題的方法,並強調,導致異常的一個:

public static Bitmap addShadow(Bitmap bitmap) { 
    try { 
     BlurMaskFilter blurFilter = new BlurMaskFilter(12, BlurMaskFilter.Blur.OUTER); 
     Paint shadowPaint = new Paint(); 
     shadowPaint.setMaskFilter(blurFilter); 
     shadowPaint.setShadowLayer(12, -3, -3, Color.parseColor("#33000000")); 
     int[] offsetXY = new int[2]; 

     Bitmap shadowImage = bitmap.extractAlpha(shadowPaint, offsetXY); 
     Bitmap shadowImage32 = shadowImage.copy(Bitmap.Config.ARGB_8888, true); 

     Canvas c = new Canvas(shadowImage32); // exception occurs here <---- 
     c.drawBitmap(bitmap, -offsetXY[0], -offsetXY[1], null); 

     return shadowImage32; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return bitmap; // if error return the original bitmap 

} 
+0

我相信這有與具有獨特的alpha通道相比,將alpha預乘到顏色分量中,以更直接地(並因此有效地)與實際顯示實現兼容地生成格式。 –

+0

@ChrisStratton是否意味着我應該更改/重新轉換服務器上的圖像,還是應該修改addShadow函數? – ajacian81

+0

如果您能接受,在服務器上更改它們可能是運行時效率最高的解決方案。 –

回答

7

我現在面臨正是在完全相同的代碼相同的問題,但我需要在Android代碼中解決這個問題,而不是在應用程序外改變圖像,因爲我使用從用戶設備加載的圖像。

什麼我發現是下面的,只是帆布呼叫前:

// Fix the non pre-multiplied state. 
if (!shadowImage32.isPremultiplied()) 
{ 
    shadowImage32.setPremultiplied(true); 
} 

這裏的問題是,我的分API度爲10,和isPremultiplied()需要API 17 setPremultiplied(真)需要API 19.

編輯:我使用的設備具有API 10測試,不存在這樣的異常,所以我想在API 19它們引入d預乘處理和異常。所以,最後,我的代碼有幾行:

// Fix the non pre-multiplied exception for API 19+. 
if (android.os.Build.VERSION.SDK_INT >= 19 && !shadowImage32.isPremultiplied()) 
{ 
    shadowImage32.setPremultiplied(true); 
} 
3

參考哈維的回答,用一種非常古老的代碼,我稱這種方法(以支持新的設備)與反思:

if (android.os.Build.VERSION.SDK_INT >= 19) 
      { 
       try { 
        java.lang.reflect.Method method = shadowImage32.getClass().getMethod("setPremultiplied",boolean.class); 
        method.invoke(shadowImage32, true); 
       } catch (Exception e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      }