c++visual-c++dword

non dword aligned pixel to dword aligned bitmap


I have to convert a raw pixel data (rows *col = 479 * 638) which is not DWORD aligned to DWORD aligned bitmap data. I have few doubts.

1) When I say d word aligned is it about allocating the total memory which is dword aligned or is it about making width DWORD aligned?

2) Say if it is about making actual width as DWORD aligned , then because of DWORD alignment I'm adding extra 2 bytes at the end to make width = 640. but when I do a memcopy from source to destination it leaves a dark black line at the bottom. But I don't want these dark line since it creates a confusion from actual image. So how can I avoid this black line at the end?

To solve this I assumed that is is about total memory allocated which is dword aligned. And I allocated that much dword aligned memory.

bitmapData = (LPBYTE) GlobalAlloc(GMEM_FIXED, bmiHeader->biSizeImage);

Where bmiHeader->biSizeImage = nrows * dowrdalignedwidth * BPP.

While doing the actual memcopy I am copying and writing to rows*cols*BPP. Is this correct?


Solution

  • DWORD alignment for images is usually for the stride, i.e. the width, and is in terms of bytes, not pixels. Right now you're changing the number of pixels you've got to be a multiple of 4 but that will be increasing your total number of bytes per row by much more than necessary, in fact probably by 8 bytes.

    What you do is calculate (columns * bits per pixel) and then align that to 32 bits to get your stride or width. Then you can multiply that by the height to get the full image size.

    So for your image which is 479 * 638, 638 is the columns and therefore the width.
    If your image is 4 bytes per pixel then you don't need to do anything special because a DWORD is 4 bytes, so your total width in bytes is a multiple of 4 bytes or 32 bits, 638 * 4 = 2552. So just multiply it by the height to get your total image size in bytes.

    However if your image was 3 bytes per pixel then 638 * 3 = 1914 and 1914 is not an even multiple of 4. So you need to pad 1914 bytes up to the next multiple of 4.

    I'm normally doing this in C# so the formula I use is:

    ((width & bitsPerPixel) + 31) & ~31

    Then divide the result by 8 to get it in terms of bytes rather than bits if necessary.

    So in your case if you do (638 * 24) / 8 to get 1914 bytes which is not a DWORD aligned value, but using the formula above you get 1916 which is an even multiple of 4 bytes and is the correct value for your stride.