2013-03-21 13 views
5

Ho iniziato a codificare un programma di elaborazione di immagini da diversi algoritmi di elaborazione delle immagini, principalmente dal lavoro di René Schulte, e durante il benchmark ho notato che da tutti gli effetti che ho trovato da diverse fonti, il codice per applicare un effetto "Softlight" era il più lento. Non sono bravo nell'ottimizzare l'equazione, ma ritengo che il filtro sia basato su una formula che forse sta ripetendo variabili senza motivo.Questa formula è ripetitiva o ottimale

Questo potrebbe essere riassunto in qualcosa di più breve o più veloce?

// Basically, b is from Image A, and t from Image B 
int csoftLight(float b, float t) 
     { 
      b /= 255; 
      t /= 255; 

      return (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
     } 

[Edit - risultati utilizzando l'equazione Mohammed Hossain trovato circa softlight in PS]

// Input: 137 and 113 

// Byte version: 
int other = ((byte)((B < 128) ? (2 * ((A >> 1) + 64)) * ((float)B/255) : (255 - (2 * (255 - ((A >> 1) + 64)) * (float)(255 - B)/255)))); 
// Returns 116  


// float version: 
int res = (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
// Returns 129 

[Edit]

Ecco l'algoritmo più veloce basano su Mohammed Hossain risposta:

int csoftLight(byte A, byte B) 
{ 
    return (int)((A < 128) ? (2 * ((B >> 1) + 64)) * ((float)A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float)(255 - A)/255)));   
} 
+0

mi auguro che i compilatori farebbero eliminazione sottoespressione comune, ma quando floating il punto viene coinvolto ... – nneonneo

+0

E googling il nome del tizio che ha aggiunto questo codice alla fonte originale non restituisce nulla, finirò col chiamare il codificatore! –

+0

Le operazioni aritmetiche su float sono più costose che su numeri interi. cambiare i tipi di parametri in int, quindi posso fornire una soluzione. –

risposta

4

Questa risposta dovrebbe aiutarti e chiarire un po 'le cose: How does photoshop blend two images together?

Una delle equazioni è l'algoritmo a luce morbida.

#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255)))) //not very accurate 

Evita importante l'operazione radice quadrata costosa e meno importante utilizza operatori bit-spostamento in posizione di divisione per 2 (che dovrebbe essere ottimizzato distanza dai compilatori intelligenti, comunque). Utilizza anche più operazioni su interi rispetto alle operazioni mobili, che è più veloce.

Ecco un'altra formula (cortesia per i proprietari di this che commuta le operazioni del variabile, e funziona apparentemente ...

#define ChannelBlend_SoftLight(A,B) (uint8)(((A < 128) ? (2 * ((B >> 1) + 64)) * ((float) A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float) (255 - A)/255)))); 
+0

Wow, hai esattamente il contesto dell'equazione. Megaupvote! –

+0

Non so cosa sto facendo male, ma non restituisce l'immagine corretta: 'int csoftLight (byte A, byte B) { return ((byte) ((B <128)? (2 * ((A >> 1) + 64)) * ((float) B/255): (255 - (2 * (255 - ((A >> 1) + 64)) * (float) (255 - B)/255)))); } ' –

+1

È necessario chiamarlo per ogni canale del pixel; se lo fai in RGB, devi chiamarlo tre volte (R, G, B). Il prodotto finale è tre valori (R, G, B) che sono i tre canali del pixel di uscita. Lo stai facendo attualmente? –

Problemi correlati