2017-10-18 6 views
2

Laden Sie ein 32-Bit-Bild in einen Puffer und ich multipremiere dann die Farbwerte mit dem entsprechenden Alpha zum Mischen.Multiplizieren von Bild Alpha effizient

Das Folgende funktioniert, aber ich frage mich, ob es eine effizientere Möglichkeit gibt, dies zu tun, auch wenn es nur zu einer guten Approximation führt?

Bilddaten ist ein Zeiger dieses Typs:

typedef struct rgba_pixel 
{ 
    uint8_t r; 
    uint8_t g; 
    uint8_t b; 
    uint8_t a; 
} rgba_pixel; 

rgba_pixel * image_data; 

for (i = 0; i < length; i++) 
{ 
    if (image_data[i].a == 0) 
     image_data[i].r = image_data[i].g = image_data[i].b = 0; 
    else if (image_data[i].a < 255) 
    { 
     alpha_factor = image_data[i].a/255.0; 
     image_data[i].r = image_data[i].r * alpha_factor; 
     image_data[i].g = image_data[i].g * alpha_factor; 
     image_data[i].b = image_data[i].b * alpha_factor; 
    } 
} 
+1

Können Sie die Definition der Typen image_data und alpha_factor anzeigen? –

+0

zur Definition hinzugefügt, alpha_factor ist ein Double. – phenompbg

Antwort

3

Da Ihr a, r, g und b Komponenten unsigned char sind, können Sie die Leistung verbessern, indem Gleitkomma-Multiplikation drehen Multiplikation auf ganzzahlige und verwenden shr 8 (Division durch 256) anstatt durch dividieren durch 255:

for (i = 0; i < length; i++) 
{ 
    if (image_data[i].a == 0) 
     image_data[i].r = image_data[i].g = image_data[i].b = 0; 
    else if (image_data[i].a < 255) 
    { 
     image_data[i].r = (unsigned short)image_data[i].r * image_data[i].a >> 8; 
     image_data[i].g = (unsigned short)image_data[i].g * image_data[i].a >> 8; 
     image_data[i].b = (unsigned short)image_data[i].b * image_data[i].a >> 8; 
    } 
} 

Dies wird 1 fp Division und 3 fp multipli konvertieren Kationen in 3 ganzzahlige Multiplikationen und 3 Bit-Verschiebungen.

Eine weitere Verbesserung, die Vereinigung Struktur für die Pixeldaten durchgeführt werden kann, wird unter Verwendung von: sofort

typedef union rgba_pixel 
{ 
    struct { 
     uint8_t r; 
     uint8_t g; 
     uint8_t b; 
     uint8_t a; 
    }; 

    uint32_t u32; 
} rgba_pixel; 

Und dann die Zuordnung Null r, g und b:

//image_data[i].r = image_data[i].g = image_data[i].b = 0; 
image_data[i].u32 = 0; //use this instead 

mit nach https://godbolt.org/x86-64 gcc 7.2, letztere generiert weniger Anweisungen bei -O3. Was natürlich in der Praxis schneller sein kann oder nicht.

Eine andere Sache, die zu berücksichtigen ist, ist das teilweise Schleifen-Abrollverfahren, d. H. Das Verarbeiten von mehreren (zum Beispiel 4) Pixeln pro Schleifeniteration. Wenn Sie garantieren, dass Ihre Zeilen ein Vielfaches von 4 in der Breite sind, tun Sie es auch ohne zusätzliche Prüfungen.

+0

Vielen Dank, ich gebe das eine Chance – phenompbg

+0

Das else wenn etwas zu vermeiden ist, wenn das Alpha 255 ist, dh. alpha_factor wird 1.0 – phenompbg

+0

Oh ja, mein Fehler. Auch habe ich einige zusätzliche Gedanken hinzugefügt. –

Verwandte Themen