2013-01-17 10 views
15

Ich habe eine benutzerdefinierte View, die immer eine Bitmap bei einer bestimmten Rotation zeichnet. Ich überschreibe die onDraw Methode, rotiere die Canvas und zeichne die Bitmap mit einem Anti-Aliased Paint.Bitmap nicht gezeichnet Anti-Aliasing

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(); 
} 

Allerdings habe ich immer gezackten Kanten auf der Bitmap. Beachten Sie, dass das roudned-Rechteck Kanten mit Anti-Aliasing erhält. Auch wenn ich p.setFilterBitmap(true); anwende, funktioniert das korrekt (die Bitmap-Oberfläche wird gefiltert/geglättet). Fehle ich etwas?

No anti-aliasing on the photo

Hier ist ein minimal Android-Projekt mit isoliertem Beispiel eines Bildschirms, der die Ansicht zeigt, dass das Nicht-Anti-Aliasing-Bitmap zeichnet, aus einer Ressource geladen: https://bitbucket.org/erickok/antialiastest

UPDATE: Ich habe auch versucht, die folgenden:

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

Aber diese Hilfe nicht als setFilterBitmap die Oberfläche filtert; Die Kanten werden nicht anti-aliasiert. Auch setAntiAlias macht dasselbe wie das Setzen des Flags im Paint Konstruktor direkt. Im Zweifelsfall versuche bitte mein minimales Testprojekt. Vielen Dank für jede Hilfe!

Antwort

17

Ich habe gefunden, warum ich kein Anti-Aliasing bekommen habe: Hardware-Beschleunigung. Nachdem ich (rein zufällig) auf meinem Nexus One getestet hatte, funktionierte es plötzlich, während mein Nexus 7 nicht funktionierte. Stellt sich heraus, dass die ANTI_ALIAS_FLAG nichts tut, wenn die Canvas mit der Hardwarebeschleunigung gezeichnet wird. Mit dieser Einsicht fand ich Romain Guy's answer on StackOverflow, die meine Frage beantwortet.

Lösungen scheinen zu sein: Hinzufügen eines transparenten Rahmens zu jeder Bitmap (manuell oder im laufenden Betrieb) oder "etwas mit Shadern machen".Beides gefällt mir nicht sehr. Stattdessen ich disabled hardware acceleration auf meine benutzerdefinierte Ansicht mit der setLayerType Methode. Beachten Sie, dass dies seit der API-Stufe 11 verfügbar ist, aber (nicht zufällig) müssen Sie sich vorher nicht mit der Hardwarebeschleunigung befassen. So habe ich hinzugefügt, in der Ansicht Konstruktor:

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

I aktualisiert habe das oben genannte Open-Source-Projekt auf BitBucket für die Interessenten.

6

In meinem Fall habe ich das, aber sein kann, mag es Sie tat:

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

Versuche mal.

Viel Glück!

+0

Danke für die Antwort. Das ist gleich dem, was ich leider gemacht habe, also hat es den gleichen Effekt (oder eher keinen Effekt auf die gezackten Kanten). –

18

Verwenden Sie setFilterBitmap (true).

paint_object.setFilterBitmap(true); 

es auch für mich funktioniert .. Ich habe es von dieser Frage

Drawing rotated bitmap with anti alias

Satz sowohl die Antialias Flagge und FilterBitmap Flagge auf true setzen, werden sie zusammen Bitmap machen Kanten glatt, ich habe es auf Samsung Galaxy Ace, Android 2.2 getestet ...

Mein Testing Code ist

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

Sorry, aber nein. Das Filtern einer Bitmap glättet die Inhaltsoberfläche eines Bildes. Es altert nicht die Kanten. Ich habe meine Frage aktualisiert, um dies zu berücksichtigen. –

+0

'setFilterBitmap()' in Kombination mit 'setLayerType (View.LAYER_TYPE_SOFTWARE, null)' funktioniert tatsächlich sehr gut für mich. Mit der Software-Ebene allein hatte ich noch einige Artefakte. – Brian

3

Ich habe die vorherigen Vorschläge getestet und sie funktionieren für mich. Vielleicht ist das Problem in Ihrer Bitmap? Vielleicht in deinem Gerät? Hier ist ein Code, der das Bitmap inline erstellt. Überprüfen Sie, ob dieses Beispiel für Sie funktioniert.

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

Obwohl Ihre Antwort nicht direkt meine Frage beantwortet, die Bemerkung "Vielleicht in Ihrem Gerät?" (und das Testen meines Nexus One) habe mich auf den richtigen Weg gebracht, also werde ich dir das Kopfgeld geben. Danke für (alle) Zeit! –

2

Ich hatte das gleiche Problem und versuchte alle diese Fixes. Was schließlich wird weltweit gearbeitet Hardware-Beschleunigung in der AndroidManifest.xml Datei zu deaktivieren:

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

und dann deaktivieren inSampleSize, wenn ich mein Bild Bitmap geladen, so dass (ich nehme an) das Bild mit einer ausreichend hohen Qualität laden würde zu vermeiden alle Zickzacks und dann für meine eigentliche ImageView den obigen Hinweis verwenden: den Layer-Typ auf View.LAYER_TYPE_SOFTWARE setzen, mit einem Paint-Objekt, bei dem die Filter-Bitmap auf "True" (wie oben) und "Anti-Aliasing" gesetzt ist.

+0

as @ eric-kok angegeben: es für die customview deaktivieren ist genug ... Sie werden wahrscheinlich nicht die gesamte App verlangsamen – martyglaubitz

Verwandte Themen