Problem with line alignment for Bitmap data
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

Thread: Problem with line alignment for Bitmap data

Threaded View

  1. #1
    Join Date
    Apr 2011
    Posts
    20

    Question Problem with line alignment for Bitmap data

    Hello,

    I have already searched on the Internet about how to align each line of the bitmap data, so that it is displayed correctly. The lines must be a multiple of 4 Byte. I also tried to do so, however the problem still exists. As long as the image width is a multiple of 4 Byte, then it is displayed correctly otherwise, the lines are shifted against each other, so that the image is displayed corruptly ( see the attached files).

    my steps to display the image are:

    1) Load the image from the .bmp file

    2) get its bits

    3) Create and modify the BITMAPINFO struct, in order to pass it to SetStretchBltMode

    4) display the image with "SetStretchBltMode"

    Code:
    // Enable button 'Load Image'
    	GetDlgItem(IDC_BUTTON_LOAD_IMAGE)->EnableWindow(FALSE);
    
    	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, _T("BMP Windows Bitmap|*.bmp|PNG Portable Network Graphics|*.png"));
    	dlg.m_ofn.nFilterIndex = 1;
    	dlg.m_ofn.lpstrTitle = _T("Search Test Image");
    	if(dlg.DoModal() == IDOK)
    	{
    		m_strFileName = dlg.GetPathName();
    		UpdateData(FALSE);
    
    		HBITMAP hBitMap = (HBITMAP)LoadImage(NULL, m_strFileName,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    
    		if (NULL != hBitMap)
    		{
    		
    			CBitmap bmp;
    			bmp.Attach((HBITMAP)hBitMap); // handle you got from LoadBitmap
    
    			BITMAP bitmap;
    			bmp.GetBitmap(&bitmap);
    
    			int paddedRow = TJPAD(bitmap.bmWidth*bitmap.bmBitsPixel/8);
    			unsigned long bufferSize = bitmap.bmHeight*paddedRow;
    			if (NULL != m_bufferBeforeCompression)
    			{
    				delete[] m_bufferBeforeCompression;
    				m_bufferBeforeCompression = NULL;
    			}
    			m_bufferBeforeCompression =  new unsigned char[bufferSize];
    
    			//::GetBitmapBits((HBITMAP)hBitMap,bufferSize,m_bufferBeforeCompression );
    
    			bmp.GetBitmapBits(bufferSize,m_bufferBeforeCompression );
    
    			//  m_bufferBeforeCompression  is the pointer to the raw image data 
    
    			m_nSizeX = bitmap.bmWidth;
    			m_nSizeY = bitmap.bmHeight;
    			m_nBitsPerPixel = bitmap.bmBitsPixel;
    
    			// if it is a grayscale image, then only the grayscale subsampling for compression is possible
    			if (m_nBitsPerPixel == 8)
    			{
    				m_cbSubsampling.SetCurSel(3);
    			}
    
    			display_frame(m_bufferBeforeCompression);
    ...
    and here is the function which displays the image data:

    Code:
    void CVITA_MFCDlg::display_frame(unsigned char * ImageData)
    {
    	// get the device handle of the picture control
    	CDC* pdc = GetDlgItem(IDC_DISPLAY_TEST)->GetDC();
    	HDC hdc = pdc->m_hDC;
    
    	// get the dimensions of the device window
    	RECT rcClient;
    	GetDlgItem(IDC_DISPLAY_TEST)->GetClientRect((LPRECT)&rcClient);
    	INT picCtrlWidth = rcClient.right;
    	INT picCtrlHeight = rcClient.bottom;
    
    
    	BITMAPINFO* BmInfo;
    	if (m_nBitsPerPixel == 8)
    	{
    		BmInfo = (BITMAPINFO*)alloca( sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
    		for(int i=0; i<256; i++)
    		{
    			BmInfo->bmiColors[i].rgbRed = i;
    			BmInfo->bmiColors[i].rgbGreen = i;
    			BmInfo->bmiColors[i].rgbBlue = i;
    			BmInfo->bmiColors[i].rgbReserved = 0;
    		}
    	}
    	else
    	{
    		BmInfo = (BITMAPINFO*)alloca( sizeof(BITMAPINFO));
    	}
    
    	BmInfo->bmiHeader.biSize		  = sizeof (BmInfo->bmiHeader);
    	BmInfo->bmiHeader.biWidth		  = m_nSizeX;
    	BmInfo->bmiHeader.biHeight		  = -m_nSizeY;
    	BmInfo->bmiHeader.biPlanes		  = 1;
    	BmInfo->bmiHeader.biBitCount	  = m_nBitsPerPixel;
    	BmInfo->bmiHeader.biCompression	  = BI_RGB;
    	//BmInfo->bmiHeader.biSizeImage	  = ((m_nSizeX * m_nBitsPerPixel +31) & ~31) /8 * m_nSizeY;
    	BmInfo->bmiHeader.biSizeImage	  = m_nSizeY * TJPAD(m_nSizeX*m_nBitsPerPixel/8);
    	BmInfo->bmiHeader.biClrUsed		  = 0;
    	BmInfo->bmiHeader.biClrImportant  = 0;
    
    
    
    	// use HALFTONE or MAXSTRETCHBLTMODE stretch mode, otherwise there are some artifacts within the image
    	SetStretchBltMode(hdc,HALFTONE); 
    
    	// display the content of the array on an output device and stretch the image accordingly to the device window dimensions
    	::StretchDIBits(		hdc, 					// hDC
    								0,						// DestX
    								0,						// DestY
    								picCtrlWidth,			// nDestWidth
    								picCtrlHeight,			// nDestHeight
    								0,						// SrcX
    								0,						// SrcY
    								m_nSizeX,				// SrcWidth
    								m_nSizeY,				// SrcHeight
    								(LPVOID)((LPDWORD)ImageData),		// lpBits
    								(LPBITMAPINFO)BmInfo, 	// lpBitsInfo
    								DIB_RGB_COLORS,			// wUsage
    								SRCCOPY);				// wDwRop
    	
    
    
    
    
    	// make the device context free for application
    	ReleaseDC(pdc);
    }
    Code:
    #define TJPAD(p) (((p)+3)&(~3))

    Could you please take a look at my code and tell me what I have to change in order to avoid the strange display bahaviour. Thanks.

    best regards
    Attached Images Attached Images   
    Last edited by vanselm; July 28th, 2011 at 12:01 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center