天天看點

WINCE圖檔使用類,支援各種格式,支援旋轉縮略圖縮放等操作

頭檔案如下:

/********************************************************************
    Copyright(c) 2011, 
 	All rights reserved.
	purpose:	圖檔加載使用類

    目前版本:   1.0
    作    者:   zhangwf
    建立日期:   2011:9:6
    完成日期:   
    
    取代版本:
    作    者:
    完成日期:   
*********************************************************************/
#ifndef _WF_BITMAP_H_
#define _WF_BITMAP_H_
//
#include <Windows.h>
#include <imaging.h>
#include "WFRect.h"
//
class CWFBitmap
{
public:
	// 構造函數
	CWFBitmap();

	// 析構函數
	~CWFBitmap();

	// 拷貝構造函數
	CWFBitmap(const CWFBitmap &other);

	// 指派函數
	CWFBitmap& operator=(const CWFBitmap &other);

//
public: // 圖像加載釋放、圖像大小相關接口
	// 從檔案中加載
	BOOL LoadFromFile(
		LPCWSTR lpFileName         // 檔案絕對路徑
		);

	// 從資源中加載,例如LoadFromResource(MAKEINTRESOURCE(IDR_BACKIMG), _T("PNG"));
	BOOL LoadFromResource(
		LPCWSTR lpName,            // 資源名稱比如:MAKEINTRESOURCE(IDR_BACKIMG)            
		LPCWSTR lpType             // 資源類型比如:_T("PNG")
		);

	// 從緩沖區中加載(該緩沖區為整個圖像檔案資料緩沖區,包括檔案頭等一切檔案資訊)
	BOOL LoadFromBuffer(
		const unsigned char *pBuf, // 緩沖區位址
		DWORD dwcbBufSize          // 緩沖區位元組大小
		);

	// 從IImage對象中加載
	BOOL LoadFromIImage(
		IImage *pIImage            // IImage對象
		);

	// 從IBitmapImage對象中加載(内部會生成新的IBitmapImage用于拷貝原資料)
	BOOL LoadFromIBitmapImage(
		IBitmapImage *pBitmapImage // IBitmapImage對象 
		);

	// 釋放占用的資源
	void Release(void);

	// 獲得圖像的寬度,未加載到圖檔傳回0
	DWORD Width() const;

	// 獲得圖像的高度,未加載到圖檔傳回0
	DWORD Height() const; 

//
public: // 圖像繪制相關接口
	// 繪制整個圖像到指定位置(會把圖像壓縮或拉伸填充到指定區域)
	void Draw(
		HDC hdc,                   // 繪制DC 
		const RECT* dstRect        // 繪制目标區域
		);	

	// 繪制圖像上一部分到指定的部分(先繪制到記憶體DC,再繪制到目标DC)
	void Draw(
		HDC hdc,                   // 繪制DC
		const RECT* dstRect,       // 繪制目标區域
		const RECT* srcRect        // 待繪制圖檔上的指定區域,NULL表示整個圖檔
		);

	// 繪制圖像上一部分到指定的區域(支援alpha混合)
	void DrawAlpha(
		HDC hdc,                   // 繪制DC
		const RECT* dstRect,       // 繪制目标區域
		const RECT* srcRect        // 待繪制圖檔上的指定區域,NULL表示整個圖檔
		);

	// 繪制整個圖像到自定義矩形類型區域(會把圖像壓縮或拉伸填充到指定區域)
	void DrawEx(
		HDC hdc,                   // 繪制DC 
		const CWFRect* dstRect     // 繪制目标區域
		);

	// 繪制圖像上一部分到指定的自定義矩形類型區域(先繪制到記憶體DC,再繪制到目标DC)
	void DrawEx(
		HDC hdc,                   // 繪制DC
		const CWFRect* dstRect,    // 繪制目标區域
		const CWFRect* srcRect     // 待繪制圖檔上的指定區域,NULL表示整個圖檔
		);

	// 繪制圖像上一部分到指定的自定義矩形類型區域(支援alpha混合)
	void DrawAlphaEx(
		HDC hdc,                   // 繪制DC
		const CWFRect* dstRect,    // 繪制目标區域
		const CWFRect* srcRect     // 待繪制圖檔上的指定區域,NULL表示整個圖檔
		);

//
public: // 圖像縮放旋轉等相關接口
	// 縮放圖像到IImage對象中,不改變自身資料
	typedef IImage* PWFIImage;
	BOOL ZoomToIImage(
		PWFIImage &pDstIImage,     // 存放縮放後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		DWORD dwNewWidth,          // 縮放後圖像寬度
		DWORD dwNewHeight          // 縮放後圖像高度
		);

	// 縮放圖像(指定縮放後圖像的寬度和高度)
	BOOL Zoom(
		DWORD dwNewWidth,          // 縮放後圖像寬度
		DWORD dwNewHeight          // 縮放後圖像高度
		);
	
	// 縮放圖像到目标對象中(指定縮放後圖像的寬度和高度),不改變對象自身
	BOOL Zoom(
		CWFBitmap &dstBitmap,      // 帶出縮放後的圖像
		DWORD dwNewWidth,          // 縮放後圖像寬度
		DWORD dwNewHeight          // 縮放後圖像高度
		);

	// 縮放圖像(指定縮放X方向,Y方向縮放比率)
	BOOL ZoomEx(
		double dbZoomXRatio,       // X方向縮放率
		double dbZoomYRatio        // Y方向縮放率
		);

	// 縮放圖像到目标對象中(指定縮放X方向,Y方向縮放比率),不改變對象自身
	BOOL ZoomEx(
		CWFBitmap &dstBitmap,      // 帶出縮放後的圖像
		double dbZoomXRatio,       // X方向縮放率
		double dbZoomYRatio        // Y方向縮放率
		);

	// 按特定角度旋轉圖像到IImage對象中,不改變自身資料
	// 順時針旋轉,隻支援90, 180, 270, or 360
	BOOL RotateSpecificAngleToIImage(
		PWFIImage &pDstIImage,     // 存放旋轉後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		float fSpecificAngle       // 特定旋轉角度(機關:度)
		);

	// 按特定角度旋轉圖像
	// 順時針旋轉,隻支援90, 180, 270, or 360
	BOOL RotateSpecificAngle(
		float fSpecificAngle       // 特定旋轉角度(機關:度)
		);

	// 按特定角度旋轉圖像到目标對象中,不改變對象自身
	// 順時針旋轉,隻支援90, 180, 270, or 360
	BOOL RotateSpecificAngle(
		CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
		float fSpecificAngle       // 特定旋轉角度(機關:度)
		);

	// 翻轉圖像到IImage對象中,不改變自身資料
	BOOL FlipToIImage(
		PWFIImage &pDstIImage,     // 存放翻轉後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		BOOL bFilpX,               // 是否反轉X方向
		BOOL bFlipY                // 是否反轉Y方向
		);

	// 翻轉圖像
	BOOL Flip(
		BOOL bFilpX,               // 是否反轉X方向
		BOOL bFlipY                // 是否反轉Y方向
		);

	// 翻轉圖像到目标對象中,不改變對象自身
	BOOL Flip(
		CWFBitmap &dstBitmap,      // 帶出翻轉後的圖像
		BOOL bFilpX,               // 是否反轉X方向
		BOOL bFlipY                // 是否反轉Y方向
		);

	// 裁剪圖像上指定區域到IImage對象中,不改變自身資料
	BOOL CutToIImage(
		PWFIImage &pDstIImage,     // 存放裁剪圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		const RECT *pCutRect       // 在圖像上裁剪的區域
		);

	// 裁剪圖像(圖像改變為指定裁剪區域的圖像)
	BOOL Cut(
		const RECT *pCutRect       // 在圖像上裁剪的區域
		);

	// 裁剪圖像到目标對象中,不改變對象自身
	BOOL Cut(
		CWFBitmap &dstBitmap,      // 帶出裁剪到的圖像
		const RECT *pCutRect       // 在圖像上裁剪的區域
		);

	// 生成縮略圖到指定IImage對象中,不改變自身資料
	BOOL ThumbnailToIImage(
		PWFIImage &pDstIImage,     // 存放縮略圖的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		DWORD dwThumbWidth,        // 縮略圖寬度
		DWORD dwThumbHeight        // 縮略圖高度
		); 

	// 生成縮略圖(指定像素寬度高度)(圖像改變為縮略圖)
	BOOL Thumbnail(
		DWORD dwThumbWidth,        // 縮略圖寬度
		DWORD dwThumbHeight        // 縮略圖高度
		);

	// 生成縮略圖(指定縮放比率)(圖像改變為縮略圖)
	BOOL ThumbnailEx(
		double dbXRatio,           // X方向縮放率
		double dbYRatio            // Y方向縮放率
		);

	// 生成縮略圖到目标對象中(指定像素寬度高度),不改變對象自身
	BOOL Thumbnail(
		CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
		DWORD dwThumbWidth,        // 縮略圖寬度
		DWORD dwThumbHeight        // 縮略圖高度
		);

	// 生成縮略圖到目标對象中(指定縮放比率),不改變對象自身
	BOOL ThumbnailEx(
		CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
		double dbXRatio,           // X方向縮放率
		double dbYRatio            // Y方向縮放率
		);

	// 圖像旋轉任意角度到IBitmapImage對象中,不改變自身資料
	// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngleToIImage	
	typedef IBitmapImage* PWFIBitmapImage;
	BOOL RotateToIBitmapImage(
		PWFIBitmapImage &pDstIBitmapImage,     // 存放旋轉後圖像的IBitmapImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
		float fAngle                           // 特定旋轉角度(機關:度)
		);

	// 按任意角度旋轉圖像	
	// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngle
	BOOL Rotate(
		float fAngle               // 特定旋轉角度(機關:度)
		);

	// 按任意角度旋轉圖像到目标對象中,不改變對象自身
	// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngle
	BOOL Rotate(
		CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
		float fAngle               // 特定旋轉角度(機關:度)
		);

//
public: // 取得圖像顔色資料相關接口
	// 獲得圖像資料(隻含有各個點的顔色資訊)
	BOOL GetColorBuf(
		unsigned char *pDataBuf,     // 存放圖像資料緩沖區
		DWORD dwcbBufSize,           // 緩沖區實際大小(需要的大小通常是(寬度*高度*4))
		DWORD *pdwRealGetBytes=NULL  // 實際取得資料位元組大小
		);

	// 獲得圖檔資料(隻含有各個點的顔色資訊)緩沖區位址,傳回NULL表示沒有圖檔資料
	const unsigned char* GetColorBufAddr(
		DWORD *pdwcbBufSize          // 帶出顔色緩沖區位元組大小
		);

//
private: // 私有成員變量	
	IImage *m_pImage;             // 儲存圖像資料
	ImageInfo m_ImageInfo;        // 圖像資訊
	unsigned char *m_pImgDataBuf; // 儲存原始圖像資料(帶有alpha通道資料)
	DWORD m_dwcbImgDataBufSize;   // 圖像資料位元組大小
	IBitmapImage *m_pBitmapImage; // 位圖指針	

	// 先繪制到記憶體DC上,再次繪制直接由記憶體DC拷貝到目标DC
	HDC m_hDrawDC;         // 臨時儲存DC
	HBITMAP m_hBitmap;     // 臨時儲存圖檔
	HBITMAP m_hOldBitmap; 

	// 靜态成員變量
	static DWORD m_dwObjCounts;                  // 對象數量
	static IImagingFactory *m_pImagingFactory;   // Image工廠接口對象

private: // 私有函數
	// 建立與釋放Image工廠接口對象
	static BOOL CreateImagingFactory(void);
	static void DeleteImagingFactory(void);

	// 為圖檔建立記憶體DC,及清除記憶體DC
	HDC CreateImgDC(HDC hdc);
	void DeleteImgDC(void);

	// 取得圖檔原始資料,及銷毀圖檔原始資料
	BOOL CreateImgDateBuf(void);
	void DeleteImgDateBuf(void);

	// 拷貝一個IBitmapImage到另一個IBitmapImage中
	static BOOL CopyBitmapImage(
		IBitmapImage *pSrcBitmapImage,           // 源IBitmapImage
		PWFIBitmapImage &pDstBitmapImage         // 目标IBitmapImage
		);
};

//
#endif
           

源檔案如下:

/********************************************************************
    Copyright(c) 2011, 
 	All rights reserved.
	purpose:	圖檔加載使用類

    目前版本:   1.0
    作    者:   zhangwf
    建立日期:   2011:9:6
    完成日期:   
    
    取代版本:
    作    者:
    完成日期:   
*********************************************************************/
#include "WFBitmap.h"
#include <initguid.h>
#include <imgguids.h>
//
// 聲明及實作不需要給出接口的全局函數
// 路徑是否有效
BOOL WFBING_PathEffective(LPCWSTR lpPathName);

// 旋轉圖像資料緩沖區
typedef BYTE* PWFBYTE;
BOOL WFBING_RotateImageBuffer(
	const BYTE* pSrcBuf,                 // 待旋轉原圖像緩沖區(32位色,每個點有ARGB四個通道),緩沖區大小不能小于高度*寬度*4
	DWORD dwSrcWidth,                    // 原圖像像素寬度
	DWORD dwSrcHeight,                   // 原圖像像素高度
	double dbRotateAngle,                // 順時針旋轉角度(機關:度)
	PWFBYTE &pDstBuf,                    // 輸出旋轉後圖像緩沖區(32位色,每個點有ARGB四個通道),帶出的緩沖區大小為高度*寬度*4,需要外部釋放
	DWORD &dwDstWidth,                   // 輸出旋轉後圖像像素寬度 
	DWORD &dwDstHeight,                  // 輸出旋轉後圖像像素高度
	DWORD dwFillColor = 0x00FFFFFF       // 填充色(旋轉後的圖像比原圖像大,空的部分使用該白色全透明顔色填充,ALPHA通道為0表示全透明)
	);

//
// 路徑是否有效
BOOL WFBING_PathEffective(LPCWSTR lpPathName)
{
	// 參數有效性
	if (lpPathName == NULL)
	{
		return FALSE;
	}

	// 是否可以取得屬性
	return (::GetFileAttributesW(lpPathName) == INVALID_FILE_ATTRIBUTES) ? FALSE : TRUE;
}

// 旋轉圖像資料緩沖區
typedef BYTE* PWFBYTE;
BOOL WFBING_RotateImageBuffer(
	const BYTE* pSrcBuf,                 // 待旋轉原圖像緩沖區(32位色,每個點有ARGB四個通道)
	DWORD dwSrcWidth,                    // 原圖像像素寬度
	DWORD dwSrcHeight,                   // 原圖像像素高度
	double dbRotateAngle,                // 順時針旋轉角度(機關:度)
	PWFBYTE &pDstBuf,                    // 輸出旋轉後圖像緩沖區(32位色,每個點有ARGB四個通道),帶出的緩沖區大小為高度*寬度*4,需要外部釋放
	DWORD &dwDstWidth,                   // 輸出旋轉後圖像像素寬度 
	DWORD &dwDstHeight,                  // 輸出旋轉後圖像像素高度
	DWORD dwFillColor                    // 填充色(旋轉後的圖像比原圖像大,空的部分使用該白色全透明顔色填充,ALPHA通道為0表示全透明)
	)
{
	// 參數有效性
	if (pSrcBuf==NULL || dwSrcWidth==0 || dwSrcHeight==0)
	{
		return FALSE;
	}

	// 計算有效的旋轉角,旋轉一周視為沒有旋轉
	double dbAngle = (dbRotateAngle - (int)dbRotateAngle) + ((int)dbRotateAngle%360);

	// 旋轉角度過小不需要旋轉,直接拷貝緩沖區
	if (dbAngle>=-0.0000001 && dbAngle<=0.0000001)
	{
		DWORD dwDstBufSize = dwSrcWidth*dwSrcHeight*4;
		pDstBuf = new BYTE[dwDstBufSize];
		if (pDstBuf == NULL)
		{
			printf("Rotate Angle Zero New Buf Error!\n");
			return FALSE;
		}

		// 拷貝資料
		memset(pDstBuf, 0, dwDstBufSize);
		memcpy(pDstBuf, pSrcBuf, dwDstBufSize);
		dwDstWidth = dwSrcWidth;
		dwDstHeight = dwSrcHeight;
		return TRUE;
	}

	// 計算sin(dbAngle)和cos(dbAngle)的值
	double dbPI = 3.1415926535;
	double dbA = dbAngle*dbPI/180;
	double dbSinA = sin(dbA);
	double dbCosA = cos(dbA);

	// 計算除去左上頂點外的其他三個頂點旋轉後坐标
	// 旋轉坐标公式:X'= X*cosθ -  Y*sinθ;Y' =  X*sinθ + Y*cosθ;其中θ為順時針旋轉角度
	// 以圖像左上角為原點,向右為X正方向,向下為Y正方向;
	// 其他頂點坐标為(dwSrcWidth, 0),(dwSrcWidth, dwSrcHeight),(0, dwSrcHeight)
	double dbX1 = (double)dwSrcWidth*dbCosA - 0*dbSinA;
	double dbY1 = (double)dwSrcWidth*dbSinA + 0*dbCosA;
	double dbX2 = (double)dwSrcWidth*dbCosA - (double)dwSrcHeight*dbSinA;
	double dbY2 = (double)dwSrcWidth*dbSinA + (double)dwSrcHeight*dbCosA;
	double dbX3 = 0*dbCosA - (double)dwSrcHeight*dbSinA;
	double dbY3 = 0*dbSinA + (double)dwSrcHeight*dbCosA;

	// 計算旋轉後4個頂點XY方向最大最小坐标值,用于确定旋轉後圖像大小
	double dbMaxX = max(dbX3, max(dbX2, max(0, dbX1))); 
	double dbMinX = min(dbX3, min(dbX2, min(0, dbX1))); 
	double dbMaxY = max(dbY3, max(dbY2, max(0, dbY1))); 
	double dbMinY = min(dbY3, min(dbY2, min(0, dbY1))); 

	// 計算旋轉後圖像的寬度和高度
	DWORD dwUseWidth = (DWORD)fabs(dbMaxX - dbMinX) + 1;
	DWORD dwUseHeight = (DWORD)fabs(dbMaxY - dbMinY) + 1;

	// 為旋轉後圖像申請資料緩沖區
	pDstBuf = new BYTE[dwUseWidth*dwUseHeight*4];
	if (pDstBuf == NULL)
	{
		printf("Rotate Angle New Buf[%d] Error!\n", dwUseWidth*dwUseHeight*4);
		return FALSE;
	}

	// 帶出旋轉後圖像大小
	dwDstWidth = dwUseWidth;
	dwDstHeight = dwUseHeight;

	// 旋轉後的圖像會出現超出坐标系區域,需要坐标平移
	// 旋轉平移變換坐标公式:X'= X*cosθ -  Y*sinθ - dbMinX;Y' =  X*sinθ + Y*cosθ - dbMinY;其中θ為順時針旋轉角度
	// 填充旋轉後圖像資料時就需要直到每個點對應原圖像位置,是以公式變換為:
	// X = (X'+dbMinX)*cosθ + (Y'+dbMinY)*sinθ;
	// Y = (Y'+dbMinY)*conθ - (X'+dbMinX)*sinθ;
	// 計算出的原圖像上(X,Y)坐标不是整數,到底選取哪一點的顔色值來填充旋轉後的區域呢?
	// 若(X,Y)不在原圖像區域上,則用預設顔色填充;
	// 若在元圖像上,從圖像品質及效率的考慮上,通常選擇雙線性插值擷取旋轉後該位置的顔色
	// 雙線性插值取的是與(X,Y)臨近的4個點的顔色值來計算旋轉後該位置的顔色值
	/************************************************************************************
	雙線性内插值:
	    對于一個目的像素,設定坐标通過反向變換得到的浮點坐标為(i+u,j+v),
		其中i、j均為非負整數,u、v為[0,1)區間的浮點數,則這個像素得值f(i+u,j+v)可由原圖像
		中坐标為 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所對應的周圍四個像素的值決定,
		即:f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
		其中f(i,j)表示源圖像(i,j)處的的像素值,以此類推。
	************************************************************************************/
	// 周遊目标圖像上每一個點,依次填充顔色
	double dbSrcX = 0;           // 對應原圖像上X坐标位置(不為整數)
	double dbSrcY = 0;           // 對應原圖像上Y坐标位置(不為整數)
	DWORD dwSrcI = 0;            // 對應dbSrcX的整數部分
	DWORD dwSrcJ = 0;            // 對應dbSrcY的整數部分
	double dbSrcU = 0;           // 對應dbSrcX-dwSrcI
	double dbSrcV = 0;           // 對應dbSrcY-dwSrcJ

	DWORD *pdwDstBuf = (DWORD*)pDstBuf;  // 以4位元組方式使用目标緩沖區
	DWORD *pdwSrcBuf = (DWORD*)pSrcBuf;  // 以4位元組方式使用原圖像緩沖區
	BYTE *pByteTmpBuf = NULL;            // 臨時使用指針

	DWORD *pSrcIJ = NULL;        // (I,J)位置顔色
	DWORD *pSrcI1J = NULL;       // (I+1,J)位置顔色
	DWORD *pSrcIJ1 = NULL;       // (I,J+1)位置顔色
	DWORD *pSrcI1J1 = NULL;      // (I+1,J+1)位置顔色
	
	DWORD dwY = 0;
	DWORD dwX = 0;
	DWORD dwColorBit = 0;
	for (dwY=0; dwY<dwUseHeight; dwY++)
	{
		for (dwX=0; dwX<dwUseWidth; dwX++)
		{
			// 坐标變換公式
			// X = (X'+dbMinX)*cosθ + (Y'+dbMinY)*sinθ;
			// Y = (Y'+dbMinY)*conθ - (X'+dbMinX)*sinθ;
			dbSrcX = ((double)dwX + dbMinX)*dbCosA + ((double)dwY + dbMinY)*dbSinA;
			dbSrcY = ((double)dwY + dbMinY)*dbCosA - ((double)dwX + dbMinX)*dbSinA;

			// 坐标點不在原圖像區域,使用預設顔色填充
			if (dbSrcX<0 || dbSrcX>=(double)dwSrcWidth || dbSrcY<0 || dbSrcY>=(double)dwSrcHeight)
			{
				pdwDstBuf[dwY*dwUseWidth + dwX] = dwFillColor;
			}
			// 在原圖像範圍内,則使用雙線性插值計算目前顔色
			else
			{
				// 計算位置
				dwSrcI = (DWORD)dbSrcX;
				dwSrcJ = (DWORD)dbSrcY;
				dbSrcU = dbSrcX - dwSrcI;
				dbSrcV = dbSrcY - dwSrcJ;

				// 得到臨近4個位置顔色位置指針
				pSrcIJ = pdwSrcBuf + (dwSrcJ*dwSrcWidth + dwSrcI);
				pSrcI1J = (dwSrcI+1 < dwSrcWidth) ? (pSrcIJ + 1) : pSrcIJ;
				pSrcI1J1 = (dwSrcI+1<dwSrcWidth && dwSrcJ+1<dwSrcHeight) ? (pdwSrcBuf + ((dwSrcJ+1)*dwSrcWidth + dwSrcI + 1)) : pSrcIJ;
				pSrcIJ1 = (dwSrcJ+1 < dwSrcHeight) ? (pdwSrcBuf + ((dwSrcJ+1)*dwSrcWidth + dwSrcI)) : pSrcIJ;

				// 根據插值公式計算顔色值
				// f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
				pByteTmpBuf = (BYTE*)(pdwDstBuf + (dwY*dwUseWidth + dwX));
				for (dwColorBit=0; dwColorBit<4; dwColorBit++)
				{
					pByteTmpBuf[dwColorBit] =   (BYTE)(  (1-dbSrcU)*(1-dbSrcV)*((BYTE*)pSrcIJ)[dwColorBit] 
													   + (1-dbSrcU)*dbSrcV*((BYTE*)pSrcIJ1)[dwColorBit]
													   + dbSrcU*(1-dbSrcV)*((BYTE*)pSrcI1J)[dwColorBit]
													   + dbSrcU*dbSrcV*((BYTE*)pSrcI1J1)[dwColorBit]
													   );
				}
			}
		}
	}

	// 旋轉成功
	return TRUE;
}

//
// 初始化靜态成員變量
DWORD CWFBitmap::m_dwObjCounts = 0;
IImagingFactory* CWFBitmap::m_pImagingFactory = NULL;
//
// 構造函數
CWFBitmap::CWFBitmap()
: m_pImgDataBuf(NULL)
, m_dwcbImgDataBufSize(0)
{
	// 建立Image工廠接口對象
	CreateImagingFactory();

	// 初始化變量
	m_pImage = NULL;
	memset(&m_ImageInfo, 0, sizeof(m_ImageInfo));
	m_hDrawDC = NULL;
	m_hBitmap = NULL;
	m_hOldBitmap = NULL;	
	m_pBitmapImage = NULL;	
}

// 析構函數
CWFBitmap::~CWFBitmap()
{
	// 釋放占用資源
	Release();

	// 釋放Image工廠接口對象
	DeleteImagingFactory();
}


// 拷貝構造函數
CWFBitmap::CWFBitmap(const CWFBitmap &other)
: m_pImgDataBuf(NULL)
, m_dwcbImgDataBufSize(0)
{
	// 建立Image工廠接口對象
	CreateImagingFactory();

	// 初始化變量
	m_pImage = NULL;
	memset(&m_ImageInfo, 0, sizeof(m_ImageInfo));
	m_hDrawDC = NULL;
	m_hBitmap = NULL;
	m_hOldBitmap = NULL;	
	m_pBitmapImage = NULL;	

	// 拷貝圖檔資訊
	m_ImageInfo = other.m_ImageInfo;

	// 拷貝IImage
	if (other.m_pImage != NULL)
	{	
		other.m_pImage->QueryInterface(IID_IImage, (void **)&m_pImage);	
	}

	// 拷貝圖檔資料
	if (other.m_pImgDataBuf!=NULL && other.m_dwcbImgDataBufSize!=0)
	{
		m_pImgDataBuf = new unsigned char[other.m_dwcbImgDataBufSize];
		if (m_pImgDataBuf != NULL)
		{
			m_dwcbImgDataBufSize = other.m_dwcbImgDataBufSize;
			memcpy(m_pImgDataBuf, other.m_pImgDataBuf, m_dwcbImgDataBufSize);
		}
	}
}

// 指派函數
CWFBitmap& CWFBitmap::operator=(const CWFBitmap &other)
{
	// 檢查自指派
	if (this == &other)
	{
		return *this;
	}

	// 釋放資源
	Release();

	// 拷貝圖檔資訊
	m_ImageInfo = other.m_ImageInfo;

	// 拷貝IImage
	if (other.m_pImage != NULL)
	{	
		other.m_pImage->QueryInterface(IID_IImage, (void **)&m_pImage);	
	}

	// 拷貝圖檔資料
	if (other.m_pImgDataBuf!=NULL && other.m_dwcbImgDataBufSize!=0)
	{
		m_pImgDataBuf = new unsigned char[other.m_dwcbImgDataBufSize];
		if (m_pImgDataBuf != NULL)
		{
			m_dwcbImgDataBufSize = other.m_dwcbImgDataBufSize;
			memcpy(m_pImgDataBuf, other.m_pImgDataBuf, m_dwcbImgDataBufSize);
		}
	} 

	// 傳回目前對象
	return *this;
}

// 從檔案中加載
BOOL CWFBitmap::LoadFromFile(
	LPCWSTR lpFileName         // 檔案絕對路徑
	)
{
	// 釋放上次圖檔資料
	Release();

	// 路徑有效性
	if (WFBING_PathEffective(lpFileName) == FALSE)
	{
		return FALSE;
	}

	// 建立Image工廠接口對象失敗
	if (m_pImagingFactory == NULL)
	{
		return FALSE;
	}

	// 從檔案中建立圖檔
	HRESULT hr = NULL;
	if(FAILED(hr = m_pImagingFactory->CreateImageFromFile(lpFileName, &m_pImage)))
	{
		return FALSE;
	}

	// 得到圖檔資訊
	if(FAILED(hr = m_pImage->GetImageInfo(&m_ImageInfo)))
	{
		return FALSE;
	}

	// 成功獲得圖檔資訊
	return TRUE;
}

// 從資源中加載,例如LoadFromResource(MAKEINTRESOURCE(IDR_BACKIMG), _T("PNG"));
BOOL CWFBitmap::LoadFromResource(
	LPCWSTR lpName,            // 資源名稱比如:MAKEINTRESOURCE(IDR_BACKIMG)            
	LPCWSTR lpType             // 資源類型比如:_T("PNG")
	)
{
	// 釋放上次圖檔資料
	Release();

	// 建立Image工廠接口對象失敗
	if (m_pImagingFactory == NULL)
	{
		return FALSE;
	}	

	// 在資源中尋找
	HMODULE hModule_Current = ::GetModuleHandle(NULL);
	HRSRC hr = ::FindResource(hModule_Current, lpName, lpType);
	DWORD dwsize = ::SizeofResource(GetModuleHandle(NULL), hr);
	HGLOBAL hg = ::LoadResource(GetModuleHandle(NULL), hr);
	LPSTR lp = (LPSTR)::LockResource(hg);
	
	// 從緩沖區建立圖檔
	HRESULT hrt = NULL;
	if(FAILED(hrt = m_pImagingFactory->CreateImageFromBuffer(lp, dwsize, DISPOSAL_NONE, &m_pImage)))
	{
		::DeleteObject(hr);
		return FALSE;
	}

	// 得到圖檔資訊
	if(FAILED(hrt = m_pImage->GetImageInfo(&m_ImageInfo)))
	{
		::DeleteObject(hr);
		return FALSE;
	}

	// 成功獲得圖檔資訊
	::DeleteObject(hr);
	return TRUE;
}

// 從緩沖區中加載
BOOL CWFBitmap::LoadFromBuffer(
	const unsigned char *pBuf,      // 緩沖區位址
	DWORD dwcbBufSize               // 緩沖區位元組大小
	)
{
	// 釋放上次圖檔資料
	Release();

	// 參數有效性
	if (pBuf==NULL || dwcbBufSize==0)
	{
		return FALSE;
	}

	// 建立Image工廠接口對象失敗
	if (m_pImagingFactory == NULL)
	{
		return FALSE;
	}

	// 從檔案中建立圖檔
	HRESULT hr = NULL;
	if(FAILED(hr = m_pImagingFactory->CreateImageFromBuffer(pBuf, dwcbBufSize, DISPOSAL_NONE, &m_pImage)))
	{
		return FALSE;
	}

	// 得到圖檔資訊
	if(FAILED(hr = m_pImage->GetImageInfo(&m_ImageInfo)))
	{
		return FALSE;
	}

	// 成功獲得圖檔資訊
	return TRUE;
}

// 從IImage對象中加載
BOOL CWFBitmap::LoadFromIImage(
	IImage *pIImage            // IImage對象
	)
{
	// 釋放上次圖檔資料
	Release();

	// 參數有效性
	if (pIImage == NULL)
	{
		return FALSE;
	}

	// 得到IImage對象
	HRESULT hr = pIImage->QueryInterface(IID_IImage, (void **)&m_pImage);	
	if (FAILED(hr))
	{
		return FALSE;
	}

	// 得到圖檔資訊
	if(FAILED(hr = m_pImage->GetImageInfo(&m_ImageInfo)))
	{
		return FALSE;
	}

	// 加載成功
	return TRUE;
}

// 從IBitmapImage對象中加載
BOOL CWFBitmap::LoadFromIBitmapImage(
	IBitmapImage *pBitmapImage // IBitmapImage對象 
	)
{
	// 釋放上次資料
	Release();

	// 參數有效性
	if (pBitmapImage == NULL)
	{
		return FALSE;
	}

	// 拷貝到新的IBitmapImage對象 
	if (CopyBitmapImage(pBitmapImage, m_pBitmapImage) == FALSE)
	{
		return FALSE;
	}

	// 得到新的IImage
	m_pBitmapImage->QueryInterface(IID_IImage, (void**)&m_pImage);

	// 得到新的ImageInfo	
	if (m_pImage != NULL)
	{
		m_pImage->GetImageInfo(&m_ImageInfo);
	}	

	// 成功
	return TRUE;
}

// 釋放占用的資源
void CWFBitmap::Release(void)
{
	// 釋放DC
	DeleteImgDC();

	// 釋放原始資料空間
	DeleteImgDateBuf();

	// 釋放IMAGE
	if(m_pImage != NULL)
	{
		m_pImage->Release();
		m_pImage = NULL;
	}

	// 釋放IBitmapImage
	if (m_pBitmapImage != NULL)
	{
		m_pBitmapImage->Release();
		m_pBitmapImage = NULL;
	}
}

// 繪制整個圖像到指定位置(會把圖像壓縮或拉伸填充到指定區域)
void CWFBitmap::Draw(
	HDC hdc,                   // 繪制DC 
	const RECT* dstRect        // 繪制目标區域
	)
{
	// 擷取圖像資訊失敗
	if (m_pImage==NULL || dstRect==NULL)
	{
		return;
	}

	// 繪制圖像
	m_pImage->Draw(hdc, dstRect, NULL);		
}

// 繪制圖像上一部分到指定的部分(先繪制到記憶體DC,再繪制到目标DC)
void CWFBitmap::Draw(
	HDC hdc,                   // 繪制DC
	const RECT* dstRect,       // 繪制目标區域
	const RECT* srcRect        // 待繪制圖檔上的指定區域,NULL表示整個圖檔
	)
{
	// 擷取圖像資訊失敗,目标繪圖區為NULL
	if (m_pImage==NULL || dstRect==NULL)
	{
		return;
	}	

	// 建立記憶體DC
	if (m_hDrawDC == NULL)
	{
		m_hDrawDC = CreateImgDC(hdc);
	}

	// 把記憶體DC上指定的部分拷貝到目标DC上
	if (srcRect != NULL)
	{
		::StretchBlt(hdc, 
			dstRect->left, 
			dstRect->top, 
			dstRect->right-dstRect->left, 
			dstRect->bottom-dstRect->top, 
			m_hDrawDC, 
			srcRect->left, 
			srcRect->top, 
			srcRect->right-srcRect->left, 
			srcRect->bottom-srcRect->top, 
			SRCCOPY
			);	
	}
	else
	{
		::BitBlt(hdc, 
			dstRect->left, 
			dstRect->top, 
			dstRect->right-dstRect->left, 
			dstRect->bottom-dstRect->top, 
			m_hDrawDC, 
			0, 
			0,
			SRCCOPY
			);
	}	
}

// 繪制圖像上一部分到指定的區域(支援alpha混合)
void CWFBitmap::DrawAlpha(
	HDC hdc,                   // 繪制DC
	const RECT* dstRect,       // 繪制目标區域
	const RECT* srcRect        // 待繪制圖檔上的指定區域,NULL表示整個圖檔
	)
{
	// 擷取圖像資訊失敗,目标繪圖區為NULL
	if (m_pImage==NULL || dstRect==NULL)
	{
		return;
	}

	// 擷取原始資料失敗
	if (CreateImgDateBuf() == FALSE)
	{
		return;
	}	

	// 計算目标區域寬度及高度
	int nDstWidth = dstRect->right - dstRect->left;
	int nDstHeight = dstRect->bottom - dstRect->top;

	// 建立目标繪制區域大小的記憶體DC
	HDC hDIBDC = CreateCompatibleDC(hdc);
	BITMAPINFO hdr; 
	ZeroMemory(&hdr , sizeof(BITMAPINFO));
	hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	hdr.bmiHeader.biWidth = nDstWidth;
	hdr.bmiHeader.biHeight = -nDstHeight;
	hdr.bmiHeader.biPlanes = 1;
	hdr.bmiHeader.biBitCount = 32;
	BYTE * pbtPixels = NULL; 
	HBITMAP hDIBitmap = CreateDIBSection(hDIBDC, (BITMAPINFO *)&hdr, DIB_RGB_COLORS, (void **)&pbtPixels, NULL, 0);
	HBITMAP hOldBmp = (HBITMAP)SelectObject(hDIBDC, hDIBitmap);

	// 拷貝背景DC上目标繪制區域到記憶體DC
	::StretchBlt(hDIBDC, 0, 0, nDstWidth, nDstHeight, hdc, dstRect->left, dstRect->top, nDstWidth, nDstHeight, SRCCOPY);	

	// 計算使用圖檔上的源區域大小
	RECT rcImgSrc;
	if (srcRect != NULL)
	{
		rcImgSrc = *srcRect;
	}
	else
	{
		rcImgSrc.left = 0;
		rcImgSrc.top = 0;
		rcImgSrc.right = m_ImageInfo.Width;
		rcImgSrc.bottom = m_ImageInfo.Height;
	}

	// 計算實際使用區域的寬度和高度
	int nUseWidth = (nDstWidth < rcImgSrc.right-rcImgSrc.left) ? nDstWidth : rcImgSrc.right-rcImgSrc.left;
	int nUseHeight = (nDstHeight < rcImgSrc.bottom-rcImgSrc.top) ? nDstHeight : rcImgSrc.bottom-rcImgSrc.top;

	// 進行Alpha混合運算	
	BYTE btAlphaSRC = 0;
	int iSrcPos = 0;
	int iDstPos = 0;
	for(int i=0; i<nUseHeight; i++)
	{		
		for(int j=0;  j<nUseWidth; j++)
		{		
			// 計算源及目标索引及該點ALPHA值
			iSrcPos = (i*m_ImageInfo.Width + rcImgSrc.left + j) * 4;
			iDstPos = (i*nDstWidth + j) * 4;		
			btAlphaSRC = m_pImgDataBuf[iSrcPos+3];

			// 計算目标像素值,ALPHA混合result = ALPHA * srcPixel + ( 1 - ALPHA ) * destPixel			
			pbtPixels[iDstPos] = ((255-btAlphaSRC)*pbtPixels[iDstPos] + btAlphaSRC*m_pImgDataBuf[iSrcPos])/255;
			pbtPixels[iDstPos+1] = ((255-btAlphaSRC)*pbtPixels[iDstPos+1] + btAlphaSRC*m_pImgDataBuf[iSrcPos+1])/255;
			pbtPixels[iDstPos+2] = ((255-btAlphaSRC)*pbtPixels[iDstPos+2] + btAlphaSRC*m_pImgDataBuf[iSrcPos+2])/255;		
		}			
	}

	// 混合ALPHA後的記憶體DC拷貝到目标DC
	BitBlt(hdc, dstRect->left, dstRect->top, nDstWidth, nDstHeight, hDIBDC, 0, 0, SRCCOPY);

	// 釋放臨時記憶體DC
	SelectObject(hDIBDC, hOldBmp);	
	DeleteObject(hDIBDC);
	DeleteObject(hDIBitmap);
}

// 繪制整個圖像到自定義矩形類型區域(會把圖像壓縮或拉伸填充到指定區域)
void CWFBitmap::DrawEx(
	HDC hdc,                   // 繪制DC 
	const CWFRect* dstRect     // 繪制目标區域
	)
{
	// 參數有效性
	if (dstRect == NULL)
	{
		return;
	}

	// 轉換矩形區域
	RECT rcDst = {dstRect->x, dstRect->y, dstRect->x+dstRect->w, dstRect->y+dstRect->h};
	Draw(hdc, &rcDst);
}

// 繪制圖像上一部分到指定的自定義矩形類型區域(先繪制到記憶體DC,再繪制到目标DC)
void CWFBitmap::DrawEx(
	HDC hdc,                   // 繪制DC
	const CWFRect* dstRect,    // 繪制目标區域
	const CWFRect* srcRect     // 待繪制圖檔上的指定區域,NULL表示整個圖檔
	)
{
	// 參數有效性
	if (dstRect == NULL)
	{
		return;
	}

	// 轉換得到目标矩形區域
	RECT rcDst = {dstRect->x, dstRect->y, dstRect->x+dstRect->w, dstRect->y+dstRect->h};

	// 轉換得到源矩形區域
	RECT rcSrc = {0};
	if (srcRect != NULL)
	{
		rcSrc.left = srcRect->x;
		rcSrc.top = srcRect->y;
		rcSrc.right = srcRect->x + srcRect->w;
		rcSrc.bottom = srcRect->y + srcRect->h;
	}
	Draw(hdc, &rcDst, (srcRect==NULL) ? NULL : &rcSrc);
}

// 繪制圖像上一部分到指定的自定義矩形類型區域(支援alpha混合)
void CWFBitmap::DrawAlphaEx(
	HDC hdc,                   // 繪制DC
	const CWFRect* dstRect,    // 繪制目标區域
	const CWFRect* srcRect     // 待繪制圖檔上的指定區域,NULL表示整個圖檔
	)
{
	// 參數有效性
	if (dstRect == NULL)
	{
		return;
	}

	// 轉換得到目标矩形區域
	RECT rcDst = {dstRect->x, dstRect->y, dstRect->x+dstRect->w, dstRect->y+dstRect->h};

	// 轉換得到源矩形區域
	RECT rcSrc = {0};
	if (srcRect != NULL)
	{
		rcSrc.left = srcRect->x;
		rcSrc.top = srcRect->y;
		rcSrc.right = srcRect->x + srcRect->w;
		rcSrc.bottom = srcRect->y + srcRect->h;
	}
	DrawAlpha(hdc, &rcDst, (srcRect==NULL) ? NULL : &rcSrc);
}

// 獲得圖像的寬度,未加載到圖檔傳回0
DWORD CWFBitmap::Width() const
{
	return m_ImageInfo.Width;
}

// 獲得圖像的高度,未加載到圖檔傳回0
DWORD CWFBitmap::Height() const
{
	return m_ImageInfo.Height;
}

BOOL CWFBitmap::ZoomToIImage(
	PWFIImage &pDstIImage,     // 存放縮放後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	DWORD dwNewWidth,          // 縮放後圖像寬度
	DWORD dwNewHeight          // 縮放後圖像高度
	)
{
	// 釋放目标IImage對象
	if (pDstIImage != NULL)
	{
		pDstIImage->Release();
		pDstIImage = NULL;
	}
	
	// 參數有效性
	if (dwNewWidth==0 || dwNewHeight==0 || m_pImage==NULL || m_pImagingFactory==NULL)
	{
		return FALSE;
	}

	// 使用到的臨時變量,由于後面使用了goto在此處定義
	BOOL bRet = TRUE;                       // 函數傳回值
	IBitmapImage *pBmp = NULL;	            // 位圖接口
	IBitmapImage *pNewBmp = NULL;           // 縮放後位圖接口
	IBasicBitmapOps *pBmpOps = NULL;        // 位圖操作接口

	// 得到位圖接口	
	HRESULT hr = m_pImagingFactory->CreateBitmapFromImage(m_pImage, m_ImageInfo.Width, m_ImageInfo.Height, m_ImageInfo.PixelFormat, InterpolationHintDefault, &pBmp);
	if (FAILED(hr))
	{
		printf("ZoomToIImage CreateBitmapFromImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到位圖操作接口	
	hr = pBmp->QueryInterface(IID_IBasicBitmapOps,(void **)&pBmpOps);
	if (FAILED(hr))
	{
		printf("ZoomToIImage QueryInterface IID_IBasicBitmapOps Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;		
	}

	// 縮放位圖
	hr = pBmpOps->Resize(dwNewWidth, dwNewHeight, m_ImageInfo.PixelFormat, InterpolationHintDefault, &pNewBmp);
	if (FAILED(hr))
	{
		printf("ZoomToIImage Resize Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到新IImage
	hr = pNewBmp->QueryInterface(IID_IImage,(void **)&pDstIImage);
	if (FAILED(hr))
	{
		printf("ZoomToIImage QueryInterface pDstIImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 正确得到縮放後的IImage
	bRet = TRUE;

	// 進入釋放過程
ERROR_END_FUNCTIONFLAG:
	// 釋放位圖
	if (pBmp != NULL)
	{
		pBmp->Release();
		pBmp = NULL;
	}

	// 釋放縮放後位圖
	if (pNewBmp != NULL)
	{
		pNewBmp->Release();
		pNewBmp = NULL;
	}

	// 釋放位圖操作接口
	if (pBmpOps != NULL)
	{
		pBmpOps->Release();
		pBmpOps = NULL;
	}

	// 傳回結果
	return bRet;
}

// 縮放圖像(指定縮放後圖像的寬度和高度)
BOOL CWFBitmap::Zoom(
	DWORD dwNewWidth,          // 縮放後圖像寬度
	DWORD dwNewHeight          // 縮放後圖像高度
	)
{
	// 縮放後新IImage
	IImage *pNewImage = NULL;   
	if (ZoomToIImage(pNewImage, dwNewWidth, dwNewHeight) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到縮放後的IImage
	BOOL bRet = (pNewImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到新的IImage
		m_pImage = pNewImage;

		// 得到新的ImageInfo	
		m_pImage->GetImageInfo(&m_ImageInfo);
	}

	// 傳回結果
	return bRet;
}

// 縮放圖像到目标對象中(指定縮放後圖像的寬度和高度),不改變對象自身
BOOL CWFBitmap::Zoom(
	CWFBitmap &dstBitmap,      // 帶出縮放後的圖像
	DWORD dwNewWidth,          // 縮放後圖像寬度
	DWORD dwNewHeight          // 縮放後圖像高度
	)
{
	// 縮放後新IImage
	IImage *pNewImage = NULL;   
	if (ZoomToIImage(pNewImage, dwNewWidth, dwNewHeight) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIImage(pNewImage);

	// 釋放縮放後對象
	if (pNewImage != NULL)
	{
		pNewImage->Release();
		pNewImage = NULL;
	}

	// 傳回縮放結果
	return bRet;
}

// 縮放圖像(指定縮放X方向,Y方向縮放比率)
BOOL CWFBitmap::ZoomEx(
	double dbZoomXRatio,       // X方向縮放率
	double dbZoomYRatio        // Y方向縮放率
	)
{
	// 計算縮放後圖像寬度高度
	DWORD dwNewW = (DWORD)((double)m_ImageInfo.Width * dbZoomXRatio);
	DWORD dwNewH = (DWORD)((double)m_ImageInfo.Height * dbZoomYRatio);
	return Zoom(dwNewW, dwNewH);
}

// 縮放圖像到目标對象中(指定縮放X方向,Y方向縮放比率),不改變對象自身
BOOL CWFBitmap::ZoomEx(
	CWFBitmap &dstBitmap,      // 帶出縮放後的圖像
	double dbZoomXRatio,       // X方向縮放率
	double dbZoomYRatio        // Y方向縮放率
	)
{
	// 計算縮放後圖像寬度高度
	DWORD dwNewW = (DWORD)((double)m_ImageInfo.Width * dbZoomXRatio);
	DWORD dwNewH = (DWORD)((double)m_ImageInfo.Height * dbZoomYRatio);
	return Zoom(dstBitmap, dwNewW, dwNewH);
}

// 按特定角度旋轉圖像到IImage對象中,不改變自身資料
// 順時針旋轉,隻支援90, 180, 270, or 360
BOOL CWFBitmap::RotateSpecificAngleToIImage(
	PWFIImage &pDstIImage,     // 存放旋轉後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	float fSpecificAngle       // 特定旋轉角度(機關:度)
	)
{
	// 釋放目标IImage對象
	if (pDstIImage != NULL)
	{
		pDstIImage->Release();
		pDstIImage = NULL;
	}

	// 參數有效性
	if (m_pImage==NULL || m_pImagingFactory==NULL)
	{
		return FALSE;
	}

	// 使用到的臨時變量,由于後面使用了goto在此處定義
	BOOL bRet = TRUE;                       // 函數傳回值
	IBitmapImage *pBmp = NULL;	            // 位圖接口
	IBitmapImage *pNewBmp = NULL;           // 縮放後位圖接口
	IBasicBitmapOps *pBmpOps = NULL;        // 位圖操作接口

	// 得到位圖接口	
	HRESULT hr = m_pImagingFactory->CreateBitmapFromImage(m_pImage, m_ImageInfo.Width, m_ImageInfo.Height, m_ImageInfo.PixelFormat, InterpolationHintDefault, &pBmp);
	if (FAILED(hr))
	{
		printf("RotateSpecificAngleToIImage CreateBitmapFromImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到位圖操作接口	
	hr = pBmp->QueryInterface(IID_IBasicBitmapOps,(void **)&pBmpOps);
	if (FAILED(hr))
	{
		printf("RotateSpecificAngleToIImage QueryInterface IID_IBasicBitmapOps Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;		
	}

	// 旋轉位圖
	hr = pBmpOps->Rotate(fSpecificAngle, InterpolationHintDefault, &pNewBmp);
	if (FAILED(hr))
	{
		printf("RotateSpecificAngleToIImage Rotate Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到新IImage
	hr = pNewBmp->QueryInterface(IID_IImage,(void **)&pDstIImage);
	if (FAILED(hr))
	{
		printf("RotateSpecificAngleToIImage QueryInterface pDstIImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 正确得到旋轉後的IImage
	bRet = TRUE;

	// 進入釋放過程
ERROR_END_FUNCTIONFLAG:
	// 釋放位圖
	if (pBmp != NULL)
	{
		pBmp->Release();
		pBmp = NULL;
	}

	// 釋放縮放後位圖
	if (pNewBmp != NULL)
	{
		pNewBmp->Release();
		pNewBmp = NULL;
	}

	// 釋放位圖操作接口
	if (pBmpOps != NULL)
	{
		pBmpOps->Release();
		pBmpOps = NULL;
	}

	// 傳回結果
	return bRet;
}

// 按特定角度旋轉圖像
// 順時針旋轉,隻支援90, 180, 270, or 360
BOOL CWFBitmap::RotateSpecificAngle(
	float fSpecificAngle       // 特定旋轉角度(機關:度)
	)
{
	// 旋轉後新IImage
	IImage *pNewImage = NULL;   
	if (RotateSpecificAngleToIImage(pNewImage, fSpecificAngle) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到旋轉後的IImage
	BOOL bRet = (pNewImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到新的IImage
		m_pImage = pNewImage;

		// 得到新的ImageInfo	
		m_pImage->GetImageInfo(&m_ImageInfo);
	}

	// 傳回結果
	return bRet;
}

// 按特定角度旋轉圖像到目标對象中,不改變對象自身
// 順時針旋轉,隻支援90, 180, 270, or 360
BOOL CWFBitmap::RotateSpecificAngle(
	CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
	float fSpecificAngle       // 特定旋轉角度(機關:度)
	)
{
	// 旋轉後新IImage
	IImage *pNewImage = NULL;   
	if (RotateSpecificAngleToIImage(pNewImage, fSpecificAngle) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIImage(pNewImage);

	// 釋放旋轉後對象
	if (pNewImage != NULL)
	{
		pNewImage->Release();
		pNewImage = NULL;
	}

	// 傳回旋轉結果
	return bRet;
}

// 翻轉圖像到IImage對象中,不改變自身資料
BOOL CWFBitmap::FlipToIImage(
	PWFIImage &pDstIImage,     // 存放翻轉後圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	BOOL bFilpX,               // 是否反轉X方向
	BOOL bFlipY                // 是否反轉Y方向
	)
{
	// 釋放目标IImage對象
	if (pDstIImage != NULL)
	{
		pDstIImage->Release();
		pDstIImage = NULL;
	}

	// 參數有效性
	if (m_pImage==NULL || m_pImagingFactory==NULL)
	{
		return FALSE;
	}

	// 使用到的臨時變量,由于後面使用了goto在此處定義
	BOOL bRet = TRUE;                       // 函數傳回值
	IBitmapImage *pBmp = NULL;	            // 位圖接口
	IBitmapImage *pNewBmp = NULL;           // 縮放後位圖接口
	IBasicBitmapOps *pBmpOps = NULL;        // 位圖操作接口

	// 得到位圖接口	
	HRESULT hr = m_pImagingFactory->CreateBitmapFromImage(m_pImage, m_ImageInfo.Width, m_ImageInfo.Height, m_ImageInfo.PixelFormat, InterpolationHintDefault, &pBmp);
	if (FAILED(hr))
	{
		printf("FlipToIImage CreateBitmapFromImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到位圖操作接口	
	hr = pBmp->QueryInterface(IID_IBasicBitmapOps,(void **)&pBmpOps);
	if (FAILED(hr))
	{
		printf("FlipToIImage QueryInterface IID_IBasicBitmapOps Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;		
	}

	// 翻轉位圖
	hr = pBmpOps->Flip(bFilpX, bFlipY, &pNewBmp);
	if (FAILED(hr))
	{
		printf("FlipToIImage Flip Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到新IImage
	hr = pNewBmp->QueryInterface(IID_IImage,(void **)&pDstIImage);
	if (FAILED(hr))
	{
		printf("FlipToIImage QueryInterface pDstIImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 正确得到翻轉後的IImage
	bRet = TRUE;

	// 進入釋放過程
ERROR_END_FUNCTIONFLAG:
	// 釋放位圖
	if (pBmp != NULL)
	{
		pBmp->Release();
		pBmp = NULL;
	}

	// 釋放縮放後位圖
	if (pNewBmp != NULL)
	{
		pNewBmp->Release();
		pNewBmp = NULL;
	}

	// 釋放位圖操作接口
	if (pBmpOps != NULL)
	{
		pBmpOps->Release();
		pBmpOps = NULL;
	}

	// 傳回結果
	return bRet;
}

// 翻轉圖像
BOOL CWFBitmap::Flip(
	BOOL bFilpX,               // 是否反轉X方向
	BOOL bFlipY                // 是否反轉Y方向
	)
{
	// 翻轉後新IImage
	IImage *pNewImage = NULL;   
	if (FlipToIImage(pNewImage, bFilpX, bFlipY) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到翻轉後的IImage
	BOOL bRet = (pNewImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到新的IImage
		m_pImage = pNewImage;

		// 得到新的ImageInfo	
		m_pImage->GetImageInfo(&m_ImageInfo);
	}

	// 傳回結果
	return bRet;
}

// 翻轉圖像到目标對象中,不改變對象自身
BOOL CWFBitmap::Flip(
	CWFBitmap &dstBitmap,      // 帶出翻轉後的圖像
	BOOL bFilpX,               // 是否反轉X方向
	BOOL bFlipY                // 是否反轉Y方向
	)
{
	// 翻轉後新IImage
	IImage *pNewImage = NULL;   
	if (FlipToIImage(pNewImage, bFilpX, bFlipY) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIImage(pNewImage);

	// 釋放翻轉後對象
	if (pNewImage != NULL)
	{
		pNewImage->Release();
		pNewImage = NULL;
	}

	// 傳回翻轉結果
	return bRet;
}

// 裁剪圖像上指定區域到IImage對象中,不改變自身資料
BOOL CWFBitmap::CutToIImage(
	PWFIImage &pDstIImage,     // 存放裁剪圖像的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	const RECT *pCutRect       // 在圖像上裁剪的區域
	)
{
	// 釋放目标IImage對象
	if (pDstIImage != NULL)
	{
		pDstIImage->Release();
		pDstIImage = NULL;
	}

	// 參數有效性
	if (m_pImage==NULL || m_pImagingFactory==NULL || pCutRect==NULL)
	{
		return FALSE;
	}

	// 裁剪區域有效性
	if (pCutRect->left>=pCutRect->right || pCutRect->top>=pCutRect->bottom)
	{
		printf("CutToIImage CurRect Error!\n");
		return FALSE;
	}

	// 使用到的臨時變量,由于後面使用了goto在此處定義
	BOOL bRet = TRUE;                       // 函數傳回值
	IBitmapImage *pBmp = NULL;	            // 位圖接口
	IBitmapImage *pNewBmp = NULL;           // 縮放後位圖接口
	IBasicBitmapOps *pBmpOps = NULL;        // 位圖操作接口

	// 得到位圖接口	
	HRESULT hr = m_pImagingFactory->CreateBitmapFromImage(m_pImage, m_ImageInfo.Width, m_ImageInfo.Height, m_ImageInfo.PixelFormat, InterpolationHintDefault, &pBmp);
	if (FAILED(hr))
	{
		printf("CutToIImage CreateBitmapFromImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到位圖操作接口	
	hr = pBmp->QueryInterface(IID_IBasicBitmapOps,(void **)&pBmpOps);
	if (FAILED(hr))
	{
		printf("CutToIImage QueryInterface IID_IBasicBitmapOps Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;		
	}

	// 翻轉位圖
	hr = pBmpOps->Clone(pCutRect, &pNewBmp, TRUE);	
	if (FAILED(hr))
	{ 
		printf("CutToIImage Clone Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 得到新IImage
	hr = pNewBmp->QueryInterface(IID_IImage,(void **)&pDstIImage);
	if (FAILED(hr))
	{
		printf("CutToIImage QueryInterface pDstIImage Error!\n");
		bRet = FALSE;
		goto ERROR_END_FUNCTIONFLAG;
	}

	// 正确得到裁剪的IImage
	bRet = TRUE;

	// 進入釋放過程
ERROR_END_FUNCTIONFLAG:
	// 釋放位圖
	if (pBmp != NULL)
	{
		pBmp->Release();
		pBmp = NULL;
	}

	// 釋放縮放後位圖
	if (pNewBmp != NULL)
	{
		pNewBmp->Release();
		pNewBmp = NULL;
	}

	// 釋放位圖操作接口
	if (pBmpOps != NULL)
	{
		pBmpOps->Release();
		pBmpOps = NULL;
	}

	// 傳回結果
	return bRet;
}

// 裁剪圖像(圖像改變為指定裁剪區域的圖像)
BOOL CWFBitmap::Cut(
	const RECT *pCutRect       // 在圖像上裁剪的區域
	)
{
	// 裁剪到的新IImage
	IImage *pNewImage = NULL;   
	if (CutToIImage(pNewImage, pCutRect) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到裁剪的IImage
	BOOL bRet = (pNewImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到新的IImage
		m_pImage = pNewImage;

		// 得到新的ImageInfo	
		m_pImage->GetImageInfo(&m_ImageInfo);
	}

	// 傳回結果
	return bRet;
}

// 裁剪圖像到目标對象中,不改變對象自身
BOOL CWFBitmap::Cut(
	CWFBitmap &dstBitmap,      // 帶出裁剪到的圖像
	const RECT *pCutRect       // 在圖像上裁剪的區域
	)
{
	// 裁剪到的IImage
	IImage *pNewImage = NULL;   
	if (CutToIImage(pNewImage, pCutRect) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIImage(pNewImage);

	// 釋放新的對象
	if (pNewImage != NULL)
	{
		pNewImage->Release();
		pNewImage = NULL;
	}

	// 傳回結果
	return bRet;
}

// 生成縮略圖到指定IImage對象中,不改變自身資料
BOOL CWFBitmap::ThumbnailToIImage(
	PWFIImage &pDstIImage,     // 存放縮略圖的IImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	DWORD dwThumbWidth,        // 縮略圖寬度
	DWORD dwThumbHeight        // 縮略圖高度
	)
{
	// 釋放目标IImage對象
	if (pDstIImage != NULL)
	{
		pDstIImage->Release();
		pDstIImage = NULL;
	}

	// 參數有效性
	if (m_pImage==NULL || dwThumbWidth==0 || dwThumbHeight==0)
	{
		return FALSE;
	}

	// 得到縮略圖
	HRESULT hr = m_pImage->GetThumbnail(dwThumbWidth, dwThumbHeight, &pDstIImage);
	if (FAILED(hr))
	{
		printf("ThumbnailToIImage GetThumbnail Error!\n");
		return FALSE;
	}

	// 得到縮略圖
	return TRUE;
}

// 生成縮略圖(圖像改變為縮略圖)
BOOL CWFBitmap::Thumbnail(
	DWORD dwThumbWidth,        // 縮略圖寬度
	DWORD dwThumbHeight        // 縮略圖高度
	)
{
	// 得到新的IImage
	IImage *pNewImage = NULL;   
	if (ThumbnailToIImage(pNewImage, dwThumbWidth, dwThumbHeight) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到新的IImage
	BOOL bRet = (pNewImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到新的IImage
		m_pImage = pNewImage;

		// 得到新的ImageInfo	
		m_pImage->GetImageInfo(&m_ImageInfo);
	}

	// 傳回結果
	return bRet;
}

// 生成縮略圖(指定縮放比率)(圖像改變為縮略圖)
BOOL CWFBitmap::ThumbnailEx(
	double dbXRatio,           // X方向縮放率
	double dbYRatio            // Y方向縮放率
	)
{
	// 計算縮放後圖像寬度高度
	DWORD dwNewW = (DWORD)((double)m_ImageInfo.Width * dbXRatio);
	DWORD dwNewH = (DWORD)((double)m_ImageInfo.Height * dbYRatio);
	return Thumbnail(dwNewW, dwNewH);
}

// 生成縮略圖到目标對象中,不改變對象自身
BOOL CWFBitmap::Thumbnail(
	CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
	DWORD dwThumbWidth,        // 縮略圖寬度
	DWORD dwThumbHeight        // 縮略圖高度
	)
{
	// 得到新的IImage
	IImage *pNewImage = NULL;   
	if (ThumbnailToIImage(pNewImage, dwThumbWidth, dwThumbHeight) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIImage(pNewImage);

	// 釋放新的對象
	if (pNewImage != NULL)
	{
		pNewImage->Release();
		pNewImage = NULL;
	}

	// 傳回結果
	return bRet;
}

// 生成縮略圖到目标對象中(指定縮放比率),不改變對象自身
BOOL CWFBitmap::ThumbnailEx(
	CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
	double dbXRatio,           // X方向縮放率
	double dbYRatio            // Y方向縮放率
	)
{
	// 計算縮放後圖像寬度高度
	DWORD dwNewW = (DWORD)((double)m_ImageInfo.Width * dbXRatio);
	DWORD dwNewH = (DWORD)((double)m_ImageInfo.Height * dbYRatio);
	return Thumbnail(dstBitmap, dwNewW, dwNewH);
}

// 圖像旋轉任意角度到IBitmapImage對象中,不改變自身資料
// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngleToIImage	
BOOL CWFBitmap::RotateToIBitmapImage(
	PWFIBitmapImage &pDstIBitmapImage,     // 存放旋轉後圖像的IBitmapImage,外部傳入若不是NULL内部會釋放,帶出的結果需要外部釋放
	float fAngle                           // 特定旋轉角度(機關:度)
	)
{	
	// 釋放目标IImage對象
	if (pDstIBitmapImage != NULL)
	{
		pDstIBitmapImage->Release();
		pDstIBitmapImage = NULL;
	}

	// 參數有效性
	if (m_pImage==NULL || m_pImagingFactory==NULL)
	{
		return FALSE;
	}

	// 得到圖檔資料區
	if (CreateImgDateBuf() == FALSE)
	{
		return FALSE;
	}

	// 旋轉圖像資料緩沖區
	PWFBYTE pDstBuf = NULL;
	DWORD dwDstWidth = 0;
	DWORD dwDstHeight = 0;
	if (WFBING_RotateImageBuffer(
							  m_pImgDataBuf, 
							  m_ImageInfo.Width, 
							  m_ImageInfo.Height, 
							  (double)fAngle,
							  pDstBuf, 
							  dwDstWidth, 
							  dwDstHeight
							  ) == FALSE)
	{
		return FALSE;
	}

	// 由于CreateBitmapFromBuffer建立時需要自己管理記憶體,對于CWFBitmap對象間的指派拷貝不容易處理
	// 此處使用CreateNewBitmap建立新的位圖,把得到旋轉後的資料強制寫入,管理此IBitmapImage即可
	// 用于鎖定位圖資料
	BitmapData bitmapData;  
	bitmapData.Width = dwDstWidth;  
	bitmapData.Height = dwDstHeight;  
	bitmapData.PixelFormat = PIXFMT_32BPP_ARGB; 
	RECT rect = {0, 0, dwDstWidth, dwDstHeight}; 

	// 建立新的位圖
	HRESULT hr = m_pImagingFactory->CreateNewBitmap(dwDstWidth, dwDstHeight, PIXFMT_32BPP_ARGB, &pDstIBitmapImage);
	BOOL bRet = FALSE;
	if (FAILED(hr))
	{
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;
	}

	// 鎖定位圖資料	 
	hr = pDstIBitmapImage->LockBits(&rect, ImageLockModeRead, PIXFMT_32BPP_ARGB, &bitmapData);  
	if (FAILED(hr))
	{
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;		
	}

	// 把旋轉後資料寫入位圖
	BYTE *pBmpBuf = (BYTE*)bitmapData.Scan0;
	memcpy(pBmpBuf, pDstBuf, dwDstWidth*dwDstHeight*4);

	// 釋放鎖定位圖資料
	pDstIBitmapImage->UnlockBits(&bitmapData);

	// 寫入成功
	bRet = TRUE;	

THEEND_FOR_THISFOUNCTION:
	// 釋放臨時存放旋轉後
	if (pDstBuf != NULL)
	{
		delete[] pDstBuf;
		pDstBuf = NULL;
	}

	// 釋放IBitmapImage對象
	if (bRet==FALSE && pDstIBitmapImage!=NULL)
	{
		pDstIBitmapImage->Release();
		pDstIBitmapImage = NULL;
	}

	// 傳回結果
	return bRet;
}

// 按任意角度旋轉圖像	
// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngle
BOOL CWFBitmap::Rotate(
	float fAngle               // 特定旋轉角度(機關:度)
	)
{
	// 得到新的IBitmapImage
	IBitmapImage *pNewBitmapImage = NULL;   
	if (RotateToIBitmapImage(pNewBitmapImage, fAngle) == FALSE)
	{
		return FALSE;
	}	

	// 是否得到新的IImage
	BOOL bRet = (pNewBitmapImage!=NULL) ? TRUE : FALSE;

	// 改變IImage對象内容
	if (pNewBitmapImage != NULL)
	{
		// 釋放原有的IImage
		Release();

		// 得到IBitmapImage
		m_pBitmapImage = pNewBitmapImage;

		// 得到新的IImage
		m_pBitmapImage->QueryInterface(IID_IImage, (void**)&m_pImage);
		
		// 得到新的ImageInfo	
		if (m_pImage != NULL)
		{
			m_pImage->GetImageInfo(&m_ImageInfo);
		}		
	}

	// 傳回結果
	return bRet;	
}

// 按任意角度旋轉圖像到目标對象中,不改變對象自身
// 若隻需要旋轉90,180,270,360請調用接口RotateSpecificAngle
BOOL CWFBitmap::Rotate(
	CWFBitmap &dstBitmap,      // 帶出旋轉後的圖像
	float fAngle               // 特定旋轉角度(機關:度)
	)
{
	// 得到新的IBitmapImage
	IBitmapImage *pNewBitmapImage = NULL;   
	if (RotateToIBitmapImage(pNewBitmapImage, fAngle) == FALSE)
	{
		return FALSE;
	}	

	// 通過IImage對象加載
	BOOL bRet = dstBitmap.LoadFromIBitmapImage(pNewBitmapImage);

	// 釋放新的對象
	if (pNewBitmapImage != NULL)
	{
		pNewBitmapImage->Release();
		pNewBitmapImage = NULL;
	}

	// 傳回結果
	return bRet; 	
}

// 獲得圖像資料(隻含有各個點的顔色資訊)
BOOL CWFBitmap::GetColorBuf(
	unsigned char *pDataBuf,           // 存放圖像資料緩沖區
	DWORD dwcbBufSize,                 // 緩沖區實際大小(需要的大小通常是(寬度*高度*4))
	DWORD *pdwRealGetBytes             // 實際取得資料位元組大小
	)
{
	// 參數有效性
	if (pDataBuf==NULL || dwcbBufSize==0)
	{
		return FALSE;
	}

	// 擷取原始資料失敗
	if (CreateImgDateBuf() == FALSE)
	{
		return FALSE;
	}	

	// 計算實際取得資料位元組大小
	DWORD dwRealBytes = (dwcbBufSize < m_dwcbImgDataBufSize) ? dwcbBufSize : m_dwcbImgDataBufSize;
	if (dwRealBytes == 0)
	{
		return FALSE;
	}

	// 拷貝資料
	memcpy(pDataBuf, m_pImgDataBuf, dwRealBytes);

	// 帶出實際拷貝資料位元組數
	if (pdwRealGetBytes != NULL)
	{
		*pdwRealGetBytes = dwRealBytes;
	}

	// 取得資料成功
	return TRUE;
}

// 獲得圖檔資料(隻含有各個點的顔色資訊)緩沖區位址,傳回NULL表示沒有圖檔資料
const unsigned char* CWFBitmap::GetColorBufAddr(
	DWORD *pdwcbBufSize          // 帶出顔色緩沖區位元組大小
	)
{
	// 初始化輸出參數
	if (pdwcbBufSize != NULL)
	{
		*pdwcbBufSize = 0;
	}

	// 擷取原始資料失敗
	if (CreateImgDateBuf() == FALSE)
	{
		return NULL;
	}	

	// 帶出實際大小
	if (pdwcbBufSize != NULL)
	{
		*pdwcbBufSize = m_dwcbImgDataBufSize;
	}

	// 傳回位址
	return m_pImgDataBuf;
}

//
// 建立Image工廠接口對象
BOOL CWFBitmap::CreateImagingFactory(void)
{
	// 已經建立了Image工廠接口對象
	if (m_pImagingFactory != NULL)
	{
		m_dwObjCounts += 1;
		return TRUE;
	}

	// 未建立則建立Image工廠接口對象
	m_dwObjCounts = 0;

	// COM初始化
	HRESULT hr = NULL;
	if (FAILED(hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED)))
	{  
		return FALSE;
	}

	// 建立COM執行個體
	if(FAILED(hr = ::CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**)&m_pImagingFactory)))
	{		
		return FALSE;
	}	

	// 建立成功數量增加
	m_dwObjCounts += 1;	
	return TRUE;
}

// 釋放Image工廠接口對象
void CWFBitmap::DeleteImagingFactory(void)
{
	if (m_pImagingFactory!=NULL && m_dwObjCounts>0)
	{
		m_dwObjCounts -= 1;
		if (m_dwObjCounts == 0)
		{
			// 釋放ImagingFactory		
			m_pImagingFactory->Release();
			m_pImagingFactory = NULL;			

			// 釋放COM
			::CoUninitialize();
		}		
	}
}

// 為圖檔建立記憶體DC
HDC CWFBitmap::CreateImgDC(HDC hdc)
{
	if (m_hDrawDC != NULL)
	{
		return m_hDrawDC;
	}

	// 建立記憶體DC
	m_hDrawDC = ::CreateCompatibleDC(hdc);			
	m_hBitmap = ::CreateCompatibleBitmap(hdc, m_ImageInfo.Width, m_ImageInfo.Height);
	m_hOldBitmap = (HBITMAP)::SelectObject(m_hDrawDC, m_hBitmap);

	// 填充背景為全黑色
	::PatBlt(m_hDrawDC, 0, 0, m_ImageInfo.Width, m_ImageInfo.Height, BLACKNESS);

	// 繪制圖像到記憶體DC上
	RECT rcDc = {0, 0, m_ImageInfo.Width, m_ImageInfo.Height};
	m_pImage->Draw(m_hDrawDC, &rcDc, NULL);
	return m_hDrawDC;
}

// 清除記憶體DC
void CWFBitmap::DeleteImgDC(void)
{
	if (m_hDrawDC != NULL)
	{
		::SelectObject(m_hDrawDC, m_hOldBitmap);
		::DeleteObject(m_hBitmap);		
		::DeleteDC(m_hDrawDC);
		m_hDrawDC = NULL;
		m_hBitmap = NULL;
		m_hOldBitmap = NULL;
	}
}

// 取得圖檔原始資料
BOOL CWFBitmap::CreateImgDateBuf(void)
{
	// 已經擷取到了原始資料
	if (m_pImgDataBuf != NULL)
	{	
		return TRUE;
	}

	// 參數有效性
	if (m_pImage==NULL || m_pImagingFactory==NULL)
	{		
		return FALSE;
	}

	// 取得圖檔原始資料
	RECT rect = {0, 0, m_ImageInfo.Width, m_ImageInfo.Height};  
	BitmapData bitmapData;  
	bitmapData.Width = m_ImageInfo.Width;  
	bitmapData.Height = m_ImageInfo.Height;  
	bitmapData.PixelFormat = m_ImageInfo.PixelFormat;  
	IBitmapImage *pBitmapImage = NULL;  
	HRESULT hr = m_pImagingFactory->CreateBitmapFromImage(m_pImage, m_ImageInfo.Width, m_ImageInfo.Height, PIXFMT_32BPP_ARGB, InterpolationHintDefault, &pBitmapImage);  
	if (FAILED(hr))
	{
		printf("CreateImgDateBuf CreateBitmapFromImage Error!\n");
		return FALSE;
	}

	// 鎖定位圖資料
	hr = pBitmapImage->LockBits(&rect, ImageLockModeRead, PIXFMT_32BPP_ARGB, &bitmapData);  
	if (FAILED(hr))
	{
		printf("CreateImgDateBuf LockBits Error!\n");
		pBitmapImage->Release();
		return FALSE;
	}

	// 用于傳回結果
	BOOL bRet = TRUE;

	// 得到資料位元組大小
	m_dwcbImgDataBufSize = m_ImageInfo.Width * m_ImageInfo.Height * 4;
	if (m_dwcbImgDataBufSize == 0)
	{
		bRet = FALSE;
		goto ERROR_END_FUNCTION;
	}

	// 申請新空間
	bRet = TRUE;	
	m_pImgDataBuf = new unsigned char[m_dwcbImgDataBufSize];
	if (m_pImgDataBuf == NULL)
	{	
		bRet = FALSE;
		goto ERROR_END_FUNCTION;
	}

	// 拷貝資料
	bRet = TRUE;
	memcpy(m_pImgDataBuf, bitmapData.Scan0, m_ImageInfo.Width * m_ImageInfo.Height * 4);  

ERROR_END_FUNCTION:
	pBitmapImage->UnlockBits(&bitmapData);  
	pBitmapImage->Release();  	
	return bRet;
}

// 銷毀圖檔原始資料
void CWFBitmap::DeleteImgDateBuf(void)
{
	if (m_pImgDataBuf != NULL)
	{
		delete[] m_pImgDataBuf;
		m_pImgDataBuf = NULL;
		m_dwcbImgDataBufSize = 0;
	}
}

// 拷貝一個IBitmapImage到另一個IBitmapImage中
BOOL CWFBitmap::CopyBitmapImage(
	IBitmapImage *pSrcBitmapImage,           // 源IBitmapImage
	PWFIBitmapImage &pDstBitmapImage         // 目标IBitmapImage
	)
{
	// 釋放目标對象
	if (pDstBitmapImage != NULL)
	{
		pDstBitmapImage->Release();
		pDstBitmapImage = NULL;
	}

	// 參數有效性
	if (pSrcBitmapImage == NULL)
	{
		return FALSE;
	}

	// 得到原圖IImage
	IImage *pSrcImage = NULL;
	HRESULT hr = pSrcBitmapImage->QueryInterface(IID_IImage, (void**)&pSrcImage);
	if (FAILED(hr))
	{
		printf("CopyBitmapImage QueryInterface SrcImage Error!\n");
		return FALSE;
	}

	// 使用到的臨時變量在此處聲明,因為下面需要使用goto語句
	BOOL bRet = FALSE;                  // 用于傳回函數結果
	ImageInfo srcImageInfo;             // 存放原圖圖像資訊
	RECT rect;                          // 用于鎖定圖像資料時的區域
	BitmapData srcBitmapData;           // 用于鎖定原圖資料 
	BOOL bLockedSrcImg = FALSE;         // 是否鎖定原圖 
	BitmapData dstBitmapData;           // 用于鎖定新圖像資料
	BOOL bLockedDstImg = FALSE;         // 是否鎖定新圖

	// 得到原圖ImageInfo	
	hr = pSrcImage->GetImageInfo(&srcImageInfo);
	if (FAILED(hr))
	{
		printf("CopyBitmapImage GetImageInfo srcImageInfo Error!\n");		
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;
	}

	// 鎖定原圖資料區
	rect.left = 0;
	rect.top = 0;
	rect.right = srcImageInfo.Width;
	rect.bottom = srcImageInfo.Height;
	srcBitmapData.Width = srcImageInfo.Width;  
	srcBitmapData.Height = srcImageInfo.Height;  
	srcBitmapData.PixelFormat = srcImageInfo.PixelFormat; 
	hr = pSrcBitmapImage->LockBits(&rect, ImageLockModeRead, srcImageInfo.PixelFormat, &srcBitmapData);
	bLockedSrcImg = TRUE;
	if (FAILED(hr))
	{
		printf("CopyBitmapImage LockBits srcBitmapData Error!\n");
		bLockedSrcImg = FALSE;
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;
	}

	//
	// 建立新的位圖
	hr = m_pImagingFactory->CreateNewBitmap(srcImageInfo.Width, srcImageInfo.Height, PIXFMT_32BPP_ARGB, &pDstBitmapImage);	
	if (FAILED(hr))
	{
		printf("CopyBitmapImage CreateNewBitmap Error!\n");		
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;
	}	 

	// 鎖定新位圖資料	
	dstBitmapData.Width = srcImageInfo.Width;  
	dstBitmapData.Height = srcImageInfo.Height;  
	dstBitmapData.PixelFormat = srcImageInfo.PixelFormat; 	
	hr = pDstBitmapImage->LockBits(&rect, ImageLockModeRead, PIXFMT_32BPP_ARGB, &dstBitmapData);  
	bLockedDstImg = TRUE;
	if (FAILED(hr))
	{
		printf("CopyBitmapImage LockBits dstBitmapData Error!\n");
		bLockedDstImg = FALSE;
		bRet = FALSE;
		goto THEEND_FOR_THISFOUNCTION;		
	}

	//
	// 把原圖資料寫人新圖		
	memcpy((BYTE*)dstBitmapData.Scan0, (BYTE*)srcBitmapData.Scan0, srcImageInfo.Width*srcImageInfo.Height*4);	
	bRet = TRUE;	

	// 進入資源釋放過程
THEEND_FOR_THISFOUNCTION:
	// 鎖定了原圖
	if (bLockedSrcImg == TRUE)
	{
		pSrcBitmapImage->UnlockBits(&srcBitmapData);
	}

	// 鎖定了新圖
	if (bLockedDstImg == TRUE)
	{
		pDstBitmapImage->UnlockBits(&dstBitmapData);
	}

	// 釋放原圖IImage
	if (pSrcImage != NULL)
	{
		pSrcImage->Release();
		pSrcImage = NULL;
	}

	// 傳回結果
	return bRet;
}
           

涉及到的矩形類頭檔案如下:

/********************************************************************
    Copyright(c) 2011, 
 	All rights reserved.
	purpose:	矩形類

    目前版本:   1.0
    作    者:   zhangwf
    建立日期:   2011:9:6
    完成日期:   
    
    取代版本:
    作    者:
    完成日期:   
*********************************************************************/
#ifndef _WF_RECT_H_
#define _WF_RECT_H_
//
class CWFRect
{
public: // 成員變量
	long x;    // 左上角X坐标
	long y;    // 左上角Y坐标
	long w;    // 矩形寬度
	long h;    // 矩形高度

public:
	// 構造函數
	CWFRect();

	// 析構函數
	~CWFRect();

	// 帶參構造
	CWFRect(long x, long y, long w, long h);

	// 拷貝構造函數
	CWFRect(const CWFRect &other);	

	// 指派函數
	CWFRect& operator=(const CWFRect &other);  

	// 比較是否相等
	bool operator==(const CWFRect &other);

	// 比較是否不等
	bool operator!=(const CWFRect &other);

	// 檢查是否被另一個矩形包含	
	bool operator<=(const CWFRect &other);

	// 檢查是否包含另一個矩形	
	bool operator>=(const CWFRect &other);

	// 求矩形交集,沒有交集傳回CWFRect(0,0,0,0)
	CWFRect operator&(const CWFRect &other);

	// 求矩形交集,沒有交集結果為CWFRect(0,0,0,0)
	CWFRect& operator&=(const CWFRect &other);

	// 求并集,傳回能夠包含此兩個矩形的矩形區域
	CWFRect operator|(const CWFRect &other);

	// 求并集,結果為能夠包含此兩個矩形的矩形區域
	CWFRect& operator|=(const CWFRect &other);

	// 該矩形區域是否包含某點
	bool CheckIn(long x, long y);

	// 檢測是否有效(檢測矩形寬度和高度不能小于或等于0)
	bool CheckValid(void);
};

//
#endif
           

涉及到的矩形類實作檔案如下:

/********************************************************************
    Copyright(c) 2011, 
 	All rights reserved.
	purpose:	矩形類

    目前版本:   1.0
    作    者:   zhangwf
    建立日期:   2011:9:6
    完成日期:   
    
    取代版本:
    作    者:
    完成日期:   
*********************************************************************/
#include "WFRect.h"
//
// 構造函數
CWFRect::CWFRect()
: x(0)
, y(0)
, w(0)
, h(0)
{

}

// 析構函數
CWFRect::~CWFRect()
{

}

// 帶參構造
CWFRect::CWFRect(long x, long y, long w, long h)
: x(x)
, y(y)
, w(w)
, h(h)
{

}

// 拷貝構造函數
CWFRect::CWFRect(const CWFRect &other)
: x(other.x)
, y(other.y)
, w(other.w)
, h(other.h)
{

}

// 指派函數
CWFRect& CWFRect::operator=(const CWFRect &other)
{
	// 檢查自指派
	if (this == &other)
	{
		return *this;
	}

	// 指派
	x = other.x;
	y = other.y;
	w = other.w;
	h = other.h;
	return *this;
}

// 比較是否相等
bool CWFRect::operator==(const CWFRect &other)
{
	// 檢查是否和自己比較
	if (this == &other)
	{
		return true;
	}

	// 比較是否相等
	return (x==other.x && y==other.y && w==other.w && h==other.h);
}

// 比較是否不等
bool CWFRect::operator!=(const CWFRect &other)
{
	// 檢查是否和自己比較
	if (this == &other)
	{
		return false;
	}

	// 比較是否不等
	return (x!=other.x || y!=other.y || w!=other.w || h!=other.h);
}

// 檢查是否被另一個矩形包含	
bool CWFRect::operator<=(const CWFRect &other)
{
	// 檢查是否和自己比較
	if (this == &other)
	{
		return true;
	}

	// 比較是否被另一個矩形包含
	return (x>=other.x && (x+w)<=(other.x+other.w) && y>=other.y && (y+h)<=(other.y+other.h));
}

// 檢查是否包含另一個矩形	
bool CWFRect::operator>=(const CWFRect &other)
{
	// 檢查是否和自己比較
	if (this == &other)
	{
		return true;
	}

	// 比較是否包含另一個矩形
	return (other.x>=x && (other.x+other.w)<=(x+w) && other.y>=y && (other.y+other.h)<=(y+h));
}

// 求矩形交集
CWFRect CWFRect::operator&(const CWFRect &other)
{
	// 是否和自己求交集
	if (this == &other)
	{
		return *this;
	}

	// 計算相交區域左上角點坐标
	long lTopX = (x >= other.x) ? x : other.x;
	long lTopY = (y >= other.y) ? y : other.y;

	// 計算相交區域有效角點坐标
	long rBtmX = ((x+w) >= (other.x+other.w)) ? (other.x+other.w) : (x+w);
	long rBtmY = ((y+h) >= (other.y+other.h)) ? (other.y+other.h) : (y+h);

	// 傳回交集
	return (lTopX>rBtmX || lTopY>rBtmY) ? CWFRect(0,0,0,0) : CWFRect(lTopX, lTopY, rBtmX-lTopX, rBtmY-lTopY);
}

// 求矩形交集
CWFRect& CWFRect::operator&=(const CWFRect &other)
{
	// 是否和自己求交集
	if (this == &other)
	{
		return *this;
	}

	// 計算相交區域左上角點坐标
	long lTopX = (x >= other.x) ? x : other.x;
	long lTopY = (y >= other.y) ? y : other.y;

	// 計算相交區域有效角點坐标
	long rBtmX = ((x+w) >= (other.x+other.w)) ? (other.x+other.w) : (x+w);
	long rBtmY = ((y+h) >= (other.y+other.h)) ? (other.y+other.h) : (y+h);

	// 計算交集結果
	// 沒有交集
	if (lTopX>rBtmX || lTopY>rBtmY)
	{
		x = 0;
		y = 0;
		w = 0;
		h = 0;
	}
	// 具有交集
	else
	{
		x = lTopX;
		y = lTopY;
		w = rBtmX - lTopX;
		h = rBtmY - lTopY;	
	}

	// 傳回結果
	return *this;
}

// 求并集,傳回能夠包含此兩個矩形的矩形區域
CWFRect CWFRect::operator|(const CWFRect &other)
{
	// 是否和自己求并集
	if (this == &other)
	{
		return *this;
	}

	// 計算合并區域左上角坐标
	long lTopX = (x <= other.x) ? x : other.x;
	long lTopY = (y <= other.y) ? y : other.y;

	// 計算合并區域右下角坐标
	long rBtmX = ((x+w) <= (other.x+other.w)) ? (other.x+other.w) : (x+w);
	long rBtmY = ((y+h) <= (other.y+other.h)) ? (other.y+other.h) : (y+h);

	// 傳回并集
	return CWFRect(lTopX, lTopY, rBtmX-lTopX, rBtmY-lTopY);
}

// 求并集,結果為能夠包含此兩個矩形的矩形區域
CWFRect& CWFRect::operator|=(const CWFRect &other)
{
	// 是否和自己求并集
	if (this == &other)
	{
		return *this;
	}

	// 計算合并區域左上角坐标
	long lTopX = (x <= other.x) ? x : other.x;
	long lTopY = (y <= other.y) ? y : other.y;

	// 計算合并區域右下角坐标
	long rBtmX = ((x+w) <= (other.x+other.w)) ? (other.x+other.w) : (x+w);
	long rBtmY = ((y+h) <= (other.y+other.h)) ? (other.y+other.h) : (y+h);

	// 計算并集
	x = lTopX;
	y = lTopY;
	w = rBtmX - lTopX;
	h = rBtmY - lTopY;
	return *this;
}

// 該矩形區域是否包含某點
bool CWFRect::CheckIn(long x, long y)
{
	return (x>=this->x && x<=(this->x+this->w) && y>=this->y && y<=(this->y+this->h));
}

// 檢測是否有效(檢測矩形寬度和高度不能小于或等于0)
bool CWFRect::CheckValid(void)
{
	return (w>0 && h>0);
}