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.