Search code examples
c++winapibitmapdirect3dcreatedibsection

CreateDIBSection returns inconsistent bitmap bit values for the same image


This is an extended question about CreateDIBSection.

I used it to get the bitMap bit value of the same image which drawn using Direct3D, to verify its consistency of Direct3D rendering, i.e. as long as I get the same bitMap bit value every time I run the program (draw the same image), then I consider the Direct3D rendering passed.

However, the weird thing is that I only able to get the same bitMap bit value (from "image" as shown in the code below) for the first 4 times of running the program (that draw the same image), on 5th times onward, the result of the bitMap bit values will start to change slightly (only a small number of bytes changed, most of the remaining bytes still the same), and never get back the same bitMap bit values as the first 4 times.

But, once I restart the computer and start to run my program again, I get back the same pattern: the bitMap bit values which I get during the first 4 times of running the program are exactly the same as the first trial, but the following runs will result in different bitMap bit values.

Two possible reasons which I can think of:

  1. There are some slight inconsistency in the rendering by GPU, means the GPU might contain some defects, but I am not the GPU expert, so I don't really have the confident to conclude it in this way.

  2. I knew the CreateDIBSection will handle the memory allocation on its own, is that possible that the memory is not cleaned properly after the call of DeleteObject and impact some of the bits in the bitMap bit values? (I had followed the freeing memory steps in this discussion, but it doesn't help me to get the consistent bitMap bit values of the same image.)

Question: How can we get the consistent bitMap bit value every time (is that possible?) when we are getting it out of the same image?

Thanks.

Codes:

#include <Windows.h>
#include <cstdint>
HWND m_hwnd;

void GetBitMapInfo(const int& x_Coordinate, const int& y_Coordinate, const int& iWidth, const int& iHeight)
{

DWORD imageSize = iWidth * iHeight * 4;

// Get the display window
HDC displayWindow = GetDC(m_hwnd);
HDC hdc = CreateCompatibleDC(displayWindow);

// Fill in the Bitmap information
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = iWidth;
bmpInfo.bmiHeader.biHeight = iHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;


// Create the storage for the pixel information
uint8_t* image = nullptr;

// Populate the storage with the BMP pixel information
HBITMAP hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)(&image), nullptr, NULL);

HGDIOBJ save = SelectObject(hdc, hBitmap);
BitBlt(hdc, x_Coordinate, y_Coordinate, iWidth, iHeight, displayWindow, 0, 0, SRCCOPY);


DeleteObject(SelectObject(hdc, save));
DeleteDC(hdc);
DeleteDC(displayWindow);
DeleteObject(hBitmap);

return;
}

int main()
{
    GetBitMapInfo(0, 0, 1920, 1080);

    return 0;
}

Solution

  • I finally root cause the issue, which is not related to CreateDBSection(), instead it is due to the rotation angle, which I passed it to DirectX::XMMatrixRotationY to control the rotation of the 3D object rendering (under GraphicsClass::Frame() of the tutorial, link below).

    The original code is actually setting it in such a way that it will loop thru the 3D object rendering (and rotating) infinitely, until user press escape key to exit, so it makes the rotation angle variable static.

    But I only want the 3D object to have one complete rotation. Since the angle is a static variable, the logic goes wrong for my modified program, which only make 1 complete rotation. Consequently, the static angle gets build up from previous run (I loop my modified test multiple times during my validation) and this cause the starting rotation angle is different for the following repeated test run, as the angle is increasing until it resets itself back to 0 degree and start over again.

    And due to this little shift, the final rendering frame will stop at different part. The returned bitmap bit values from CreateDBSection() (I use it for my own CRC check purpose to verify the consistency of the 3D object rendering), which is based on the last displayed frame after the rendering done and before the window being destroyed, will of course different than the beginning runs and thus will make my CRC (cyclic redundancy check) keeps changing.

    I corrected my code so that every time of the test execution, the rotation will always start at zero degree and end with 360 degree, then exit the test. After that, the returned bitmap bit values are consistent no matter how many loops I repeated run for the test.

    Summary:

    1. CreateDBSection() has no issue for the returned bitmap bit values (I am the one got problem for not clearly understand the Direct3D rendering and my poor C++, I will improve myself;))
    2. I had tried out the Graphics driver updates (by checking the driver status via Intel Driver & Support Assistant, although it does not help for my case as after the checking, my graphics driver is up-to-date, it is a helpful debugging step in some situation.

    Thanks all for the helps.