利用COM組件IPicture讀取jpg、gif、bmp圖片文件數據和顯示圖片
1.讀取圖片數據
函數原型:bool LoadImage(const char *pName, unsigned char *pBitData);
函數功能,讀取pName指向的圖片文件的位圖數據
bool LoadImage(const char *pName, unsigned char *pBitData)
{
HDC hdcTemp; // DC用來保存位圖
HBITMAP hbmpTemp; // 保存臨時位圖
IPicture *pPicture; // 定義IPicture Interface
OLECHAR wszPath[MAX_PATH+1]; // 圖片的完全路徑
char szPath[MAX_PATH+1]; // 圖片的完全路徑
long lWidth; // 圖像寬度
long lHeight; // 圖像高度
long lWidthPixels; // 圖像的寬帶(以像素為單位)
long lHeightPixels; // 圖像的高帶(以像素為單位)
GLint glMaxTexDim ; // 保存紋理的最大尺寸
if (strstr(pName, "http://")) // 如果路徑包含 http:// 則…
{
strcpy(szPath, pName); // 把路徑拷貝到 szPath
}
else // 否則從文件導入圖片
{
GetCurrentDirectory(MAX_PATH, szPath); // 取得當前路徑
strcat(szPath, "\\"); // 添加字符"\"
strcat(szPath, pName); // 添加圖片的相對路徑
}
MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); // 把ASCII碼轉化為Unicode標準碼
HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);
if(FAILED(hr)) // 如果導入失敗
{
// 圖片載入失敗出錯信息
MessageBox (HWND_DESKTOP, "圖片導入失敗!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
hdcTemp = CreateCompatibleDC(GetDC(0)); // 建立窗口設備描述表
if(!hdcTemp) // 建立失敗?
{
pPicture->Release(); // 釋放IPicture
// 圖片載入失敗出錯信息
MessageBox (HWND_DESKTOP, "圖片導入失敗!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // 取得支持的紋理最大尺寸
pPicture->get_Width(&lWidth); // 取得IPicture 寬度 (轉換為Pixels格式)
lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight); // 取得IPicture 高度 (轉換為Pixels格式)
lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);
// 調整圖片到最好的效果
if (lWidthPixels <= glMaxTexDim) // 圖片寬度是否超過顯卡最大支持尺寸
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else // 否則,將圖片寬度設為顯卡最大支持尺寸
lWidthPixels = glMaxTexDim;
if (lHeightPixels <= glMaxTexDim) // 圖片高度是否超過顯卡最大支持尺寸
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else // 否則,將圖片高度設為顯卡最大支持尺寸
lHeightPixels = glMaxTexDim; // 建立一個臨時位圖
BITMAPINFO bi = {0}; // 位圖的類型
DWORD *pBits = 0; // 指向位圖Bits的指針
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // 設置結構大小
bi.bmiHeader.biBitCount = 32; // 32 位
bi.bmiHeader.biWidth = lWidthPixels; // 寬度像素值
bi.bmiHeader.biHeight = lHeightPixels; // 高度像素值
bi.bmiHeader.biCompression = BI_RGB; // RGB 格式
bi.bmiHeader.biPlanes = 1; // 一個位平面
// 建立一個位圖這樣我們可以指定顏色和深度 并訪問每位的值
hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);
if(!hbmpTemp) // 建立失敗?
{
DeleteDC(hdcTemp); // 刪除設備描述表
pPicture->Release(); // 釋放IPicture
// 圖片載入失敗出錯信息
MessageBox (HWND_DESKTOP, "圖片導入失敗!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
SelectObject(hdcTemp, hbmpTemp); //選擇臨時DC句柄和臨時位圖對象
// 在位圖上繪制IPicture
pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);
// 將BGR轉換為RGB 將ALPHA值設為255
width = lWidthPixels; height = lHeightPixels;
pBitData = new unsigned char[lWidthPixels * lHeightPixels * 4];
// 循環遍歷所有的像素
for(long i = 0; i < lWidthPixels * lHeightPixels; i++)
{
BYTE* pPixel = (BYTE*)(&pBits[i]); // 獲取當前像素
pBitData[i*4] = pPixel[2];
pBitData[i*4+1] = pPixel[1];
pBitData[i*4+2] = pPixel[0];
pBitData[i*4+3] = 255;
}
DeleteObject(hbmpTemp); // 刪除對象
DeleteDC(hdcTemp); // 刪除設備描述表
pPicture->Release(); // 釋放 IPicture
return true; // 返回 TRUE
}
2.顯示圖片
函數原型:HRESULT ShowPicture(CString lpImageFile, HWND hWnd, int nScrWidth, int nScrHeight)
函數功能,讀取lpImageFile指向的圖片文件,并且顯示以nScrWidth*nScrHeight顯示在hWnd中
HRESULT ShowPicture(CString lpImageFile, HWND hWnd, int nScrWidth, int nScrHeight)
{
HDC hDC_Temp=::GetDC(hWnd);
IPicture *pPic;
IStream *pStm;
BOOL bResult;
HANDLE hFile=NULL;
DWORD dwFileSize,dwByteRead;
//打開硬盤中的圖形文件
hFile=CreateFile(lpImageFile,GENERIC_READ,
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile!=INVALID_HANDLE_VALUE)
{
dwFileSize=GetFileSize(hFile,NULL);//獲取文件字節數
if (dwFileSize==0xFFFFFFFF)
return E_FAIL;
}
else
{
return E_FAIL;
}
//分配全局存儲空間
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
LPVOID pvData = NULL;
if (hGlobal == NULL)
{
AfxMessageBox(_T("圖片分配內存出錯!"));
return E_FAIL;
}
if ((pvData = GlobalLock(hGlobal)) == NULL)//鎖定分配內存塊
{
AfxMessageBox(_T("內存塊鎖定出問題!"));
return E_FAIL;
}
ReadFile(hFile, pvData, dwFileSize, &dwByteRead, NULL);//把文件讀入內存緩沖區
GlobalUnlock(hGlobal);
if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStm) != S_OK)
{
AfxMessageBox(_T("流初始化失敗!"));
return E_FAIL;
}
//裝入圖形文件
bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);
if(FAILED(bResult))
{
AfxMessageBox(_T("圖形文件裝載出錯!"));
return E_FAIL;
}
OLE_XSIZE_HIMETRIC hmWidth;//圖片的真實寬度
OLE_YSIZE_HIMETRIC hmHeight;//圖片的真實高度
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
//將圖形輸出到屏幕上
bResult=pPic->Render(hDC_Temp,0,0,nScrWidth,nScrHeight,
0,hmHeight,hmWidth,-hmHeight,NULL);
CloseHandle(hFile);//關閉打開的文件
pPic->Release();
// Free memory.
GlobalFree(hGlobal);
if (SUCCEEDED(bResult))
{
return S_OK;
}
else
{
AfxMessageBox(_T("圖形文件裝載出錯!"));
return E_FAIL;
}
}