标题:
分块内存映射处理大文件-例子
[打印本页]
作者:
bibi
时间:
2015-4-18 20:40
标题:
分块内存映射处理大文件-例子
//////////////////////////////////////////////////////////////////////////
// 该函数用于读取从CCD摄像头采集来的RAW视频数据当中的某一帧图像,
// RAW视频前596字节为头部信息,可以从其中读出视频总的帧数,
// 帧格式为1024*576*8
/*
参数:
pszPath:文件名
dwFrame: 要读取第几帧,默认读取第2帧
*/
BOOL MyFreeImage::LoadXRFrames(TCHAR *pszPath, DWORD dwFrame/* = 2*/ )
{
// get the frames of X-Ray frames
BOOL bLoop = TRUE;
inti;
int width = 1024;
int height = 576;
int bitcount = 8;//1, 4, 8, 24, 32
//////////////////////////////////////////////////////////////////////////
//Build bitmap header
BITMAPFILEHEADER bitmapFileHeader;
BITMAPINFOHEADER bitmapInfoHeader;
BYTE rgbquad[4];// RGBQUAD
int index = 0;
DWORD widthbytes = ((bitcount*width + 31)/32)*4;//每行都是4的倍数 DWORD的倍数 这里是 576-
TRACE1("widthbytes=%d\n", widthbytes);
switch(bitcount) {
case 1:
index = 2;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4);
break;
case 4:
index = 16;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4);
break;
case 8:
index = 256;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD));
break;
case 24:
case 32:
index = 0;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
break;
default:
break;
}
//构造Bitmap文件头BITMAPFILEHEADER
bitmapFileHeader.bfType = 0x4d42; // 很重要的标志位 BM 标识
bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * widthbytes);//bmp文件长度
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;
//构造Bitmap文件信息头BITMAPINFOHEADER
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = width;
bitmapInfoHeader.biHeight = height;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = bitcount;
bitmapInfoHeader.biCompression = BI_RGB; // 未压缩
bitmapInfoHeader.biSizeImage = height * widthbytes;
bitmapInfoHeader.biXPelsPerMeter = 3780;
bitmapInfoHeader.biYPelsPerMeter = 3780;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
//创建BMP内存映像,写入位图头部
BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize];// 我的位图pMyBmp
BYTE *curr = pMyBmp;// curr指针指示pMyBmp的位置
memset(curr, 0, bitmapFileHeader.bfSize);
//写入头信息
memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));
curr = pMyBmp + sizeof(BITMAPFILEHEADER);
memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
curr += sizeof(BITMAPINFOHEADER);
//构造调色板 , 当像素大于8位时,就没有调色板了。
if(bitcount == 8)
{
rgbquad[3] = 0;//rgbReserved
for(i = 0; i < index; i++)
{
rgbquad[0] = rgbquad[1] = rgbquad[2] = i;
memcpy(curr, rgbquad, sizeof(RGBQUAD));
curr += sizeof(RGBQUAD);
}
}else if(bitcount == 1)
{
rgbquad[3] = 0;//rgbReserved
for(i = 0; i < index; i++)
{
rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256;
memcpy(curr, rgbquad, sizeof(RGBQUAD));
curr += sizeof(RGBQUAD);
}
}
//////////////////////////////////////////////////////////////////////////
// 文件映射,从文件中查找图像的数据
//Open the real file on the file system
HANDLE hFile = CreateFile(pszPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
ATLTRACE(_T("MapFile, Failed in call to CreateFile, Error:%d\n"), dwError);
SetLastError(dwError);
bLoop = FALSE;
return FALSE;
}
//Create the file mapping object
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapping == NULL)
{
DWORD dwError = GetLastError();
ATLTRACE(_T("MapFile, Failed in call to CreateFileMapping, Error:%d\n"), dwError);
// Close handle
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
SetLastError(dwError);
bLoop = FALSE;
return FALSE;
}
// Retrieve allocation granularity
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;
// Retrieve file size
// Retrieve file size
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
CloseHandle(hFile);
// Read Image
__int64 qwFileOffset = 0;// 偏移地址
DWORD dwBytesInBlock = 0,// 映射的块大小
dwStandardBlock = 100* dwAllocationGranularity ;// 标准块大小
DWORD dwFrameSize = height*width; // 计算一帧图像的数据量,不包括头部信息
DWORD dwCurrentFrame = 1;
dwBytesInBlock = dwStandardBlock;
if (qwFileSize < dwStandardBlock)
dwBytesInBlock = (DWORD)qwFileSize;
//Map the view
LPVOID lpData = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS,
static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);
if (lpData == NULL)
{
DWORD dwError = GetLastError();
ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
// Close Handle
if (hMapping != NULL)
{
CloseHandle(hMapping);
hMapping = NULL;
}
SetLastError(dwError);
bLoop = FALSE;
return FALSE;
}
BYTE *lpBits = (BYTE *)lpData;
BYTE *curr1, *curr2, *lpEnd;
curr1 = lpBits;// seek to start
curr2 = lpBits + 596;// seek to first frame
lpEnd = lpBits + dwBytesInBlock;// seek to end
// Read video infomation
KMemDataStream streamData( curr1, dwBytesInBlock);
ReadXRHeader(streamData);
while(bLoop)
{
DWORD dwTmp = lpEnd - curr2;//内存缓冲剩余的字节
if ( dwTmp >= dwFrameSize )
{
if(dwCurrentFrame == dwFrame)
{
memcpy(curr, curr2, dwFrameSize);
bLoop = FALSE;
}
curr2 += dwFrameSize;
}else//内存中不够一帧数据
{
DWORD dwTmp2 = dwFrameSize - dwTmp;// 一副完整的帧还需要dwTmp2字节
if (dwCurrentFrame == dwFrame)
{
memcpy(curr, curr2, dwTmp);
curr += dwTmp;
}
// 检查还可以映射多少字节的东东到内存里面
if ( qwFileSize - qwFileOffset < dwStandardBlock)
dwBytesInBlock = (DWORD)(qwFileSize - qwFileOffset);
qwFileOffset += dwBytesInBlock;
UnmapViewOfFile(lpData);
lpData = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS,
static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);
if (lpData == NULL)// 一定要检查,不然可能内存映射失败
{
DWORD dwError = GetLastError();
ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
SetLastError(dwError);
bLoop = FALSE;
break;
}
curr2 = lpBits = (BYTE *)lpData;
lpEnd = lpBits + dwBytesInBlock;// seek to end
if (dwCurrentFrame == dwFrame)
{
memcpy(curr, curr2, dwTmp2);
bLoop = FALSE;
}
curr2 += dwTmp2;
}
dwCurrentFrame++;
if (dwCurrentFrame > ((LPKINFO)m_VideoInfoHeader)->frames ) // 到达文件末尾
{
bLoop = FALSE;
}
}
//将内存流 pMyBmp 转为bitmap
KMemDataStream stream(pMyBmp, bitmapFileHeader.bfSize, true);
if(!LoadFromMemory(FIF_BMP, stream))
return FALSE;
//
if (lpData != NULL)
{
//FlushViewOfFile(lpData, 0);
UnmapViewOfFile(lpData);
lpData = NULL;
}
//remove the file mapping
if (hMapping != NULL)
{
CloseHandle(hMapping);
hMapping = NULL;
}
return TRUE;
}
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1