Creating a DIB from a buffer and blitting it to the screen - c++

I'm trying to create my own image buffer filled with red pixels and then use that with a DIB to display it on a screen DC. The result is that I'm getting a dialog full of lines, almost like what would happen if the stride was off... maybe someone here can point out my mistake. The lines in the image are difficult to see, but they alternate as a line of red, then green, then blue.. repeating until the bottom of the dialog. Much appreciated if someone can help me out on this!
//Filling the buffer with all red pixels
uint8_t *buffer = new uint8_t[IMAGEX * IMAGEY * 3];
for (int y = 0; y < IMAGEY; y++)
{
for (int x = 0; x < IMAGEX * 3; x += 3)
{
buffer[y*IMAGEX*3 + x] = 0;
buffer[y*IMAGEX*3 + x + 1] = 0;
buffer[y*IMAGEX*3 + x + 2] = 255;
}
}
pCam->pTestQ->push_back(buffer);
//Displaying the buffer on a DC
BITMAPINFOHEADER bmih = {0};
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = IMAGEX;
bmih.biHeight = -IMAGEY;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
bmih.biSizeImage = IMAGEX * IMAGEY * 3;
BITMAPINFO bmi = {0};
bmi.bmiHeader = bmih;
pDC = GetDC();
mDC.CreateCompatibleDC(pDC);
CBitmap img;
img.CreateCompatibleBitmap(pDC, IMAGEX, IMAGEY);
CBitmap* pOldBmp = mDC.SelectObject(&img);
int iRet = SetDIBits(mDC, img, 0, IMAGEY, pCamera->pTestQ->front(), &bmi, DIB_RGB_COLORS);
pDC->BitBlt(0, 0, IMAGEX, IMAGEY, &mDC, 0, 0, SRCCOPY);
mDC.SelectObject(pOldBmp);
ReleaseDC(pDC);
Resulting dc blit:
http://i.imgur.com/qtImSFE.png

Related

Can I output a one channel image acquired from camera into a winAppi window?

I have a pointer to an image acquired from acamera using a third party SDK. The image is one band (Mono 8). I want to output it as a bittmap into a winAppi window. What i do is
HBITMAP hBitmap = NULL;
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = 1280;
bmih.biHeight = 960;
bmih.biPlanes = 1;
bmih.biBitCount = 8;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
BITMAPINFO dbmi;
ZeroMemory(&dbmi, sizeof(dbmi));
dbmi.bmiHeader = bmih;
dbmi.bmiColors->rgbBlue = 0;
dbmi.bmiColors->rgbGreen = 0;
dbmi.bmiColors->rgbRed = 0;
dbmi.bmiColors->rgbReserved = 0;
void* bits = &aquiredImageCPU.m_sMemory.ptr()[0];
hBitmap = CreateDIBitmap(dc, &bmih, CBM_INIT, bits, &dbmi, DIB_RGB_COLORS);
src = CreateCompatibleDC(dc);
SelectObject(src, hBitmap);
BitBlt(dc, 10,10,512, 512, src, 0, 0, SRCCOPY);
If i output the image as matrix and previou it using my library (a library where i use imsave similiar to matlabs imsave) i can see that the image is ok(grayscale image). But when i output it to winAppi window it tranforms it to RGB. I think it has to do with
HDC dc = GetDC(hwnd);
src = CreateCompatibleDC(dc);
Any suggestions?
Thank you
What i did in a similiar case is to take every 8 bits and to copy them 2 more times after the chunk of 8 bits. That works but it is costly and i need to have a real tile application.
auto outputImageHight = 1280;
auto outputImageWidth = 960;
unsigned char *myArray = new unsigned char[3 * outputImageHight * outputImageWidth];
for (int i = 0; i < outputImageHight; i++)
for (int j = 0; j < outputImageWidth; j++)
{
unsigned char ucTmp = (unsigned char)(image(i, j));
myArray[3 * (i + outputImageHight * j) + 0] = ucTmp;
myArray[3 * (i + outputImageHight * j) + 1] = ucTmp;
myArray[3 * (i + outputImageHight * j) + 2] = ucTmp;
}
An 8-bit bitmap requires a color table. Since you want grayscale, you have to set up the color table to have 256 levels of gray. You've set the first one to black, which is correct, but you haven't set the rest.
BITMAPINFO is actually a variably sized structure. The bmiColors field is just a placeholder for the first color in the color table. You have to allocate extra space for the entire color table and fill it out.
std::size_t size = sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);
std::vector<char> buffer(size);
BITMAPINFO *dbmi = reinterpret_cast<BITMAPINFO *>(buffer.data());
ZeroMemory(dbmi, size); // probably unnecessary
dbmi->bmiHeader = bmih;
for (int i = 0; i < 256; ++i) {
dbmi->bmiColors[i].rgbBlue = i;
dbmi->bmiColors[i].rgbGreen = i;
dbmi->bmiColors[i].rgbRed = i;
dbmi->bmiColors[i].rgbReserved = 0;
}

Windows GetDIBits not returning expected values

I'm currently writing a small program that scans the screen and looks for pixels. My issue is that GetDIBits function doesn't appear to return a proper screenshot of the screen.
Copying the bitmap to the clipboard does put the right screen image in the clipboard.
I decided to print out the function's output to a BMP file to get an idea of what's going on and it clearly isn't what I'm expecting.
I'll also mention that I have 3 monitors, incase that could explain why it's not behaving like expected.
class Test {
int screenWidth;
int screenHeight;
HWND targetWindow;
HDC targetDC;
HDC captureDC;
RGBQUAD *pixels;
HBITMAP captureBitmap;
bool TakeScreenshot() {
ZeroMemory(pixels, screenHeight*screenWidth);
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
targetWindow = GetDesktopWindow();
targetDC = GetDC(NULL);
captureDC = CreateCompatibleDC(targetDC);
captureBitmap = CreateCompatibleBitmap(targetDC, screenWidth, screenHeight);
HGDIOBJ old = SelectObject(captureDC, captureBitmap);
if (!old)
printf("Error selecting object\n");
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, captureBitmap);
CloseClipboard();
if (BitBlt(captureDC, 0, 0, screenWidth, screenHeight, targetDC, 0, 0, SRCCOPY)) {
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = screenWidth;
bmi.bmiHeader.biHeight = -screenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
if (!SelectObject(captureDC, old))
printf("Error unselecting object\n");
if (!GetDIBits(captureDC,
captureBitmap,
0,
screenHeight,
pixels,
&bmi,
DIB_RGB_COLORS
)) {
printf("%s: GetDIBits failed\n", __FUNCTION__);
return false;
}
}
else {
printf("%s: BitBlt failed\n", __FUNCTION__);
return false;
}
return true;
}
// This is from somewhere on stackoverflow - can't find where.
void MakePicture() {
typedef struct /**** BMP file header structure ****/
{
unsigned int bfSize; /* Size of file */
unsigned short bfReserved1; /* Reserved */
unsigned short bfReserved2; /* ... */
unsigned int bfOffBits; /* Offset to bitmap data */
} BITMAPFILEHEADER;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
unsigned short bfType = 0x4d42;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfSize = 2 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2560 * 1440 * 3;
bfh.bfOffBits = 0x36;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = screenWidth;
bih.biHeight = screenHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = 0;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 5000;
bih.biYPelsPerMeter = 5000;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
FILE *file;
fopen_s(&file, "test.bmp", "wb");
if (!file)
{
printf("Could not write file\n");
return;
}
/*Write headers*/
fwrite(&bfType, 1, sizeof(bfType), file);
fwrite(&bfh, 1, sizeof(bfh), file);
fwrite(&bih, 1, sizeof(bih), file);
/*Write bitmap*/
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
unsigned char r = pixels[x + y].rgbRed;
unsigned char g = pixels[x + y].rgbGreen;
unsigned char b = pixels[x + y].rgbBlue;
fwrite(&b, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&r, 1, 1, file);
}
}
fclose(file);
}
Test() {
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
pixels = new RGBQUAD[screenWidth * screenHeight];
}
~Test() {
//cleanup
}
};
Here is the result that the code is giving(instead of a screenshot):
It appears like it takes a few pixels from the top of my screen and stretches them into an image. The screenshot is from Visual Studio being open(orange part being the notifications).
If I put a giant red square (255, 0, 0) in my screen, if it's height isn't 0, the pixels array will not contain a single red pixel.
BitBlt performs the actual copying. Clipboard functions should be called after BitBlt
Also note, in mutli-monitor settings, SM_CXSCREEN/Y... give the size for the primary monitor. Use SM_XVIRTUALSCREEN/XV... for the whole screen. SM_XVIRTUALSCREEN/Y will give the X/Y coordinate (it's usually zero)
Be sure to release all the handles and delete the used objects when you are finished. In fact, there is no need to declare targetDC etc. as class members.
If the application is not DPI aware, the bitmap may look smaller depending on DPI settings. Call SetProcessDPIAware() at the start of the program for a quick fix, or set the manifest.
As noted in comment, with SetClipboardData(CF_BITMAP, captureBitmap); the system takes over captureBitmap. Avoid calling this function or make a copy of the bitmap to pass to clipboard.
int main()
{
int screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
int screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
screen_x = 0;
screen_y = 0;
RGBQUAD* pixels = new RGBQUAD[screenWidth * screenHeight];
DWORD size = screenWidth * screenHeight * 4;
ZeroMemory(pixels, size);
HDC targetDC = GetDC(NULL);
HDC captureDC = CreateCompatibleDC(targetDC);
HBITMAP captureBitmap = CreateCompatibleBitmap(targetDC, screenWidth, screenHeight);
HGDIOBJ old = SelectObject(captureDC, captureBitmap);
if(!BitBlt(captureDC, 0, 0, screenWidth, screenHeight, targetDC,
screen_x, screen_y, SRCCOPY))
printf("BitBlt error\n");
SelectObject(captureDC, old);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = screenWidth;
bmi.bmiHeader.biHeight = -screenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
if(OpenClipboard(NULL))
{
EmptyClipboard();
SetClipboardData(CF_BITMAP,
CopyImage(captureBitmap, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE));
CloseClipboard();
}
if(!GetDIBits(targetDC,
captureBitmap,
0,
screenHeight,
pixels,
&bmi,
DIB_RGB_COLORS
))
printf("%s: GetDIBits failed\n", __FUNCTION__);
BITMAPFILEHEADER filehdr = { 'MB', 54 + size, 0, 0, 54 };
std::ofstream f("test.bmp", std::ios::binary);
f.write((char*)&filehdr, sizeof(filehdr));
f.write((char*)&bmi, sizeof(bmi));
f.write((char*)pixels, size);
//cleanup:
SelectObject(captureDC, old);
DeleteObject(captureBitmap);
DeleteDC(captureDC);
ReleaseDC(0, targetDC);
}
GetDIBits function reference, remarks section:
The bitmap identified by the hbmp parameter must not be selected into
a device context when the application calls this function.
Deselect bitmap before calling GetBIBits.
HBITMAP oldBitmap = SelectObject(captureDC, captureBitmap);
...
// Deselect captureBitmap by selecting oldBitmap.
SelectObject(captureDC, oldBitmap);
Remember to add cleanup code (restore bitmap, destroy bitmap, destroy or release device contexts).
Additional bug:
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
unsigned char r = pixels[x + y].rgbRed;
unsigned char g = pixels[x + y].rgbGreen;
unsigned char b = pixels[x + y].rgbBlue;
fwrite(&b, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&r, 1, 1, file);
}
}
I think it should be
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
unsigned char r = pixels[x + y*screenWidth].rgbRed;
unsigned char g = pixels[x + y*screenWidth].rgbGreen;
unsigned char b = pixels[x + y*screenWidth].rgbBlue;
fwrite(&b, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&r, 1, 1, file);
}
}
But rows require padding to multiplies of 4 bytes:
// Important: each row has to be padded to multiple of DWORD.
// Valid only for 24 bits per pixel bitmaps.
// Remark: 32 bits per pixel have rows always aligned (padding==0)
int padding = 3 - (screenWidth*3 + 3)%4;
// or
// int padding = 3 - ((screenWidth*3 + 3) & 3);
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
unsigned char r = pixels[x + y*screenWidth].rgbRed;
unsigned char g = pixels[x + y*screenWidth].rgbGreen;
unsigned char b = pixels[x + y*screenWidth].rgbBlue;
fwrite(&b, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&r, 1, 1, file);
}
// Important: each row has to be padded to multiple of DWORD.
fwrite("\0\0\0\0", 1, padding, file);
}
Adjust file size (valid for 24 bits per pixel):
bfh.bfSize =
2
+ sizeof(BITMAPFILEHEADER)
+ sizeof(BITMAPINFOHEADER)
+ ((screenWidth*3 + 3) & ~3) * screenHeight;

C++ get average colour of multible squares on screen (ambilight)

Im new and i hope you can help me.
First some infos:
I wanna create a ambilight for my Keyboard(Roccat MK FX)
My Screen is 2560x1440.
I wanna split the screen in multible squares. For each Key on the board 1 square.
The board layout: enter image description here
The Splitting of the screen(more or less):
enter image description here
SOOO i wanna get the average colour of field "esc" and put it in the key "0" and so on.
I only have problems to get the colour of the screen.
I wanna only read every 10 pixel for speed and so on. maybe i lower it or so. i will see it later^^
the code is only for the top row of keys.
every square for a key has the dimension of 160x240 pixels for all 16 keys.
HDC hScreen = GetDC(0);
ScreenX = GetDeviceCaps(hScreen, HORZRES);
ScreenY = GetDeviceCaps(hScreen, VERTRES);
HDC hdcMem = CreateCompatibleDC(hScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
BITMAPINFOHEADER bmi = { 0 };
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biWidth = ScreenX;
bmi.biHeight = -ScreenY;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = 0;// 3 * ScreenX * ScreenY;
if (ScreenData)
free(ScreenData);
ScreenData = (BYTE*)malloc(4*ScreenX * ScreenY);
GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
ReleaseDC(0, hScreen);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
if (tasta)
{
//teiler = 1;
redcolor = 0;
greencolor = 0;
bluecolor = 0;
redtemp = 0;
greentemp = 0;
bluetemp = 0;
hori = 0;
vert = 0;
memset(frame_dataOnOff, 0, 110);
memset(frame_dataRed, 0, 110);
memset(frame_dataGreen, 0, 110);
memset(frame_dataBlue, 0, 110);
x_cord = 0;
for (int k = 0; k <= 15; k++)//eigne einteilung wählen
{
redcolor = 0;
greencolor = 0;
bluecolor = 0;
teiler = 0;
for (int y = 1440; y > 1200; y = y - 10)//VERTIKAL 1440 240
{
for (int x = 160 * k; x <= 160 * k + 160; x = x + 10)//Horizontal 2560 variable
{
redcolor = redcolor + ScreenData[4 * (((y)*ScreenX) + x) + 2];
greencolor = greencolor + ScreenData[4 * (((y)*ScreenX) + x) + 1];
bluecolor = bluecolor + ScreenData[4 * (((y)*ScreenX) + x)];
teiler++;
}
}
redcolor = redcolor / teiler;
greencolor = greencolor / teiler;
bluecolor = bluecolor / teiler;
frame_dataOnOff[k] = 1;
frame_dataRed[k] = redcolor;
frame_dataGreen[k] = greencolor;
frame_dataBlue[k] = bluecolor;
}
x_cord = 0;
ReleaseDC(0, hScreen);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
}
with this code i get a error when k is 6 and x is 1010 error is: Ausgelöste Ausnahme: Lesezugriffsverletzung "ScreenData" war "0x62C511C". ScreenData for red = 14749642
ScreenData for blue= 14749641
ScreenData for green = 14749640
I think im out of range or so. but dont know
Thx for help ;)
ps. when i change the multiplier from ScreenData from 4 to 3, the code works, but the colour squares ae on the wrong place. more in the left middle of the screen.

Given just a HBITMAP, how to draw to it?

I'm an absolute beginner at this but have managed to blunder my way to 93% of where I want to be. Need help for the final 7%.
I've manually created a bitmap like so:
BITMAPINFO bmpInfo = { 0 };
BITMAPINFOHEADER bmpInfoHeader = { 0 };
BITMAP ImageBitmap;
void *bits;
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biBitCount = 32;
bmpInfoHeader.biClrImportant = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biHeight = -IMAGE_DISPLAY_HEIGHT;
bmpInfoHeader.biWidth = IMAGE_DISPLAY_WIDTH;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biSizeImage = IMAGE_DISPLAY_WIDTH * IMAGE_DISPLAY_HEIGHT * 4;
ZeroMemory(&bmpInfo, sizeof(bmpInfo));
bmpInfo.bmiHeader = bmpInfoHeader;
bmpInfo.bmiColors->rgbBlue = 0;
bmpInfo.bmiColors->rgbGreen = 0;
bmpInfo.bmiColors->rgbRed = 0;
bmpInfo.bmiColors->rgbReserved = 0;
g_hImageBitmap = CreateDIBSection(hDC, &bmpInfo, DIB_RGB_COLORS, &bits, NULL, 0);
GetObject(g_hImageBitmap, sizeof(BITMAP), &ImageBitmap);
for (i = 0; i < IMAGE_DISPLAY_WIDTH; i++) {
for (j = 0; j < IMAGE_DISPLAY_HEIGHT; j++) {
((unsigned char *)bits)[j*IMAGE_DISPLAY_WIDTH * 4 + i * 4] = 255; // Blue
((unsigned char *)bits)[j*IMAGE_DISPLAY_WIDTH * 4 + i * 4 + 1] = 255; // Green
((unsigned char *)bits)[j*IMAGE_DISPLAY_WIDTH * 4 + i * 4 + 2] = 255; // Red
((unsigned char *)bits)[j*IMAGE_DISPLAY_WIDTH * 4 + i * 4 + 3] = 0;
}
}
g_ImageBitmapPixels = bits;
and elsewhere WM_PAINT handles drawing this like so
hdc = BeginPaint(hwnd, &ps);
if (g_hImageBitmap != NULL) {
GetObject(g_hImageBitmap, sizeof(BITMAP), &bm);
hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, g_hImageBitmap);
BitBlt(hdc, UPPER_LEFT_IMAGE_X, UPPER_LEFT_IMAGE_Y,
bm.bmWidth, bm.bmHeight, hMemoryDC, 0, 0, SRCCOPY);
SelectObject(hMemoryDC, hOldBitmap);
}
Given the global variable g_ImageBitmapPixels other parts of the program can change and manipulate individual pixels in the bitmap, and when that happens, I use
InvalidateRect(hwnd, &RECT_ImageUpdate_Window, TRUE);
UpdateWindow(hwnd);
to update just that little portion of the screen. Works great. Hooray for me.
To get to the point, my question is, if a function has ONLY the HBITMAP (g_hImageBitmap) ... is there a way to call the Windows library functions to draw lines, text, circles, filled circles, to the HBITMAP? Like these functions
MoveToEx(hDC, x1, y1, NULL);
LineTo(hDC, x2, y2 );
HBRUSH hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
FillRect(hDC, &somerectangle, hRedBrush);
except instead of needing a device context, they just take the HBITMAP?
I have a pointer to the actual pixels (g_ImageBitmapPixels) so I could just write my own line drawing, circle drawing, rectangle filling functions. Indeed I have done that, but it seems a shame not to use the functions Microsoft so kindly provides. Also, I'm not smart enough to make my own text-drawing functions.
Thank you for your help.

Wrong display depending on displayed bitmap size

I am having a trouble in a SDI view.
I am using the following code to display a bitmap buffer.
Depending on the width of the bitmap and when the width is becoming large, then a flickering problem occurs.
Additionally, the view is displaying weird data as seen below :
Here is the expected display.
The code I am using for this view is here :
void CTestLargeView::RefreshDisplay()
{
CClientDC dc(this);
CRect cRect;
GetClientRect(&cRect);
LPBITMAPINFO pBmpInfo;
pBmpInfo = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = XSize;
pBmpInfo->bmiHeader.biHeight = YSize;
pBmpInfo->bmiHeader.biPlanes = 1;
pBmpInfo->bmiHeader.biBitCount = 32;
pBmpInfo->bmiHeader.biCompression = BI_RGB;
pBmpInfo->bmiHeader.biSizeImage = XSize * YSize;
pBmpInfo->bmiHeader.biXPelsPerMeter = 0;
pBmpInfo->bmiHeader.biYPelsPerMeter = 0;
pBmpInfo->bmiHeader.biClrUsed = 0;
pBmpInfo->bmiHeader.biClrImportant = 0;
SetStretchBltMode(dc.m_hDC, STRETCH_DELETESCANS);
StretchDIBits(dc.m_hDC,
0,
0,
cRect.Width(),
cRect.Height(),
0,
0,
XSize,
YSize,
Data,
pBmpInfo,
DIB_RGB_COLORS,
SRCCOPY);
delete[] pBmpInfo;
}
void CTestLargeView::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 150)
RefreshDisplay();
CView::OnTimer(nIDEvent);
}
int CTestLargeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
SetTimer(150, 33, NULL);
XSize = 32000; // No flickering
//XSize = 32800; // Flickering occurring
YSize = 256;
Data = new int[XSize * YSize];
for (int i = 0 ; i < XSize * YSize ; i++)
Data[i] = RGB(i % 255, i % 255, i % 255);
return 0;
}
Thanks !
Found the problem->
It is caused by the "STRETCH_DELETESCANS". Changing it to STRETCH_HALFTONE is correcting the trouble.