2013-01-17 414 views
15

我有一個定製的View,它總是在某個旋轉時繪製一個Bitmap。我覆蓋onDraw方法,旋轉Canvas並用反鋸齒Paint繪製位圖。位圖未繪製消除鋸齒

public RotatedImageView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    someBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.placeholder); 
} 

@Override 
protected void onDraw(Canvas canvas) { 

    // Save and rotate canvas 
    canvas.save(); 
    canvas.rotate(3F, getWidth()/2, getHeight()); 

    // Draw the icon 
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); 
    canvas.drawBitmap(someBitmap, 0, 0, p); 
    canvas.drawRoundRect(new RectF(75, 50, 225, 200), 10, 10, p); 

    // All done; restore canvas 
    canvas.restore(); 
} 

但是,我總是在位圖上看到鋸齒狀的邊緣。請注意,粗糙的矩形可以很好地消除鋸齒邊緣。此外,當我應用p.setFilterBitmap(true);這個工程(位圖表面得到過濾/平滑)正確。我錯過了什麼嗎?

No anti-aliasing on the photo

這裏有一個最小的Android項目與一個畫面的孤立的例子,顯示繪製非反鋸齒位圖的角度,從資源加載:https://bitbucket.org/erickok/antialiastest

更新:我有也試過如下:

Paint p = new Paint(); 
    p.setAntiAlias(true); 
    p.setFilterBitmap(true); 
    p.setDither(true); 
    canvas.drawBitmap(someBitmap, 0, 0, p); 

但是,這並不利於爲setFilterBitmap過濾表面;它不會抵消邊緣。另外,setAntiAlias與在Paint構造函數中直接設置標誌的做法相同。如果有疑問,請嘗試我最小的測試項目。非常感謝您的幫助!

回答

17

我發現爲什麼我沒有得到任何抗鋸齒:硬件加速。在我(通過純粹的事故)在我的Nexus One上測試後,它突然運行,而我的Nexus 7沒有。結果ANTI_ALIAS_FLAGCanvas使用硬件加速繪製時什麼都不做。有了這種見解,我發現了Romain Guy's answer on StackOverflow這回答了我的問題。

解決方案似乎是:爲每個位圖添加一個透明邊框(手動或即時)或「用着色器做某事」。這對我來說也不是很吸引人。在我的自定義視圖上使用setLayerType方法取代disabled hardware acceleration。請注意,這是API級別11後可用的,但(不是偶然),您不必在任何方式之前處理硬件加速。所以我加入,在視圖中的構造函數:

if (android.os.Build.VERSION.SDK_INT >= 11) { 
     setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
    } 

我已經更新到位桶對於那些有興趣在上面提到的開源項目。

6

在我來說,我這樣做,但可能是它喜歡你做的事:

Paint paint = new Paint(); 
paint.setAntiAlias(true); 

試試看。

祝你好運!

+0

感謝您的回覆。這等於我不幸的,所以它具有相同的效果(或者說,對鋸齒狀邊緣沒有影響)。 –

18

使用setFilterBitmap(true)。

paint_object.setFilterBitmap(true); 

工作對我來說太.. 我是從這個問題

Drawing rotated bitmap with anti alias

消除鋸齒標誌和FilterBitmap標誌設置爲true兩者又一同做位圖的邊緣平滑,我已經在三星Galaxy Ace,android 2.2上測試過它...

我的測試代碼是

Paint p = new Paint(); 
p.setAntiAlias(true); 
p.setFilterBitmap(true); 
canvas.drawBitmap(someBitmap, new Matrix(), p); 
+0

對不起,但沒有。過濾位圖會平滑圖像的內容表面。它不會螞蟻化邊緣。我已更新我的問題以反映這一點。 –

+0

'setFilterBitmap()'結合'setLayerType(View.LAYER_TYPE_SOFTWARE,null)'實際上對我很好。僅憑軟件層,我仍然有一些文物。 – Brian

3

我測試了以前的建議,他們爲我工作。也許問題出在你的位圖上?也許在你的設備?這裏是創建位圖內聯的代碼。檢查這個例子是否適合你。

public class BitmapRotateActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(new MyView(this)); 
    } 
    class MyView extends View { 

    Bitmap bitmap; 
    public MyView(Context context) { 
     super(context); 

     bitmap = Bitmap.createBitmap(160, 160, Bitmap.Config.RGB_565); 
     Paint p = new Paint(); 
     p.setColor(Color.RED); 
     p.setStyle(Paint.Style.FILL); 
     Canvas c = new Canvas(bitmap); 
     c.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), p); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     Paint pbg = new Paint(); 
     pbg.setStyle(Paint.Style.FILL); 
     pbg.setColor(0xffe0e0ff); 
     canvas.drawRect(0, 0, getWidth(), getHeight(), pbg); 

     Paint p = new Paint(); 
     p.setAntiAlias(true); 
     p.setFilterBitmap(true); 

     canvas.save(); 
     canvas.rotate(3F, getWidth()/2, getHeight()/2); 
     canvas.drawBitmap(bitmap, 30, 30, p); 
     canvas.restore(); 
    } 
    } 
} 
+0

雖然你的回答並沒有直接回答我的問題,但評論'也許在你的設備上?' (並在我的Nexus One上進行測試)讓我走上了正確的道路,所以我會獎勵你的賞金。謝謝(全部)你的時間!作爲@ eric-kok –

2

我有同樣的問題,並嘗試所有這些修復。什麼終於摸索被禁止全局在AndroidManifest.xml文件中的硬件加速:

<application 
     android:hardwareAccelerated="false" 
    ... 
> 

,然後禁用inSampleSize當我裝我的形象的位圖,讓(我相信)的圖像將在足夠高的質量加載,以避免任何之字形,然後,對於我的實際ImageView,使用上述建議:將圖層類型設置爲View.LAYER_TYPE_SOFTWARE,並使用濾鏡位圖設置爲true(如上所示)和抗鋸齒功能的繪畫對象。

+0

表示:禁用它的customview足夠了......你可能不會減慢整個應用程序 – martyglaubitz