2015-09-26 26 views
8

Dato un'immagine con canale alfa (trasparenza) Vorrei rimuovere qualsiasi spazio vuoto tra i contorni dell'immagine e l'immagine reale. Questo dovrebbe essere fatto in un task backgound o con una schermata di caricamento, con un tempo di esecuzione accettabile per non paralizzare l'esperienza dell'utente.Come rimuovere uno spazio vuoto attorno ad un'immagine in Android?

enter image description here

Come posso ottenere questo risultato?

risposta

17

Ho avuto difficoltà a trovare le migliori pratiche o anche i consigli per risolvere il mio problema. Basato su this anwer by JannGabriel, che ritaglia l'immagine in basso e a destra riducendo la dimensione dell'immagine, sono riuscito a fare un ulteriore passo avanti e anche a rimuovere gli spazi vuoti in alto e a sinistra, e in generale a migliorare i tempi di elaborazione. Il risultato è buono, e attualmente lo sto usando nel mio progetto. Sono abbastanza nuovo per la programmazione Android e qualsiasi consiglio su questo metodo è il benvenuto.

public static Bitmap TrimBitmap(Bitmap bmp) { 
    int imgHeight = bmp.getHeight(); 
    int imgWidth = bmp.getWidth(); 


    //TRIM WIDTH - LEFT 
    int startWidth = 0; 
    for(int x = 0; x < imgWidth; x++) { 
     if (startWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 


    //TRIM WIDTH - RIGHT 
    int endWidth = 0; 
    for(int x = imgWidth - 1; x >= 0; x--) { 
     if (endWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - TOP 
    int startHeight = 0; 
    for(int y = 0; y < imgHeight; y++) { 
     if (startHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - BOTTOM 
    int endHeight = 0; 
    for(int y = imgHeight - 1; y >= 0; y--) { 
     if (endHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 


    return Bitmap.createBitmap(
      bmp, 
      startWidth, 
      startHeight, 
      endWidth - startWidth, 
      endHeight - startHeight 
    ); 

} 

Spiegazione: Per ogni lato dell'immagine, un ciclo FOR viene eseguito per verificare se pixel non contiene il colore trasparente, restituendo il primo pixel non trasparente utile coordinate. Questo viene fatto elaborando le coordinate usando come base la dimensione opposta rispetto alla dimensione da tagliare: per trovare y, scansionare x per ogni y.

Per controllare dove finisce lo spazio vuoto verticale-Top, esegue le seguenti operazioni:

  1. partenza è dalla prima riga (y = 0)
  2. controlla tutte le colonne della riga (x da 0 a imageWidth)
  3. Se viene trovato un pixel non trasparente, interrompere il ciclo e salvare la coordinata y. Altrimenti continua.
  4. Alla fine delle colonne, passare alla riga successiva (y + 1) e iniziare a controllare le colonne nuovamente. Interrompi se è già stato trovato un pixel non trasparente.

Per le altre dimensioni vengono utilizzati metodi simili, cambiando solo la direzione della scansione.

Una volta ottenuti i 4 coordinate dei primi pixel utili dell'immagine, il metodo Bitmap.createBitmap viene richiamato con il bitmap originale come un'immagine di base, e coordina i pixel utili come alto a sinistra e limiti inferiore destro per il ridimensionamento .

Nota 1: E 'utile notare che le coordinate 0, 0 equivale a alto a sinistra.

Nota 2: La larghezza e l'altezza finali in Bitmap.createBitmap vengono ridotte dalla nuova coordinata relativa iniziale, altrimenti la nuova immagine avrà i limiti erroneamente spinti in basso a destra. Figura in questo modo: hai un'immagine 100x100px, quindi con coordinate finali 100.100. Cambiando le coordinate iniziali a 50,50, le coordinate finali del rettangolo di elaborazione verranno portate a 150,150 (100 coordinate originali + 50 del punto iniziale modificato), spingendole oltre i limiti dell'immagine originale. Per evitare ciò, la nuova coordinata finale viene ridotta dalla nuova coordinata iniziale (100 + 50 nuovo coord iniziale - 50 nuova regolazione iniziale coord)

Nota 3: nella risposta originale, un controllo per tutti i pixel in un dato la direzione viene eseguita utilizzando la stessa dimensione della coordinata per trovare, restituendo il pixel utile più avanzato.Controllare la dimensione opposta e fermarsi al primo pixel utile ha aumentato le prestazioni.

+1

Il codice di esempio ridurrà almeno un pixel, anche se l'immagine non ha una colonna o riga trasparente. È meglio usare il modo descritto in 'http: // stackoverflow.com/a/886979/1043882' invece di' if (startWidth == 0) 'e altre dichiarazioni simili. – hasanghaforian

+0

'startWidth' e' startHeight' non dovrebbero essere impostati su 0 inizialmente, perché se la tua immagine non ha spazio vuoto in alto ea sinistra i tuoi cappi for-loop verranno eseguiti fino alla fine. Quindi perderai tempo di calcolo pari a "2 * larghezza * altezza". Penso sia meglio impostarli su '-1'. – Ruslan