标题: 分块内存映射处理大文件-例子 [打印本页]

作者: 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