Thread: Color Conversion

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    20

    Color Conversion

    I use the following to convert from ARGB1555 to ARGB8888

    Code:
                TempColor = ((pColor->Value.argb.B & 0xF8) << 7) |
                            ((pColor->Value.argb.G & 0xF8) << 2) |
                            ((pColor->Value.argb.R & 0xF8) >> 3) |
                            ((pColor->Value.argb.A & 0x80) << 8);
    Can you anyone tell me equivalent code for converting ARGB8888 to ARGB1555

    Thanks in advance

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    It looks like you are combining the B,G,R,A values into an integer with the bits having the following meanings:

    abbbbbgggggrrrrr

    So to split it out into separate components
    Code:
    pColor->Value.argb.A = TempColor >> 8 & 0x80;
    pColor->Value.argb.R = TempColor << 3 & 0xF8;
    pColor->Value.argb.G = TempColor >> 2 & 0xF8;
    pColor->Value.argb.B = TempColor >> 7 & 0xF8;

  3. #3
    Registered User
    Join Date
    Dec 2008
    Posts
    20
    Quote Originally Posted by nonoob View Post
    It looks like you are combining the B,G,R,A values into an integer with the bits having the following meanings:

    abbbbbgggggrrrrr

    So to split it out into separate components
    Code:
    pColor->Value.argb.A = TempColor >> 8 & 0x80;
    pColor->Value.argb.R = TempColor << 3 & 0xF8;
    pColor->Value.argb.G = TempColor >> 2 & 0xF8;
    pColor->Value.argb.B = TempColor >> 7 & 0xF8;
    So the above one gives ARGB values in ARGB8888 format, where TempColor is in APRG1555 ?

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    That code isn't quite right. When converting the 5-bit channel values to 8-bit quantities a value of 0x1F (31) should convert to 0xFF (255), not 0xF8 (248). The rest between 0 and 0x1F should smoothly map to values from 0 to 0xFF. The way to do this is to repeat the bit pattern.
    Taking 0x1A for example, and dropping down to binary:
    Code:
    0x1A:
    11010
         11010 (same as above again)
    11010110   (taking first 8 bits)
    ==> 0xD6
    Thus our answer is that 0x1A gets converted into 0xD6, not 0xD0 which you would get without repeating the bit pattern.
    Now that seems like more work, however it can be done very fast by using some clever tricks to do the bit repeating on all 3 RGB channels at once.
    Note that for the alpha channel we're converting from a 1-bit quantity to an 8-bit quantity. 0 maps to 0 and 1 maps to 255, that's it. Since we have to repeat the bit pattern 8 times, it's actually quicker to achieve that through a multiply, or if you prefer, a shift plus a 2 byte lookup table.
    See the below code which is optimised to about as fast as these correct conversions can possibly be done.

    When you convert back from 8-bit RGB channels to 5-bit, you just drop the extra bits.
    Code:
    unsigned int ARGB1555toARGB8888(unsigned short c)
    {
        const unsigned int a = c&0x8000, r = c&0x7C00, g = c&0x03E0, b = c&0x1F;
        const unsigned int rgb = (r << 9) | (g << 6) | (b << 3);
        return (a*0x1FE00) | rgb | ((rgb >> 5) & 0x070707);
    }
    unsigned short ARGB8888toARGB1555(unsigned int c)
    {
        return (unsigned short)(((c>>16)&0x8000 | (c>>9)&0x7C00 | (c>>6)&0x03E0 | (c>>3)&0x1F));
    }
    You'll need direct access to the unsigned short and unsigned int in each case, so if you can't work that out, post the definitions of the data types for "Value" etc.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed