头文件如下:
/******************************************************************** 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); }