由于项目需要,bmp图片特别大有1G多,读取数据是只读取其中的一个窗口所以就根据网上的资料搞了下面这个c++的类。
class cReadBmp
{
private:
//图像的宽和高,行补足,头长度
int m_fw,m_fh,m_att,m_hl;
PBYTE m_bm;//像素数据
PBYTE m_pvFile;//内存映射文件促使地址
HANDLE m_hFileMapping;
public:
cReadBmp(LPCWSTR pfilename);
~cReadBmp(void);
public:
//获取图片宽度成功返回TRUE
BOOL getPictureWidth(PINT pwidth);
//获取图片高度成功返回TRUE
BOOL getPictureHeight(PINT pheight);
//获取图片的区域,失败返回NULL
HBITMAP getBmpRect(int x,int y,int width,int height);
//打开BMP文件
BOOL openBmp(LPCWSTR pfilename);
//关闭BMP文件
BOOL closeBmp(void);
//修正获取图像区域,返回TRUE表示已经修正过,否则表示没有修正过。
BOOL fixRect(PINT px,PINT py,PINT pwidth,PINT pheight);
};
cReadBmp::cReadBmp(LPCWSTR pfilename)
{
m_hFileMapping=NULL;
openBmp(pfilename);
}
BOOL cReadBmp::openBmp(LPCWSTR pfilename)
{
if(m_hFileMapping!=NULL)
{
closeBmp();
m_hFileMapping=NULL;
}
//打开文件内核对象
HANDLE hFile = CreateFile(pfilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//如果打开文件失败则返回
if (hFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
return FALSE;
}
//获取文件长度
DWORD dwFileSize = GetFileSize(hFile, NULL);
//映射文件视图
m_hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize , NULL);
CloseHandle(hFile);
if (m_hFileMapping == NULL)
{
return FALSE;
}
//映射到进程地址空间
m_pvFile = (PBYTE)MapViewOfFile(m_hFileMapping, FILE_MAP_READ, 0, 0, 0);
if (m_pvFile == NULL)
{
CloseHandle(m_hFileMapping);
return FALSE;
}
//BMP图片头长度
memcpy(&m_hl,&m_pvFile[0xa],4);
//BMP文件宽度
memcpy(&m_fw,&m_pvFile[0x12],4);
//BMP文件高度
memcpy(&m_fh,&m_pvFile[0x16],4);
//获取真实宽度
m_att=(((m_fw*24)+31)>>5)<<2;
//获取BMP图片的起始地址
m_bm=&m_pvFile[m_hl];
return TRUE;
}
BOOL cReadBmp::closeBmp(void)
{
BOOL result=FALSE;
if(m_hFileMapping!=NULL)
{
UnmapViewOfFile((LPCVOID)m_pvFile);
CloseHandle(m_hFileMapping);
result=TRUE;
}
m_pvFile=NULL;
m_hFileMapping=NULL;
return result;
}
cReadBmp::~cReadBmp(void)
{
if(m_hFileMapping!=NULL)
closeBmp();
}
BOOL cReadBmp::getPictureWidth(PINT pwidth)
{
if(m_hFileMapping!=NULL)
{
*pwidth=m_fw;
return TRUE;
}
return FALSE;
}
BOOL cReadBmp::getPictureHeight(PINT pheight)
{
if(m_hFileMapping!=NULL)
{
*pheight=m_fh;
return TRUE;
}
return FALSE;
}
HBITMAP cReadBmp::getBmpRect(int x,int y,int width,int height)
{
if(m_hFileMapping==NULL)
return NULL;
HBITMAP result=NULL;
int att;
BITMAPINFOHEADER bmih;
//生成返回数据快
PBYTE pBits,pCurBits;
fixRect(&x,&y,&width,&height); //获取窗口修正
bmih.biSize = sizeof (BITMAPINFOHEADER) ;
bmih.biWidth = width ;
bmih.biHeight = height ;
bmih.biPlanes = 1 ;
bmih.biBitCount = 24 ;
bmih.biCompression = BI_RGB ;
bmih.biSizeImage = 0 ;
bmih.biXPelsPerMeter = 0 ;
bmih.biYPelsPerMeter = 0 ;
bmih.biClrUsed = 0 ;
bmih.biClrImportant = 0 ;
result=CreateDIBSection(NULL,(BITMAPINFO *)&bmih,DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
pCurBits=pBits;
//宽度不足4的倍数的话要填满
att=(((width*24)+31)>>5)<<2;
for(int m=y;m<y+height;m++)
{
//if(m==5998)
//DebugBreak();
memcpy(pCurBits,&m_bm[m*m_att+x*3],width*3);
pCurBits+=att;
}
return result;
}
BOOL cReadBmp::fixRect(PINT px,PINT py,PINT pwidth,PINT pheight)
{
BOOL result=FALSE;
if(m_hFileMapping==NULL)
return result;
*py = m_fh - *py - *pheight; //坐标轴调整
if(*pwidth>m_fw)
{
*pwidth=m_fw;
result=TRUE;
}
if(*pheight>m_fh)
{
*pheight=m_fh;
result=TRUE;
}
if(*px<0)
{
*px=0;
result=TRUE;
}
if(*py<0)
{
*py=0;
result=TRUE;
}
if(*px+*pwidth>m_fw)
{
*px=m_fw-*pwidth;
//*pwidth=m_fw-*px;
result=TRUE;
}
if(*py+*pheight>m_fh)
{
*py=m_fh-*pheight;
//*pheight=m_fh-*py
result=TRUE;
}
return TRUE;
}