CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    May 2008
    Posts
    7

    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

  2. #2
    Join Date
    Sep 2004
    Location
    Holland (land of the dope)
    Posts
    4,123

    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.

  3. #3
    Join Date
    May 2008
    Posts
    7

    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

  4. #4
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    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."

  5. #5
    Join Date
    May 2008
    Posts
    7

    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

  6. #6
    Join Date
    Sep 2004
    Location
    Holland (land of the dope)
    Posts
    4,123

    Re: bytearray to bitmap, drawing in dialog

    Add Invalidate () or InvalidateRect () to the update function, so the OnPaint () will be triggered.

  7. #7
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    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."

  8. #8
    Join Date
    Sep 2004
    Location
    Holland (land of the dope)
    Posts
    4,123

    Re: bytearray to bitmap, drawing in dialog

    Souldog. .. why the UpdateWindow () ? Invalidate () should be enough.

  9. #9
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    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."

  10. #10
    Join Date
    May 2008
    Posts
    7

    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.

  11. #11
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    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."

  12. #12
    Join Date
    May 2008
    Posts
    7

    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

  13. #13
    Join Date
    May 2008
    Posts
    7

    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);

  14. #14
    Join Date
    May 2008
    Posts
    7

    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
  •  





Click Here to Expand Forum to Full Width

Featured