-
July 28th, 2011, 10:51 AM
#1
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
Last edited by vanselm; July 28th, 2011 at 11:01 AM.
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|