Author Topic: [C++] Extracting 4 separate bytes from an unsigned int...  (Read 12261 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
I'm currently up and running through the examples over at LazoFoo's site (which seems to be the defacto place to learn SDL) and I have realized that often the library wants an unsigned int value to assign color. I'm very used to working in RGB triplets I understand how they are stored in an int but I'm confused on how to manipulate the bits for converting between four bytes (for ABGR) and a single unsigned int.

I'm looking to write the 4 byte values to an int, and later to extract them from an unsigned int.

Alpha       Blue        Green       Red
00000000 00000000 00000000 00000000
Thanks again folks. Still getting my feet wet with this stuff. Bit level operators are not something I'm totally comfortable with yet.  ::)
« Last Edit: November 24, 2010 by Pixel_Outlaw »
Challenge Trophies Won:

Offline LittleWhite

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 418
  • Karma: 31
  • It's me!
    • View Profile
Hey,

It looks that the website is a place to learn SDL, all my classmates learnt there ...
I didn't go through :p but I know what you need. I think you should like to the documentation of SDL_MapRGB or SDL_MapRGBA :)

Otherwise:
Code: [Select]
unsigned int colour = 0xFF00FF00;
unsigned char a = colour >> 24 & 0xFF;
unsigned char r = colour >> 16 & 0xFF;
unsigned char g = colour >> 8 & 0xFF;
unsigned char b = colour & 0xFF;
Here we are :)

For putting all together, nearly the same:
Code: [Select]
unsigned char a = 0xFF;
unsigned char r =0xFF;
unsigned char g =0xFF;
unsigned char b = 0x00;
unsigned int colour = (a << 24) & 0xFF000000) + (r << 16) & 0x00FF0000) + ((g << 8) & 0x0000FF00) + (b & 0x000000FF)
Far to be optimised ... I am doing certainly some useless masking.

If you don't get the lines ... it's just moving bits (>> and <<) and masking (& -> AND)

Warning: Be careful with the endianness, because bits order will change ... so you should really use this SDL_MapRGB() :)
The demoscene will never die, never!

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Thank you.

This is pretty common in many of the graphics programming applications so this will be useful beyond SDL.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
There's a small problem with Littlewhite's codes as they stand - you need brackets around the shifts, because & has a higher precedence than >>
Code: [Select]
unsigned int colour = 0xFF00FF00;
unsigned char a = (colour >> 24) & 0xFF;
unsigned char r = (colour >> 16) & 0xFF;
unsigned char g = (colour >> 8) & 0xFF;
unsigned char b = colour & 0xFF;

Jim
Challenge Trophies Won:

Offline LittleWhite

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 418
  • Karma: 31
  • It's me!
    • View Profile
Oops!
Jim is totally right of course :)
The demoscene will never die, never!

Offline va!n

  • Pentium
  • *****
  • Posts: 1435
  • Karma: 109
    • View Profile
    • http://www.secretly.de
I think you can write more compact code to get r,g,b,a back to one uint value...

Code: [Select]
unsigned int colour = (a << 24 | (r << 16) | (g << 8) | b);
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
You could also do it with macros:

Code: [Select]
#ifdef _ARGB
   #define ARGB_A(u) (((u) >> 24) & 0x000000FF) 
   #define ARGB_R(u) (((u) >> 16) & 0x000000FF)
   #define ARGB_G(u) (((u) >> 8)  & 0x000000FF)
   #define ARGB_B(u) (((u) >> 0)  & 0x000000FF)
   #define ARGB( r, g, b, a )   (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#else  //RGBA
   // reverse the process
#endif
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Perhaps working with pointers without shfting and bitmasking:

Its Masm but i think it can be done in inline asm for c++

.data
   color dd 0ffeeddcch               
.data?
   r db ?
   g db ?
   b db ?
   a db ?

 .code
main:
   invoke GetModuleHandle,NULL
      xor eax,eax
   
      ;Extracting RGBA bytes from DWORD
      lea edi,r
      lea esi,color
      mov ecx,4
      rep movsb
   
      mov color,0 ;Clear color

      ;Writing RGBA bytes to DWORD
      lea edi,color
      lea esi,r
      mov ecx,4
      rep movsb
coding: jwasm,masm
hobby: www.scd2003.de

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Real coders don't separate their RGBs ;)
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Yeah, real coders only use toggle switches for their Altairs too.

I'm really going to have to study more at the bit level. :crutches:
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Alternatively you can avoid most of that bit-fiddling by using unions:
Code: [Select]
struct Color
{
   union
   {
      struct
      {
         unsigned char b,g,r,a;
      };
      unsigned int argb;
   };

   Color()
   {
   }

   Color(unsigned int col)
   {
      argb= col;
   }
};
This way the for bytes r,g,b,a occupy the same space as the integer argb.

Code: [Select]
   Color col;
   col= 0xffeeddcc;

   printf("Color: %d,%d,%d,%d \n", col.a, col.r, col.g, col.b);

Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
OT: Hellfire:  "Can you see it?"

Challenge Trophies Won: