2013-01-17 8 views
15

Ho una personalizzazione View che disegna sempre un Bitmap a una determinata rotazione. Sovrascrivo il metodo onDraw, ruoto lo Canvas e disegno la bitmap con un anti-aliasing Paint.Bitmap non disegnata 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(); 
} 

Tuttavia, ottengo sempre bordi frastagliati sulla bitmap. Si noti che il rettangolo roudned ottiene bordi con anti-aliasing. Inoltre, quando applico lo p.setFilterBitmap(true); questo funziona (la superficie bitmap viene filtrata/levigata) correttamente. Mi sto perdendo qualcosa?

No anti-aliasing on the photo

Ecco un progetto Android minimo con isolato esempio di uno schermo che mostra la vista che disegna il bitmap non-anti-aliasing, caricati da una risorsa: https://bitbucket.org/erickok/antialiastest

UPDATE: Ho anche provato il seguente:

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

Ma questo non aiuta come setFilterBitmap filtri superficie; non ha anti-alias i bordi. Inoltre, setAntiAlias equivale all'impostazione diretta del flag nel costruttore Paint. In caso di dubbio, prova il mio progetto di prova minimo. Grazie mille per qualsiasi aiuto!

risposta

17

Ho trovato il motivo per cui non ho ricevuto alcun anti-alias: accelerazione hardware. Dopo che ho provato (per puro caso) sul mio Nexus One, improvvisamente ha funzionato, mentre il mio Nexus 7 no. Risulta che il ANTI_ALIAS_FLAG non fa nulla quando il Canvas viene disegnato utilizzando l'accelerazione hardware. Con questa intuizione ho trovato Romain Guy's answer on StackOverflow che risponde alla mia domanda.

Le soluzioni sembrano essere: aggiungere un bordo trasparente a ogni bitmap (manualmente o al volo) o "fare qualcosa con gli shader".Neanche mi piacciono molto. Invece ho disabled hardware acceleration sulla mia visualizzazione personalizzata utilizzando il metodo setLayerType. Nota che questo è disponibile dal livello API 11, ma (non per caso) non dovrai affrontare l'accelerazione hardware prima di alcuno dei modi. Così ho aggiunto, nel costruttore vista:

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

Ho aggiornato quanto sopra si fa riferimento progetto open-source sul BitBucket per chi è interessato.

6

Nel mio caso ho fatto questo, ma può essere che vuole che hai fatto:

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

Basta provare.

Buona fortuna!

+0

Grazie per la risposta. Questo è uguale a quello che ho fatto sfortunatamente, quindi ha lo stesso effetto (o meglio, nessun effetto sui bordi frastagliati). –

18

Utilizzare setFilterBitmap (true).

paint_object.setFilterBitmap(true); 

funziona anche per me .. ho presa da questa domanda

Drawing rotated bitmap with anti alias

insieme sia il AntiAlias ​​ bandiera e FilterBitmap bandiera per vero, che insieme mettono a bitmap di bordi lisci, l'ho provato su Samsung Galaxy Ace, Android 2.2 ...

Il mio codice di prova è

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

Siamo spiacenti, ma no. Il filtraggio di una bitmap attenua la superficie del contenuto di un'immagine. Non fa antialiasing i bordi. Ho aggiornato la mia domanda per riflettere questo. –

+0

'setFilterBitmap()' in combinazione con 'setLayerType (View.LAYER_TYPE_SOFTWARE, null)' funziona davvero molto bene per me. Con il solo strato del software avevo ancora alcuni artefatti. – Brian

3

Ho testato i suggerimenti precedenti e funzionano per me. Forse i problemi sono nella tua bitmap? Forse nel tuo dispositivo? Ecco un codice che crea la bitmap in linea. Controlla se questo esempio funziona per te.

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

Sebbene la risposta non abbia risposto direttamente alla mia domanda, l'osservazione "Forse nel dispositivo?" (e testando accidentalmente il mio Nexus One) mi ha messo sulla strada giusta, quindi ti assegnerò la taglia. Grazie per tutto il tuo tempo! –

2

Ho avuto lo stesso problema, e provato tutte queste correzioni. Che fine ha funzionato è la disabilitazione a livello globale l'accelerazione hardware nel file AndroidManifest.xml:

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

e poi disattivando inSampleSize quando ho caricato la mia immagine bitmap, in modo che (presumo) l'immagine caricherebbe a una qualità sufficientemente elevata per evitare qualsiasi zigzag, e poi, per il mio attuale ImageView, usando il consiglio precedente: impostando il tipo di livello su View.LAYER_TYPE_SOFTWARE, con un oggetto paint con il filtro bitmap impostato su true (come sopra) e anti-aliasing attivo.

+0

come dichiarato @ eric-kok: disabilitarlo per la customview è sufficiente ... probabilmente non rallenterai l'intera app – martyglaubitz