2009-10-17 10 views
5

Ich habe einen DWORD (unsigned long) RGBA zu vier int konvertieren Vars (R, G, B und A) Bisher habe ich diese Funktion die 4 ints auf einen DWORD konvertieren:Wie kann ich von DWORD RGBA in Ints konvertieren?

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA) 
{ 
    return ((iA << 24) | (iR << 16) | (iG << 8) | iB); 
} 

Wie kann ich es zurück konvertieren?

So etwas wie

struct RGBA 
{ 
    int R, G, B, A; 
}; 

RGBA DWORD2RGBA(unsigned long dwColor) 
{ 
    static RGBA tmp; 
    //.......conversion process 
    return tmp; 
} 

Jede Art von Hilfe geschätzt! :)

Dank

+1

Wahrscheinlich nur ein Tippfehler, aber Sie müssen '|' Operator in der Verpackungsfunktion verwenden, nicht '||'. – AnT

+5

Warum wird Ihr 'tmp' als 'statisch' deklariert? Wollten Sie einen Zeiger zurückgeben? – AnT

+0

Manchmal habe ich eine Compiler-Warnung erhalten, wenn ich eine in einer Funktion deklarierte Variable zurückgebe. Also habe ich es als statisch erklärt um die Warnung zu verhindern ..? Nein? –

Antwort

9

Wenn ich Sie wäre, ich mit multiplikativen-additive Operationen in der Packen/Entpacken Funktionen bleiben würde. So etwas wie diese

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA) 
{   
    return ((iA * 256 + iR) * 256 + iG) * 256 + iB; 
} 

mit einer symmetrischen auspacken Funktion

RGBA DWORD2RGBA(unsigned long dwColor) 
{   
    RGBA tmp; /* why did you declare it static??? */ 

    tmp.B = dwColor % 256; dwColor /= 256; 
    tmp.G = dwColor % 256; dwColor /= 256; 
    tmp.R = dwColor % 256; dwColor /= 256; 
    tmp.A = dwColor % 256; /* dwColor /= 256; */ 

    return tmp; 
} 

Beachten Sie, dass es in dem gesamten Code nur eine „magische Konstante“ ist.

Natürlich, wenn Sie eine externe Spezifikation haben, die in Bitmuster in den gepackten Daten geschrieben wird, kann eine Version basierend auf Bit und Schichtoperationen vorzuziehen sein. Immer noch

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA) 
{   
    return (((((iA << 8) + iR) << 8) + iG) << 8) + iB; 
} 

RGBA DWORD2RGBA(unsigned long dwColor) 
{   
    RGBA tmp; /* why did you declare it static??? */ 

    tmp.B = dwColor & 0xFF; dwColor >>= 8; 
    tmp.G = dwColor & 0xFF; dwColor >>= 8; 
    tmp.R = dwColor & 0xFF; dwColor >>= 8; 
    tmp.A = dwColor & 0xFF; /* dwColor >>= 8; */ 

    return tmp; 
} 

hat viel weniger "magische Konstanten".

Jetzt können Sie die Wiederholungsaktionen/Teilausdrücke in Makros oder besser Inline-Funktionen einbinden und zu einem sehr kompakten und lesbaren Packer/Entpacker gelangen.

+1

@Alex: Huh? Nein. Es gibt absolut keinen Unterschied zwischen dem Leistungsprinzip und dieser anderen arithmetischen Lösung, die bisher angeboten wurde. Wo hast du die Performance-Probleme gefunden, sorgst du um die Ausarbeitung? – AnT

+0

Im Gegenteil, dies ist wohl die bisher effizienteste Lösung, da der Compiler die einzige (oder zwei) "magische Konstante" im Register speichern kann. Die Lösungen mit mehreren "magischen Konstanten" werden den Compiler höchstwahrscheinlich zwingen, Maschinenbefehle mit eingebetteten Operanden zu erzeugen, was in Bezug auf die Leistung merklich schlechter ist. – AnT

+0

Ich meine dies "((iA * 256) + iR) * 256 + iG) * 256 + iB" im Vergleich zu einigen einfachen "Shift" s. Finde das sehr verwirrend. Ich möchte diesen Kommentar jedoch gerne zurücknehmen. Ziemlich möglich, dass ich aus meinem Arsch gesprochen habe ;-) – Alex

2

Sie in die andere Richtung gehen können, um mag:

iA = rgb >> 24; iR = (0x00FF0000 & rgb) >> 16; iG = (0x0000FF00 & rgb) >> 8; iB = (0x000000FF & rgb);

+2

Beachten Sie, dass RGBA2DWORD falsch ist - es verwendet logische statt bitweise OR-Operatoren. Siehe meine Antwort unten für die korrekte Implementierung. –

+0

Oooops, ja, kopiere einfach aus dem ursprünglichen Post eingefügt. – Alex

+0

@Alex Wenn Sie Ihre Antwort falsch finden, beheben Sie es bitte. Sonst werde ich es ablehnen müssen. –

3

Wenn es Ihnen nichts ausmacht, Ganzzahlen mit Byte-Größe für RGBA zu verwenden, können Sie eine Union verwenden. [] edit Dies ist eine häufig verwendete Methode und Sie werden wahrscheinlich keinen Compiler finden, der es nicht unterstützt, aber streng genommen (so wird mir gesagt) ist es ein illegaler Hack. In den meisten Fällen ist der bessere Ansatz eine mathematische oder binäre Konvertierung, aber ich werde diese Hälfte meiner Antwort an Ort und Stelle belassen, weil es dem Leser helfen kann, zu verstehen, was Menschen tun, wenn sie diese Art von Code in der Realität sehen Welt]

 
union RGBA 
{ 
    DWORD dword; 
    unsigned char RGBA[4]; 
    struct RGBAstruct 
    { 
     unsigned char b; 
     unsigned char g; 
     unsigned char r; 
     unsigned char a; 
    } 
}; 

Dann können Sie die grüne Komponente zugreifen, wie:

 
RGBA colour; 
int green = (int) colour.RGBA[2]; 

oder

 
int green = (int) colour.RGBAstruct.g; 

und Zugriff auf den DWORD-Wert als

 
DWORD value = colour.dword; 

Wenn Sie die RGBA-Werte als int-Werte benötigen oder einen Konvertierungsansatz verwenden möchten, müssen Sie bitweise Operatoren verwenden.

Sie codieren sie fast korrekt, aber Sie müssen bitweise ODER-Operator verwenden |, nicht logisch ODER || Betreiber:

 
DWORD value = (iA << 24) | (iR << 16) | (iG << 8) | iB; 

in umgekehrter Richtung zu gehen:

 
int iA = (value >> 24) & 0xff; 
int iR = (value >> 16) & 0xff; 
int iG = (value >> 8) & 0xff; 
int iB = (value) & 0xff; 
+0

P.S. Mein union/struct Beispiel ist ein bisschen durcheinander. Die Reihenfolge der RGBA-Werte hängt davon ab, ob Sie auf einer Big-Endian- oder Little-Endian-CPU ausgeführt werden. Daher müssen Sie in Ihrer Struktur möglicherweise die Reihenfolge RGBA oder ABGR verwenden, um die Werte an den richtigen Stellen zu platzieren. Ein bisschen Experimentieren (kodieren Sie einen 255,0,0,0 Wert und sehen Sie, was Sie bekommen) wird Ihnen sagen, welchen Weg Sie auf Ihrer Zielplattform machen müssen. –

+4

Ihr Gewerkschaftsbeispiel ist auf mehrere Arten vermischt. Der beliebte "Union Hack" ist in C ausdrücklich verboten. Mit ein paar Ausnahmen führt das Schreiben eines Mitglieds einer Union und das Lesen eines anderen zu einem undefinierten Verhalten. Es funktioniert möglicherweise nicht bei einem aggressiv optimierenden Compiler. GCC mit seinen aggressiven "typ-punning" -Optimierungen hat den "union hack" vorerst verschont (d. H. Es wird mit GCC funktionieren), aber ich kann nicht für alle Compiler da draußen bürgen. – AnT

+0

Die Frage sagt "C++", und erwähnt nicht den Compiler oder die Plattform, also gab ich eine generalisierte Antwort. Der Zweck von Unionen ist es, Ihnen zu ermöglichen, einen einzelnen Speicherort als unterschiedliche Datentypen zu interpretieren. Wie Sie sagen, wird es schwierig sein, einen Compiler zu finden, der dies nicht unterstützt. –

0

die RGBA Teil unsigned Eigentlich sollte lang sein:

int iR = (Wert) & 0xFF;
int iG = (Wert >> 8) & 0xff;
int iB = (Wert >> 16) & 0xff;
int iA = (Wert >> 24) & 0xff;

und die ganze Frage ist über BGRA (nach dem Beispiel der Frage) statt RGBA.

Verwandte Themen