|
//////////////////////////////////////////////////////////////////////////
// 該函數(shù)用于讀取從CCD攝像頭采集來的RAW視頻數(shù)據(jù)當(dāng)中的某一幀圖像,
// RAW視頻前596字節(jié)為頭部信息,可以從其中讀出視頻總的幀數(shù),
// 幀格式為1024*576*8
/*
參數(shù):
pszPath:文件名
dwFrame: 要讀取第幾幀,默認(rèn)讀取第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的倍數(shù) DWORD的倍數(shù) 這里是 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;
}
//構(gòu)造Bitmap文件頭BITMAPFILEHEADER
bitmapFileHeader.bfType = 0x4d42; // 很重要的標(biāo)志位 BM 標(biāo)識(shí)
bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * widthbytes);//bmp文件長度
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;
//構(gòu)造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;
//創(chuàng)建BMP內(nèi)存映像,寫入位圖頭部
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);
//構(gòu)造調(diào)色板 , 當(dāng)像素大于8位時(shí),就沒有調(diào)色板了。
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);
}
}
//////////////////////////////////////////////////////////////////////////
// 文件映射,從文件中查找圖像的數(shù)據(jù)
//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 ;// 標(biāo)準(zhǔn)塊大小
DWORD dwFrameSize = height*width; // 計(jì)算一幀圖像的數(shù)據(jù)量,不包括頭部信息
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;//內(nèi)存緩沖剩余的字節(jié)
if ( dwTmp >= dwFrameSize )
{
if(dwCurrentFrame == dwFrame)
{
memcpy(curr, curr2, dwFrameSize);
bLoop = FALSE;
}
curr2 += dwFrameSize;
}else//內(nèi)存中不夠一幀數(shù)據(jù)
{
DWORD dwTmp2 = dwFrameSize - dwTmp;// 一副完整的幀還需要dwTmp2字節(jié)
if (dwCurrentFrame == dwFrame)
{
memcpy(curr, curr2, dwTmp);
curr += dwTmp;
}
// 檢查還可以映射多少字節(jié)的東東到內(nèi)存里面
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)// 一定要檢查,不然可能內(nèi)存映射失敗
{
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 ) // 到達(dá)文件末尾
{
bLoop = FALSE;
}
}
//將內(nèi)存流 pMyBmp 轉(zhuǎn)為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;
}
|
|