2009-11-12 15 views
6

In generale, l'equazione metodo di fusione "normale" si presenta come segue:modalità di miscelatura su uno sfondo trasparente e semitrasparente

D = Sa * S + D * (1.0 - Sa) 

dove D è colore destinazione, Sa è alfa sorgente e S è il colore di origine.

Ora, questo funziona perfettamente con una destinazione completamente opaca, ma mi piacerebbe sapere come gestirlo con una destinazione semi e completamente trasparente.

Quando si configura la sorgente su una destinazione completamente trasparente, il pixel di origine (un pixel che è colore e alfa) rimarrà invariato e non si mescolerà come nell'equazione precedente, e se lo sfondo di destinazione è completamente opaco, l'equazione di cui sopra dovrebbe essere applicato, ma non riesco a trovare un buon modo per gestire le situazioni in cui l'alpha di destinazione è tra 0 e 1.

Ad esempio, se si fonde un pixel bianco con 50% di alpha su uno sfondo trasparente, il colore non dovrebbe tendere a quel valore di colore trasparente (che è più o meno in uno stato indefinito), il colore di destinazione dovrebbe essere bianco pieno e non 50% (dopo la moltiplicazione alfa), che è ciò che si ottiene dopo aver applicato l'equazione precedente (se D è fatto dello stesso colore di S, che era qualcosa che io ght of).

risposta

7

Questa equazione è una semplificazione dell'equazione generale di miscelazione. Presume che il colore di destinazione sia opaco e quindi abbandoni il termine alfa del colore di destinazione.

D = C1 * C1a + C2 * C2a * (1 - C1a) 

dove D è il colore risultante, C1 è il colore del primo elemento, C1a è l'alfa del primo elemento, C2 è il secondo colore elemento, C2a è l'alfa del secondo elemento. L'alfa destinazione viene calcolato con:

Da = C1a + C2a * (1 - C1a) 

il colore risultante viene premoltiplicato con l'alfa. Per ripristinare il colore ai valori non moltiplicati, basta dividere per Da, l'alfa risultante.

+0

Questo non funziona. Ad esempio, se il colore di destinazione è nero e il colore di origine è bianco. L'alfa di destinazione è 0 e l'alfa di origine è 0,5, quindi si finisce con D = 1,0 * 0,5 + 0,0 * 0,0 * (1,0 - 0,5) che è 1,0 * 0,5 con è uguale moltiplicando il colore sorgente con il suo alfa. Questo non è quello che voglio, mi piacerebbe che il colore sorgente non fosse toccato se l'alpha di destinazione è 0. –

+0

Ecco come funziona questa modalità di fusione.Avrai bisogno di una diversa modalità di fusione se vuoi un comportamento diverso. Ci sono una gran quantità di altri metodi di fusione. C'è una buona lista su http://illusions.hu/effectwiki/doku.php?id=list_of_blendings –

+2

Inoltre, il colore risultante è premoltiplicato dall'alfa. È possibile ripristinare i colori non compensati dividendo i colori risultanti per l'alfa risultante. Il che, a mio avviso, è ciò che penso che tu voglia. –

0

La maggior parte delle formule di fusione vengono utilizzate su immagini statiche in cui non viene memorizzato l'alfa colori di destinazione. Se l'alpha è disponibile, l'alpha finale sarà semplicemente lo arithmetic mean dell'alfa di origine e l'alpha di destinazione.

È possibile calcolare l'alfa medio e quindi utilizzarlo semplicemente nella posizione di "Sa" nella formula.

La mente ci dice a cosa serve?

+0

Il calcolo dell'alfa di destinazione non è un problema, è il colore che pone un problema. È per unire 1 immagine semitrasparente su una seconda immagine semitrasparente e salvare il risultato in un file PNG con trasparenza. In Photoshop posso farlo caricando le due immagini, unendo i due livelli e salvando in un PNG. –

+0

Non riesco ancora a capire perché la media dei canali alfa non produce il colore corretto? – tplaner

1

Ho trovato questo answer essere utile e sembra funzionare come previsto quando si applica la stessa formula al canale alfa.

Altered qui per mostrare la versione estesa:

int blend(unsigned char result[4], unsigned char fg[4], unsigned char bg[4] { 
    unsigned int alpha = fg[3] + 1; 
    unsigned int inv_alpha = 256 - fg[3]; 
    result[0] = (unsigned char)((alpha * fg[0] + inv_alpha * bg[0]) >> 8); 
    result[1] = (unsigned char)((alpha * fg[1] + inv_alpha * bg[1]) >> 8); 
    result[2] = (unsigned char)((alpha * fg[2] + inv_alpha * bg[2]) >> 8); 
    result[3] = (unsigned char)((alpha * fg[3] + inv_alpha * bg[3]) >> 8); 
    // result[3] = 0xff; 
} 

Questo funziona bene per il codice rapido e sporco, ma ci sono metodi più veloci e, come commentato nella risposta di cui sopra, ma anche affrontato here e here.