0

I can't seem to work out what is happening here. I have the following alert icon;

K_USHORT usaAlertIcon[16] = { 0x0000, 0x0000, 0x0180, 0x03C0, 0x03C0, 0x0660, 0x0660, 0x0E70, 0x0E70, 0x1E78, 0x3E7C, 0x3FFC, 0x7E7E, 0x7E7E, 0xFFFF, 0x0000 };

Now, I want to use it in my code, that considers the array to be in 8 bit data (unsigned char);

//---------------------------------------------------------------------------
void GraphicsDriver::Stamp(DrawStamp_t *pstStamp_)
{
    K_USHORT usRow;
    K_USHORT usCol;
    K_USHORT usShift;
    K_USHORT usIndex;
    DrawPoint_t stPoint;

    usIndex = 0;
    for (usRow = pstStamp_->usY; usRow < (pstStamp_->usY + pstStamp_->usHeight); usRow++)
    {
        usShift = 0x80;
        for (usCol = pstStamp_->usX; usCol < (pstStamp_->usX + pstStamp_->usWidth); usCol++)
        {
            // If the packed bit in the bitmap is a "1", draw the color.
            if (pstStamp_->pucData[usIndex] & usShift)
            {
                stPoint.usX = usCol;
                stPoint.usY = usRow;
                stPoint.uColor = pstStamp_->uColor;
                DrawPixel(&stPoint);
            }
            // Stamps are opaque, don't fill in the BG

            // Shift to the next bit in the field
            usShift >>= 1;

            // Rollover - next bit in the bitmap.
            // This obviously works best for stamps that are multiples of 8x8
            if (usShift == 0)
            {
                usShift = 0x80;
                usIndex++;
            }
        }
    }
}

When assigning the array to the data structure to be sent through to this function, I cast it as;

stStamp.pucData = (K_UCHAR*)usaAlertIcon;

However, when I do this, it seems to flip the bytes. It draws the left half first, then the right half; so it has cut the image down the middle, and swapped the left piece for the right piece.

As a sanity check, if I explicitly split up the array myself;

K_UCHAR ucaAlertIcon[32] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0E, 0x70, 0x1E, 0x78, 0x3E, 0x7C, 0x3F, 0xFC, 0x7E, 0x7E, 0x7E, 0x7E, 0xFF, 0xFF, 0x00, 0x00 };

All works as expected.

Can someone explain why these bytes seem to be flipping when I do a type cast?

5
  • 2
    Are you aware of Endianness? Commented Jan 4, 2013 at 2:14
  • 3
    en.wikipedia.org/wiki/Endianness Commented Jan 4, 2013 at 2:14
  • @Joe: bah! you beat me to it :) Commented Jan 4, 2013 at 2:15
  • Gee, I had a feeling it was endianness. Seems odd that the 16 bit array is not stored in memory the same as the 8 bit array when split. Commented Jan 4, 2013 at 2:19
  • 16 bits is typically the first size where endianness becomes an issue. Thats why UTF-16 has a byte order mark. Commented Jan 4, 2013 at 2:21

1 Answer 1

2

Can someone explain why these bytes seem to be flipping when I do a type cast?

Endianness. You are apparently on a little-endian machine, that means the byte at the lowest address is the least significant byte. You need to convert the unsigned short values to big-endian format, htons for example does that.

#include <arpa/inet.h>

uint16_t htons(uint16_t hostshort);

You can of course do it yourself too,

array[i] = (array[i] << 8) | (array[i] >> 8);
Sign up to request clarification or add additional context in comments.

1 Comment

...and of course, that code would totally break on a big-endian machine. htons() is a safer alternative (though perhaps slower). Of course this begs the question: why was the original data stored as 16 bits anyway?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.