-
May 25th, 2008, 01:15 PM
#1
bytearray to bitmap, drawing in dialog
Hello,
i'Ve been looking for an answer the last days. But havnt found out something. MAybe you can help me.
Im programming on a dialog. It shows me the live view from my webcam.
Through a callback function i get a pointer to the
LPVIDEOHDR structure. This structure contains a pointer (lpData) to
a bytearray that contains the Pixels.
I convert this RGB ByteArray into a greyvalue array.
Now i want to convert this bytearray into a Bitmap and display it
in my dialog.
I have a methode
Code:
void Dlg::Update(unsigned char* pData, int iWidth, int iHeight)
{
CClientDC dc(this);
CDC cdc;
cdc.CreateCompatibleDC(&dc);
// here i want to convert this bytearray into a bitmap and display it
// at a certain position in my dialog
}
i've already been trying this piece of code here
Code:
CreateBitmapFromPixel( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
HBITMAP hBitmap = 0;
if ( !uWidth || !uHeight || !uBitsPerPixel )
{
return hBitmap;
}
LONG lBmpSize = uWidth * uHeight * uBitsPerPixel;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Pointer to access the pixels of bitmap
UINT * pPixels = 0;
hBitmap = CreateDIBSection( hDC, (BITMAPINFO *)&
bmpInfo, DIB_RGB_COLORS, (void **)&
pPixels , NULL, 0);
if ( !hBitmap )
return hBitmap; // return if invalid bitmaps
SetBitmapBits( hBitmap, lBmpSize,pBits);
/* Or Directly Write
memcpy(ptPixels, pBitmapBitmapBits, lBmpSize );
*/
return hBitmap;
}
Update(unsigned char* pData, int iWidth, int iHeight)
{
CRect rect;
m_IDCGreyView.GetWindowRect(&rect);
ScreenToClient(&rect);
CClientDC dc(this);
CDC cdc;
cdc.CreateCompatibleDC(&dc);
HBITMAP hBitmap = CreateBitmapFromPixel(pData,iWidth,iHeight);
CBitmap bitmap;
BITMAP bmp;
GetObject(hBitmap,sizeof(bmp),&bmp);
CRect rect;
m_IDCGreyview.GetWindowRect(&rect);
ScreenToClient(&rect);
cdc.SelectObject(CBitmap::FromHandle(hBitmap));
dc.BitBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height
(),&cdc,0,0,SRCCOPY);
}
This doesnt work. i still can see my live view from the webcam.
But at the position in the dialog where i want to see the greyed image,
its just black there.
Can you help me ? im desperated.
Greetings, cmos
-
May 25th, 2008, 01:19 PM
#2
Re: bytearray to bitmap, drawing in dialog
You need to draw your stuff in the OnPaint () function. Because everything you draw outside of the function is erased by the OnPaint () function.
-
May 25th, 2008, 02:31 PM
#3
Re: bytearray to bitmap, drawing in dialog
Already tried this in OnPaint methode. doesnt work.
I tried this here just a few minutes ago. and it works. but with some strange results.
The Picuter is mirrored at the x axis and it is upside down.
but it works so far.
Code:
void Dlg::Update(unsigned char* pData, int iWidth, int iHeight)
{
if(m_pBuffer == NULL)
{
m_pBuffer = new unsigned char[iWidth * iHeight * 4];
long lSize = iWidth * iHeight;
for(int i = 0; i < lSize; i += 4)
{
m_pBuffer[i] = pData[i];
m_pBuffer[i+1] = pData[i];
m_pBuffer[i+2] = pData[i];
m_pBuffer[i+3] = 0;
}
m_ImageReady = TRUE;
}
CClientDC dc(this);
CBitmap bitmap;
CDC memDC;
memDC.CreateCompatibleDC(&dc);
int iSize = m_iSrcWidth * m_iSrcHeight * 4;//RGB + Reserved
bitmap.CreateCompatibleBitmap(&dc,m_iSrcWidth,m_iSrcHeight);
bitmap.SetBitmapBits(iSize,m_pBuffer);
//Bitmap anzeigen
(CBitmap*)memDC.SelectObject(bitmap);
CRect rect;
m_IDCGreyview.GetWindowRect(&rect);
ScreenToClient(&rect);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(), &memDC, 0, 0, m_iSrcWidth / 4, m_iSrcHeight / 4, SRCCOPY);
}
When i did this piece of code into the onpaint it didnt work really.
When move the window out of the screen and bacl, than i saw the picture (with same result in Update methode)
in my onpaint the last line is CDialog::OnPaint();
Without this line, nothing happend. with this line, i saw the picuter when i moved the window out of the screen and back into the screen.
Thats the reason for using CCLientDC.
MAybe u can help me..
greeintgs,
cmos
-
May 25th, 2008, 02:42 PM
#4
Re: bytearray to bitmap, drawing in dialog
put the code in the OnPaint, then in your update function just invalidate the client area.
Wakeup in the morning and kick the day in the teeth!! Or something like that.
"i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."
-
May 25th, 2008, 03:21 PM
#5
Re: bytearray to bitmap, drawing in dialog
Hi again,
and thanks for your fast reply.
I've changed it as you told me
Code:
Update(.....)
{
if(m_pBuffer != NULL)
{
delete[] m_pBuffer;
m_pBuffer = NULL;
}
if(m_pBuffer == NULL)
{
m_pBuffer = new unsigned char[iWidth * iHeight * 4];
long lSize = iWidth * iHeight;
for(int i = 0; i < lSize; i += 4)
{
m_pBuffer[i] = pData[i];
m_pBuffer[i+1] = pData[i];
m_pBuffer[i+2] = pData[i];
m_pBuffer[i+3] = 0;
}
m_ImageReady = TRUE;
}
}
OnPaint()
{
if(isIconic())
{
....
....
}
else
{
if(m_ImageReady)
{
CPaintDC dc(this);
CBitmap bitmap;
CDC memDC;
memDC.CreateCompatibleDC(&dc);
int iSize = 640 * 480 * 4;//RGB + Reserved
bitmap.CreateCompatibleBitmap(&dc,640,480);
bitmap.SetBitmapBits(iSize,m_pBuffer);
(CBitmap*)memDC.SelectObject(bitmap);
CRect rect;
m_IDCGreyview.GetWindowRect(&rect);
ScreenToClient(&rect);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(), &memDC, 0, 0, 640 / 4, 480 / 4, SRCCOPY);
m_ImageReady = FALSE;
}
CDialog::OnPaint();
}
;
Well, i dont see anything, except i move the dialog out of the screen and then back. If i dont do this, OnPaint will never be called.
cmos
-
May 25th, 2008, 03:26 PM
#6
Re: bytearray to bitmap, drawing in dialog
Add Invalidate () or InvalidateRect () to the update function, so the OnPaint () will be triggered.
-
May 25th, 2008, 03:29 PM
#7
Re: bytearray to bitmap, drawing in dialog
From Update you need to call
Code:
Invalidate(TRUE);
UpdateWindow();
at the end of your update function
Wakeup in the morning and kick the day in the teeth!! Or something like that.
"i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."
-
May 25th, 2008, 03:34 PM
#8
Re: bytearray to bitmap, drawing in dialog
Souldog. .. why the UpdateWindow () ? Invalidate () should be enough.
-
May 25th, 2008, 03:56 PM
#9
Re: bytearray to bitmap, drawing in dialog
UpdateWindow is probably not needed. It forces an immediate WM_PAINT.
Invalidate will cause this too when the message queue is empty
Wakeup in the morning and kick the day in the teeth!! Or something like that.
"i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."
-
May 25th, 2008, 03:56 PM
#10
Re: bytearray to bitmap, drawing in dialog
HEy, thanks again..
My OnPAint now looks like
Code:
if (IsIconic())
{
CPaintDC dc(this); // Gerätekontext zum Zeichnen
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Symbol in Clientrechteck zentrieren
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Symbol zeichnen
dc.DrawIcon(x, y, m_hIcon);
}
else
{
if(m_ImageReady)
{
CPaintDC dc(this);
CBitmap bitmap;
CDC memDC;
memDC.CreateCompatibleDC(&dc);
int iSize = m_iSrcWidth * m_iSrcHeight * 4; //RGB + Reserved
bitmap.CreateCompatibleBitmap(&dc,m_iSrcWidth,m_iSrcHeight);
bitmap.SetBitmapBits(iSize,m_pBuffer);
//Bitmap anzeigen
(CBitmap*)memDC.SelectObject(bitmap);
CRect rect;
m_IDCGreyview.GetWindowRect(&rect);
ScreenToClient(&rect);
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(), &memDC, 0, 0, m_iSrcWidth / 4, m_iSrcHeight / 4, SRCCOPY);
//dc.BitBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);
DeleteObject(bitmap);
m_ImageReady = FALSE;
}
CDialog::OnPaint();
}
My Update methode now just copies the buffer
Code:
m_iSrcWidth = iWidth;
m_iSrcHeight = iHeight;
if(m_pBuffer != NULL)
{
delete[] m_pBuffer;
m_pBuffer = NULL;
}
m_iSrcWidth = iWidth;
m_iSrcHeight = iHeight;
// RGB + Reserved
if(m_pBuffer == NULL)
{
m_pBuffer = new unsigned char[iWidth * iHeight * 4];
long lSize = iWidth * iHeight;
for(int i = lSize-1, idx = 0; i >= 0; i -= 4, idx += 4)
{
m_pBuffer[idx] = pData[i];
m_pBuffer[idx+1] = pData[i];
m_pBuffer[idx+2] = pData[i];
m_pBuffer[idx+3] = 0;
}
m_ImageReady = TRUE;
}
Not the whole dialog flickers. Guess as soon as the Update calls Invalidate (or UpdateWindow) it redraws the dialog.
By the way, do you know another way to convert my byte array into a bitmap and display it in my dialog ?
My versions works, but if i use StretchBlt and set the SourceWidth and SourceHeigth then i can see the grey picture 2 or 3 times next to each other. But if i divide it by 4, the i get one greyed picture that fits into
the frame.
thanks,
cmos
Last edited by cmos; May 25th, 2008 at 04:03 PM.
-
May 25th, 2008, 04:07 PM
#11
Re: bytearray to bitmap, drawing in dialog
to alleviate the flickering call
Invalidate(FALSE);
and handle WM_ERASEBKGND and instead of calling the base class implementation just return TRUE.
Wakeup in the morning and kick the day in the teeth!! Or something like that.
"i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."
-
May 25th, 2008, 05:12 PM
#12
Re: bytearray to bitmap, drawing in dialog
Thanks again. So far it works. Just flickers a little bit, but nothing worth to mention.
Finally some question. I hope you can give me an answer
1. is there a reason for drawing in OnPaint instead of in other methods ?
Just good coding style ?
2. is there another way how to get a bitmap from bytearray ?
somewhere i found this piece of code
Code:
CreateBitmapFromPixel( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
HBITMAP hBitmap = 0;
if ( !uWidth || !uHeight || !uBitsPerPixel )
{
return hBitmap;
}
LONG lBmpSize = uWidth * uHeight * uBitsPerPixel;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Pointer to access the pixels of bitmap
UINT * pPixels = 0;
hBitmap = CreateDIBSection( hDC, (BITMAPINFO *)&
bmpInfo, DIB_RGB_COLORS, (void **)&
pPixels , NULL, 0);
if ( !hBitmap )
return hBitmap; // return if invalid bitmaps
SetBitmapBits( hBitmap, lBmpSize,pBits);
/* Or Directly Write
memcpy(ptPixels, pBitmapBitmapBits, lBmpSize );
*/
return hBitmap;
}
But this code doesnt work. I dont know why.
My code has following problems.
I have 4 bits per pixel (R,G,B, and the las 0)
Dont know why.
When i use this here
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(), &memDC, 0, 0, m_iSrcWidth / 4, m_iSrcHeight / 4, SRCCOPY);
I have to devide the Sourec Width and Source Height by 4. Otherwise the grey picture will not fill out the frame (Picturecontrol). Instead i have lots of small grey pcitures next to eachother. like patterns.
thanks,
cmos
-
May 25th, 2008, 06:14 PM
#13
Re: bytearray to bitmap, drawing in dialog
Hello again..
I tried this code again. And "it works"
It returns a valid Handle. When I use
BITMAP bmp;
GetObject(hBmp,(sizeof(bmp),&bmp);
i get information about width height and so on.
please have a look at the code , (and please ignore that im drawing with CClientDC again)
Code:
CreateBitmapFromPixel( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
//HBITMAP hBitmap = 0;
m_HBitmap = NULL;
if ( !uWidth || !uHeight || !uBitsPerPixel )
{
return m_HBitmap;//hBitmap;
}
LONG lBmpSize = uWidth * uHeight * uBitsPerPixel / 8;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSizeImage = uWidth * uHeight * uBitsPerPixel / 8;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Pointer to access the pixels of bitmap
UINT * pPixels = 0;
/*hBitmap*/m_HBitmap = CreateDIBSection( hDC, (BITMAPINFO *)&
bmpInfo, DIB_RGB_COLORS, (void **)& pPixels , NULL, 0);
if ( !m_HBitmap )
return m_HBitmap;//hBitmap; // return if invalid bitmaps
SetBitmapBits( m_HBitmap, lBmpSize,pBits);
/* Or Directly Write
memcpy(ptPixels, pBitmapBitmapBits, lBmpSize );
*/
return m_HBitmap;
}
Code:
Update(....)
{
HBITMAP hBMP = CreateBitmapFromPixel(GetDC()->GetSafeHdc(),
(DWORD)iWidth,(DWORD)iHeight,24,m_pBuffer);
CClientDC dc(this);
CDC cdc;
cdc.CreateCompatibleDC(&dc);
cdc.SelectObject(CBitmap::FromHandle(hBMP));
CRect rect;
m_IDCGreyview.GetWindowRect(&rect);
ScreenToClient(&rect);
dc.BitBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),&cdc,0,0,SRCCOPY);
}
This works, but Bitblt doesnt Stretch the Bitmap according to my frame size.
It Displays the Bitmap and right next to it the same Bitmap again. It's like when you have a wallpaper and dont set stretch or center image. it displays the image like a pattern.
When i use StretchBlt it looks very strange.
look the following links please
first is created with
www.webz-innovations.de/dc.Bitblt.jpg
dc.BitBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),&cdc,0,0,SRCCOPY);
second one with
www.webz-innovations.de/dc.StretchBlt.jpg
dc.StretchBlt(rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height(),&cdc,0,0,iWidth,iHeight,SRCCOPY);
-
May 25th, 2008, 08:00 PM
#14
Re: bytearray to bitmap, drawing in dialog
I got it. Bitmap fits into my frame and looks great.
had to made some changes.. but it works now.
Thanks for your help.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|