导航

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;
	}
}