Farbe "aufsplitten"



  • Hey ihr, ich schreibe gerade einen color-manager (eine klasse, die alles übernimmt, was mit farben zu tun hat).
    in dieser brauche ich eine lösung für folgendes problem:
    ich übergebe eine 16 bit farbe (R5G6B5( an eine funktion und will ein unsigned char[4] array mit den farbkomponenten rgba zurück bekommen. die frage also:
    wie kann ich die einzelnen farben (r, g, b, a) aus einem unsigned short (der 16 bit farbe) "herausfiltern"?



  • Die entsprechenden Bits ausmaskieren und dann shiften. Ich sehe mit Schrecken, das es bei diesen grundlegenden Informatikwissen immer wieder mangelt!



  • Erleuchte uns doch mal 👍 mit einem Beispiel. Wie war das, keine Makros verwenden. Wie schreibt man eine Funktion die universal anzuwenden ist?



  • Ja, ein Beispiel wäre nett, ich bin halt noch in der neunten klasse und hatte kein informatik, *entschuldigung*...
    "die entsprechenden bits ausmaskieren"... wie? und welcge sind die entsürechenden? "und dann shiften"... um wieviel??
    bitte am besten wirklich ein beispiel, danke



  • Ausmaskieren:
    unsigsh & 0x1111100000000000 (nur die '1'er des unsigsh werden benutzt -> Aus 0101010101010101 wird also 01010 00000000000)

    maskedunsigsh >> 11 (maskedunsigsh wir um 11 Stellen nach rechts verschoben -> Aus 0101000000000000 wird also 0000000000001010)

    Nun hast'e den Wert 0x01010 der den R-Wert repräsentiert z.B.

    Alles nur Theorie, Syntax kann etwas falsch sein, da ich's kaum benutze...



  • Hi,
    Hm, ok um den Anfängern hier ein kleines Beispiel darzulegen, poste ich hier einen kleinen Teil meiner Engine.

    Hier werden alle Formate unterstützt was die Funktion GetPixelFormat unterstützt.

    Also die Funktion GetPixelFormat liefert die RGBA Bitmasken ( von A/32Bit ist sie zb. 0xff000000, ..usw ).

    // get textureinfo from level 0
    	(*pTexture)->GetLevelDesc( iLevel, &d3ddesc );
    	PixelFormat = GetPixelFormat( d3ddesc.Format );
    
    	// get bits per channel
    	DWORD bits_a  = GetBitsFromBitMask( PixelFormat.dwABitMask, PixelFormat.BitsPerPixel );
    	DWORD bits_r  = GetBitsFromBitMask( PixelFormat.dwRBitMask, PixelFormat.BitsPerPixel );
    	DWORD bits_g  = GetBitsFromBitMask( PixelFormat.dwGBitMask, PixelFormat.BitsPerPixel );
    	DWORD bits_b  = GetBitsFromBitMask( PixelFormat.dwBBitMask, PixelFormat.BitsPerPixel );
    
    	// set colorkey
    	for( UINT cy=0; cy < d3ddesc.Height; cy++ )
    	{
    		for( UINT cx=0; cx < d3ddesc.Width; cx++ )
    		{
    			DWORD dwColor;
    			DWORD dwNewColor;
    
    			// read color from current pixel
    			if( PixelFormat.BitsPerPixel == 16 )
    				dwColor = ((WORD*)pBits)[cy*dwLineLength+cx];
    			if( PixelFormat.BitsPerPixel == 32 )
    				dwColor = ((DWORD*)pBits)[cy*dwLineLength+cx];
    
    			// .. 64 bits
    
    			// export color
    			UCHAR pix_a = (UCHAR)	( (dwColor &  PixelFormat.dwABitMask ) >> (bits_r+bits_g+bits_b) );
    			UCHAR pix_r = (UCHAR)	( (dwColor &  PixelFormat.dwRBitMask ) >> (bits_g+bits_b) );
    			UCHAR pix_g = (UCHAR)	( (dwColor &  PixelFormat.dwGBitMask ) >> (bits_b) );
    			UCHAR pix_b = (UCHAR)	( (dwColor &  PixelFormat.dwBBitMask ) );
    
    			// reduce values 0-1
    			FLOAT fA = ((FLOAT)pix_a)/(pot( 2, bits_a )-1);
    			FLOAT fR = ((FLOAT)pix_r)/(pot( 2, bits_r )-1);
    			FLOAT fG = ((FLOAT)pix_g)/(pot( 2, bits_g )-1);
    			FLOAT fB = ((FLOAT)pix_b)/(pot( 2, bits_b )-1);
    
    			// compute 32 bit value
    			UCHAR ucA = (UCHAR)(fA * 255);
    			UCHAR ucR = (UCHAR)(fR * 255);
    			UCHAR ucG = (UCHAR)(fG * 255);
    			UCHAR ucB = (UCHAR)(fB * 255);
    		}//for
    	}//for
    

    Bye



  • Hi,
    Für die die nicht wissen wie ich auf dwLineLength gekommen bin:
    Aber das sollte eig. selbstverständlich sein.

    // compute line length
    	if( PixelFormat.BitsPerPixel == 16 )
    		dwLineLength = LockedRect.Pitch >> 1;
    	if( PixelFormat.BitsPerPixel == 32 )
    		dwLineLength = LockedRect.Pitch >> 2;
    

    Bye



  • danke schonmal, hab aber noch ne wahrscheinlich sehr dumme frage:
    wie sehen denn die bitmasken aus?? um speziell auf meine frage zurück zu kommen, wie sieht die bitmask für r5g6b5 aus?
    und noch was, diese frage habe ich ähnlich hier schonmal gesachriebem:
    was machst du in dieser funktion, wenn deine textur ein 24 bit format hat??
    dank



  • Gab's nicht auch in der FAQ schon irgendwo mal eine allgemeine Methode? Was ich hier nicht so toll finde, ist die Verwendung von floats, wenn man erst multipliziert und dann teilt, geht es ohne. Zudem warum ist der Faktor denn 255, müsste doch 2^8 sein!

    Wie die Bitmasken für 565 aussieht ist doch klar, die ersten 5 Bits sind für Rot, die nächsten 6 Grün, der Rest Blau. Das ist doch mal logisch!



  • ja, aber wie schreibe ich das? bitmasken sind doch diese 0xff000000 und so, oder? also, wie sähe z.b. eine typische "dsBitMask" aus [Helper]´s PixelFormat Struktur aus?



  • Hi,

    @TGGC:
    Also die Float's hab ich damal genommen, weil irgent etwas anderes rauskam. Bin mir aber nicht sicher was. Mit den 255 hast du recht. Hab ich gleich geändert, Danke 👍

    @Tetris Fan:
    Die Bitmaske würde in diesem Falle folgende sein:

    pfmt.dwRBitMask		= 0xF800;
    pfmt.dwGBitMask		= 0x07E0;
    pfmt.dwBBitMask		= 0x001F;
    pfmt.BitsPerPixel	= 16;
    

    Aber wie TGGC gesagt hat, im FAQ findest du genauere Informationen.

    Bye



  • Danke, aber das hilft mir leider immer noch nicht... 😞 wie kommt man denn auf diese bitmasken? sind die alle irgendwie festgelegt, oder gibt es eine formel oder so, mit der man das berechnen kann?
    in den faq zur spiele und grafik programmierung hab ich noch nichts gefunden... suche aber weiter.



  • Tetris Fan schrieb:

    Danke, aber das hilft mir leider immer noch nicht... 😞 wie kommt man denn auf diese bitmasken? sind die alle irgendwie festgelegt, oder gibt es eine formel oder so, mit der man das berechnen kann?
    in den faq zur spiele und grafik programmierung hab ich noch nichts gefunden... suche aber weiter.

    Wenn Du mal in meinen Post geguckt hättest, wüsstest Du es:

    R5G6B5 sind 5 Bits für Rot, 6 für Grün und 5 für Blau.

    Entsprechend, um ROT zu erhalten:
    1111100000000000 (erste 5 Bits)
    Um GRÜN zu erhalten:
    0000011111100000 (zweite 6 Bits)
    Für BLAU entsprechend!

    Und jetzt rate mal, wie das HEXADEZIMAL aussieht:
    Richtig:

    [Helper] schrieb:

    @Tetris Fan:
    Die Bitmaske würde in diesem Falle folgende sein:

    pfmt.dwRBitMask		= 0xF800;
    pfmt.dwGBitMask		= 0x07E0;
    pfmt.dwBBitMask		= 0x001F;
    pfmt.BitsPerPixel	= 16;
    

    Für ROT:
    4 Bits = 1 HexWert
    Also die ersten 4 Bits alle auf 1 ergibt F
    Die zweiten 4 Bits nur das erste auf 1 (1000) ergibt 8

    Und wenn Du es jetzt nicht verstanden hast, Schande über Dich, selbst meine Freundin hat das gerade gerallt! 🤡 👍



  • AAAAAAAAHHHHHHHHHH
    ich habs gerafft (MEINE Freundin leider immer noch net... egal)
    nun noch aber eine letzte frage, dann seid ihr mich (vorserst...) los:
    ich habe beim weiteren suchen etwas gefunden, zwar nichtt das, was ich gesucht habe, fand es aber dennoch sehr interessant:
    um vier farbkomponenten zu einer farbe zusammen zu führen benutze ich D3DCOLOR_ARGB, dieses rechnet das ja so:
    (((a) & 0xff) << 24) | (((r) & 0xff) << 16 etc.
    auf gamedev.net habe ich aber eine solche rechnung gefunden:
    (a << 24) | (r << 16) | (r << 😎 | (b).
    ist das das gleiche???



  • Hi,

    Hm ich nehme ´jetzt an, dass die der '&' und '|' operator nichts sagt, sonst hättest du es dir denken können.

    Wenn ich zwei Fargen(a,b) mit einem '&' operator vergleiche kommen die Bits raus, die in beiden Farben gesetzt sind. Da kommt zb. folgendes raus. ( in Bits)

    Bit a b ergebnis
    1 1 0 0
    2 1 0 0
    3 1 1 1
    4 0 1 0
    .
    .

    Also dieser & operator "entfernt" einfach die Werte die überflüssig sind.

    zb. für den Rot-Wert brauch ich nicht die A, G,B Werte. Durch das Bitweise vergleichen mit der Roten-Bitmask bleiben nur die Bits stehen die den Rot anteil der Farbe angeben.

    Im Prinzip ist das Verfahren überflüssig. Aber um wirklich 100% sicher zu gehen wird das einfach gemacht 🙂

    Bye



  • Man, hier wird ja echt beim Urschleim angefangen...



  • Tetris Fan schrieb:

    um vier farbkomponenten zu einer farbe zusammen zu führen benutze ich D3DCOLOR_ARGB, dieses rechnet das ja so:
    (((a) & 0xff) << 24) | (((r) & 0xff) << 16 etc.
    auf gamedev.net habe ich aber eine solche rechnung gefunden:
    (a << 24) | (r << 16) | (r << 😎 | (b).
    ist das das gleiche???

    Im ersteren ist ja überhaupt kein g, b drin?
    Um in 2. ist r doppelt und g fehlt?!?
    Das ist falsch.

    Im Übrigen stimmt hier Helper's comment

    [Helper] schrieb:

    Also dieser & operator "entfernt" einfach die Werte die überflüssig sind.

    zb. für den Rot-Wert brauch ich nicht die A, G,B Werte. Durch das Bitweise vergleichen mit der Roten-Bitmask bleiben nur die Bits stehen die den Rot anteil der Farbe angeben.

    nicht!
    Ein "& 0xFF" ist VÖLLIG überflüssig (da alle Bits genommen werden).

    Aber ich denke Du hast es einfach falsch abgeschrieben... 🙂

    Helper's anderer

    [Helper] schrieb:

    Hm ich nehme ´jetzt an, dass die der '&' und '|' operator nichts sagt, sonst hättest du es dir denken können.

    stimmt aber umso mehr: Einfach mal in einem CPP-Tut Deiner Wahl bitweise Operatoren nachschlagen. Das dürfte Licht in die Angelegenheit bringen.

    Im Übrigen gab's irgendwo hier letztens eine Frage zu "SDL_Init(SDL _AUDIO | SDL_VIDEO)" -> Das ist das gleiche Prinzip... 🤡



  • ok, gut, sonst hätte ich alles von meinem color manager, was ich schon habe, umschreiben müssen...
    gut, das solls dan wirklich mal gewesen sein.
    danke an alle, 1000x danke,
    cya



  • Sgt. Nukem:
    oh... peinlich. also ddie zweite zeile habe ich tatsächlich falsch abgeschrieben. bei der ersten (übrigens ein auszug aus der dx doku) habe ich ein etc. jinter die ersten beiden teile der rechning gesetzt, da ich keine lust hatte, diese komplett abzuschreiben.



  • Ich werde langsam Wahnsinning...........
    folgendes problem: ich setze eine 565 farbe zusammen (16 bit, logisch), und zwar so:

    unsigned short color = (unsigned short)((255 << 11) | (128 << 5) | (0));

    Die resultierende farbe ist gelb, wie das "profi-auge" erkennen sollte... (R:255, G:128, B:0)
    nun möchte ich den rot-teil der farbe haben:

    unsigned char red = (unsigned char) ((color & 0xF800) >> 11);

    wenn ich mir red ausgeben lasse, erhalte ich alles andere, als 255 (was ja der rot-teil der erstellten farbe ist),
    HELP.......


Anmelden zum Antworten