I am trying to use the code mentioned Write text on BITMAPINFO in memory. My code is below.
BITMAPINFO MyBMInfo = {0}; //debug
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); //debug
int lines; //debug
HDC hdc = GetDC(0);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateBitmap(10, 10, 1, 8, bmp_buffer);
GetDIBits(memdc, hbitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS); //debug
HBITMAP oldbmp = SelectObject(memdc, hbitmap);
TextOut(memdc, 0, 0, "123", 3);
SelectObject(memdc, oldbmp);
lines = GetDIBits(memdc, hbitmap, 0, 10, bmp_buffer, &MyBMInfo, DIB_RGB_COLORS); //<-here was used other BMInfo structure
DeleteObject(hbitmap);
DeleteDC(memdc);
ReleaseDC(0, hdc);
It does not work as expected. During troubleshooting I had discovered the GetDIBits
returns 0 lines, like could not copy the content of bitmap to bmp_buffer
, later I tried to observe current selected bitmap within memdc
by executing GetCurrentObject(memdc, OBJ_BITMAP)
and it does not change, so for some reason hbitmap
is not "selected" within memdc
.
Then I had tried many different ideas and I found if hbitmap
is created by CreateCompatibleBitmap()
, lines of bmp_buffer
are updated. I queried the attributes of such created bitmap and it looks it has correct dimensions but 1 bit color setting. Following this track, if I change to hbitmat=CreateBitmap(10, 10, 1, 1, bmp_buffer)
it kind works, at least lines != 0, and some bytes in bmp_buffer
are updated. This suggests hbitmap
created by CreateBitmap(10, 10, 1, 8, bmp_buffer)
is "not compatible" with memdc
. Changing to monochromatic is not solution, as I need colors in my bitmap.
GDI documentation says any DC created by CreateCompatibleDC()
is monochromatic and 1x1 pixel size. It also says it must be update later to use color images different sizes, but there is no suggestion how to change color size. What am I doing wrong, the code I follows just use 24 bit per pixel and it worked in some other application.
I had few misunderstanding while reading documentation and example code used in questions, they are summarized below:
GetDIBits
does not use provided pallete, just itself overwrite existing memory array. It is explicly stated in documentation, I missed that part. Also does not obey biClrUsed
neither biClrImportant
, so allocate enought memory.GetDC(0)
return context from desktop which is 32 bits per pixel and HDC memdc = CreateCompatibleDC(hdc)
creates context with 1bpp (as it is in documentation).GetDIBits()
but to use intermediate buffer and copy the image to bmp file image buffer. It gives possibilities to control position and color of printed text.My working example:
char* local_img = malloc(100*100);
BITMAPINFO local_bmi = malloc(sizeof(BITMAPINFO)+sizeof(COLORREF)*255);
local_bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
local_bmi->bmiHeader.biPlanes = 1;
local_bmi->bmiHeader.biBitCount = 8;
local_bmi->bmiHeader.biHeight = 100;
local_bmi->bmiHeader.biWidth = 100;
local_bmi->bmiHeader.biCompression = 0;
local_bmi->bmiHeader.biSizeImage = 100*100;
local_bmi->bmiHeader.biClrImportant = 256;
local_bmi->bmiHeader.biClrUsed = 256;
HDC hdc = GetDC(0);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, 100, 100);
HBITMAP oldbmp = SelectObject(memdc, hbitmap);
TextOut(memdc, 0, 0, "123", 3);
SelectObject(memdc, oldbmp);
GetDIBits(memdc, hbitmap, 0, 100, local_img, local_bmi, DIB_RGB_COLORS);
DeleteObject(hbitmap);
DeleteDC(memdc);
ReleaseDC(0, hdc);
free(local_bmi);
//use local_img for own purpose, then free it!!!