主程序:
#define PI 3.1415926535
#define RADIAN(angle) ((angle)*PI/180.0) //convert angle to radian
CBitmap m_bmp;
HBITMAP hbit;
hbit = m_voimg.Copy(); //该句得到一个hbitmap句柄
m_bmp.Attach(hbit);
......
HBITMAP tempbit;
tempbit = GetRotatedBitmap(hbit,RADIAN(90), RGB(255,255,0));
m_bmp .DeleteObject();
m_bmp.Attach(tempbit);
旋转函数:
HBITMAP GetRotatedBitmap( HBITMAP hBitmap, float radians, COLORREF clrBack )
{
// Create a memory DC compatible with the display
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC( NULL );
destDC.CreateCompatibleDC( NULL );
// Get logical coordinates
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
float cosine = (float)cos(radians);
float sine = (float)sin(radians);
// Compute dimensions of the resulting bitmap
// First get the coordinates of the 3 corners other than origin
int x1 = (int)(-bm.bmHeight * sine);
int y1 = (int)(bm.bmHeight * cosine);
int x2 = (int)(bm.bmWidth * cosine - bm.bmHeight * sine);
int y2 = (int)(bm.bmHeight * cosine + bm.bmWidth * sine);
int x3 = (int)(bm.bmWidth * cosine);
int y3 = (int)(bm.bmWidth * sine);
int minx = min(0,min(x1, min(x2,x3)));
int miny = min(0,min(y1, min(y2,y3)));
int maxx = max(x1, max(x2,x3));
int maxy = max(y1, max(y2,y3));
int w = maxx - minx;
int h = maxy - miny;
// Create a bitmap to hold the result
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(this), w, h);
HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
// Draw the background color before we change mapping mode
HBRUSH hbrBack = CreateSolidBrush( clrBack );
HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
destDC.PatBlt( 0, 0, w, h, PATCOPY );
::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
// Now do the actual rotating - a pixel at a time
// Computing the destination point for each source point
// will leave a few pixels that do not get covered
// So we use a reverse transform - e.i. compute the source point
// for each destination point
for( int y = miny; y < maxy; y++ )
{
for( int x = minx; x < maxx; x++ )
{
int sourcex = (int)(x*cosine + y*sine);
int sourcey = (int)(y*cosine - x*sine);
if( sourcex >= 0 && sourcex < bm.bmWidth && sourcey >= 0 && sourcey < bm.bmHeight )
{
COLORREF col = sourceDC.GetPixel(sourcex,sourcey);
destDC.SetPixel(x,y,col);
}
}
}
// Restore DCs
::SelectObject( sourceDC.m_hDC, hbmOldSource );
::SelectObject( destDC.m_hDC, hbmOldDest );
return hbmResult;
}
结果我再次把m_bmp显示到屏幕上时,出来没有图象,只有单一的一片颜色,这个颜色为我调用GetRotatedBitmap(hbit,RADIAN(90), RGB(255,255,0)) 时,的最后一个参数的RGB颜色,为什么呢?难道是GetPixel()没有取到东西???请高手指点呀!
11 个解决方案
#1
例子:
http://www.vckbase.com/document/viewdoc.asp?id=451
http://www.vckbase.com/document/viewdoc.asp?id=451
#2
请用GDI+,里面旋转已经封装了,用matiax实现
#3
你传进来的是HBITMAP,那为什么又要转换成CDC呢?这不是绕了个弯吗?
#4
我是在CE下实现,CE下好象不支持这些吧?他的哪个EVC++,功能没有VC++强大。
#5
请问 jszj: 那我怎么直接用HBITMAP进行转换呢?
#6
help 呀...........
#7
/**
* 快速旋转指定的Dib对象
* @param pDib 待旋转的Dib对象
* @param nAngle 旋转角度(角度制)
*/
void DIB_RotateFast(CDib *pDib, int nAngle) {
int i, j;
CDib *pTmp;
nAngle %= 360;
BYTE **scanLines = new BYTE*[pDib->m_nHeight];
BYTE *pScanLine = pDib->m_pBits;
for (i = 0; i < pDib->m_nHeight; i++) {
*(scanLines+i) = pScanLine;
pScanLine += pDib->m_nPitch;
}
switch (nAngle) {
case 0:
delete scanLines;
return;
case 90:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate90Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
case 180:
DIB_Flip(pDib, FLIP_HORIZONTAL | FLIP_VERTICAL);
return;
case 270:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate270Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
default:
break;
}
double dAngle = nAngle/180.0 * PI;
int nSin = (int)(sin(dAngle)*65536.0+0.5);
int nCos = (int)(cos(dAngle)*65536.0+0.5);
POINT vertex[] = {
{0, 0},
{(pDib->m_nWidth*nCos) >> 16, (pDib->m_nWidth*nSin) >> 16},
{(pDib->m_nWidth*nCos + pDib->m_nHeight*nSin) >> 16, (pDib->m_nWidth*nSin - pDib->m_nHeight*nCos) >> 16},
{(pDib->m_nHeight*nSin) >> 16, (-pDib->m_nHeight*nCos) >> 16}
};
POINT newVertex[4];
if (nAngle > 0 && nAngle < 90) {
newVertex[0] = vertex[0];
newVertex[1] = vertex[1];
newVertex[2] = vertex[2];
newVertex[3] = vertex[3];
} else if (nAngle > 90 && nAngle < 180) {
newVertex[0] = vertex[1];
newVertex[1] = vertex[2];
newVertex[2] = vertex[3];
newVertex[3] = vertex[0];
} else if (nAngle > 180 && nAngle < 270) {
newVertex[0] = vertex[2];
newVertex[1] = vertex[3];
newVertex[2] = vertex[0];
newVertex[3] = vertex[1];
} else {
newVertex[0] = vertex[3];
newVertex[1] = vertex[0];
newVertex[2] = vertex[1];
newVertex[3] = vertex[2];
}
SIZE newSize;
int edgeSlope[4];
int edgeConst[4];
int deltaX = nCos*newVertex[0].x+nSin*newVertex[1].y;
int deltaY = nCos*newVertex[1].y-nSin*newVertex[0].x;
dib_GetEdgeFormulas(newVertex, &newSize, edgeSlope, edgeConst);
pTmp = new CDib(newSize.cx, newSize.cy, g_colorKey);
int ox, oy;
int boundLeft, boundRight;
BYTE *pVInc = pTmp->m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
int actualY = -pTmp->m_nHeight;
for (i = 0; i > actualY; i--) {
if (i > newVertex[0].y) {
boundLeft = (edgeSlope[0]*i + edgeConst[0]) >> 16;
} else {
boundLeft = (edgeSlope[1]*i + edgeConst[1]) >> 16;
}
if (i > newVertex[2].y) {
boundRight = (edgeSlope[2]*i + edgeConst[2]) >> 16;
} else {
boundRight = (edgeSlope[3]*i + edgeConst[3]) >> 16;
}
pHInc = pVInc+boundLeft+boundLeft+boundLeft; // 把水平增量指针初始化为当前扫描行的首址
for (j = boundLeft; j < boundRight; j++) {
ox = (nCos*j+nSin*i+deltaX) >> 16;
oy = -((nCos*i-nSin*j+deltaY) >> 16);
ox = ox < 0 ? 0 : ox;
ox = ox >= pDib->m_nWidth ? pDib->m_nWidth-1 : ox;
oy = oy < 0 ? 0 : oy;
oy = oy >= pDib->m_nHeight ? pDib->m_nHeight-1 : oy;
dib_SetColor(pHInc, dib_GetColor(*(scanLines+oy)+ox+ox+ox));
pHInc += PIXELSIZE; // 一个像素数据过滤完成,指针指向下一个
}
pVInc += pTmp->m_nPitch; // 一个扫描行处理完,指针指向下一行
}
*pDib = *pTmp;
delete scanLines;
delete pTmp;
}
* 快速旋转指定的Dib对象
* @param pDib 待旋转的Dib对象
* @param nAngle 旋转角度(角度制)
*/
void DIB_RotateFast(CDib *pDib, int nAngle) {
int i, j;
CDib *pTmp;
nAngle %= 360;
BYTE **scanLines = new BYTE*[pDib->m_nHeight];
BYTE *pScanLine = pDib->m_pBits;
for (i = 0; i < pDib->m_nHeight; i++) {
*(scanLines+i) = pScanLine;
pScanLine += pDib->m_nPitch;
}
switch (nAngle) {
case 0:
delete scanLines;
return;
case 90:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate90Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
case 180:
DIB_Flip(pDib, FLIP_HORIZONTAL | FLIP_VERTICAL);
return;
case 270:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate270Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
default:
break;
}
double dAngle = nAngle/180.0 * PI;
int nSin = (int)(sin(dAngle)*65536.0+0.5);
int nCos = (int)(cos(dAngle)*65536.0+0.5);
POINT vertex[] = {
{0, 0},
{(pDib->m_nWidth*nCos) >> 16, (pDib->m_nWidth*nSin) >> 16},
{(pDib->m_nWidth*nCos + pDib->m_nHeight*nSin) >> 16, (pDib->m_nWidth*nSin - pDib->m_nHeight*nCos) >> 16},
{(pDib->m_nHeight*nSin) >> 16, (-pDib->m_nHeight*nCos) >> 16}
};
POINT newVertex[4];
if (nAngle > 0 && nAngle < 90) {
newVertex[0] = vertex[0];
newVertex[1] = vertex[1];
newVertex[2] = vertex[2];
newVertex[3] = vertex[3];
} else if (nAngle > 90 && nAngle < 180) {
newVertex[0] = vertex[1];
newVertex[1] = vertex[2];
newVertex[2] = vertex[3];
newVertex[3] = vertex[0];
} else if (nAngle > 180 && nAngle < 270) {
newVertex[0] = vertex[2];
newVertex[1] = vertex[3];
newVertex[2] = vertex[0];
newVertex[3] = vertex[1];
} else {
newVertex[0] = vertex[3];
newVertex[1] = vertex[0];
newVertex[2] = vertex[1];
newVertex[3] = vertex[2];
}
SIZE newSize;
int edgeSlope[4];
int edgeConst[4];
int deltaX = nCos*newVertex[0].x+nSin*newVertex[1].y;
int deltaY = nCos*newVertex[1].y-nSin*newVertex[0].x;
dib_GetEdgeFormulas(newVertex, &newSize, edgeSlope, edgeConst);
pTmp = new CDib(newSize.cx, newSize.cy, g_colorKey);
int ox, oy;
int boundLeft, boundRight;
BYTE *pVInc = pTmp->m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
int actualY = -pTmp->m_nHeight;
for (i = 0; i > actualY; i--) {
if (i > newVertex[0].y) {
boundLeft = (edgeSlope[0]*i + edgeConst[0]) >> 16;
} else {
boundLeft = (edgeSlope[1]*i + edgeConst[1]) >> 16;
}
if (i > newVertex[2].y) {
boundRight = (edgeSlope[2]*i + edgeConst[2]) >> 16;
} else {
boundRight = (edgeSlope[3]*i + edgeConst[3]) >> 16;
}
pHInc = pVInc+boundLeft+boundLeft+boundLeft; // 把水平增量指针初始化为当前扫描行的首址
for (j = boundLeft; j < boundRight; j++) {
ox = (nCos*j+nSin*i+deltaX) >> 16;
oy = -((nCos*i-nSin*j+deltaY) >> 16);
ox = ox < 0 ? 0 : ox;
ox = ox >= pDib->m_nWidth ? pDib->m_nWidth-1 : ox;
oy = oy < 0 ? 0 : oy;
oy = oy >= pDib->m_nHeight ? pDib->m_nHeight-1 : oy;
dib_SetColor(pHInc, dib_GetColor(*(scanLines+oy)+ox+ox+ox));
pHInc += PIXELSIZE; // 一个像素数据过滤完成,指针指向下一个
}
pVInc += pTmp->m_nPitch; // 一个扫描行处理完,指针指向下一行
}
*pDib = *pTmp;
delete scanLines;
delete pTmp;
}
#8
void DIB_RotateFast(CDib *pDib, int nAngle)
这里的CDib是哪里来的呢,没有这个类呀。
这里的CDib是哪里来的呢,没有这个类呀。
#9
/**********************************************************
dibcore.h WannaPlayDIB实用图形库 类、接口和核心API声明
版权所有(C) 2001 WannaPlay
WannaPlay实用图形函数库完全*发放。
任何人都可以没有限制的使用、修改和再发布本代码。
同时作者也没有义务为代码可能对你的应用和系统造
成的任何损害承担责任。
发现任何Bug,缺陷,或有任何意见和建议,请联系作者。
谢谢。
Home Page: http://wannaplay.51.net
eMail: rocks_lee@263.net
OICQ: 17219193
***********************************************************/
#ifndef __WANNAPLAY_DIBCORE_H__
#define __WANNAPLAY_DIBCORE_H__
#include "dibstruct.h"
class CDib;
class IAbstractFilter;
class IImageWrapper;
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库自定义类型
//////////////////////////////////////////////////////////////////////
// 颜色数据。CDib每像素由3 bytes组成,在内存中的排列顺序是bbggrr,
// 这是与GDI的24位DIB完全相同的。
// 用这个类型可以一次得到全部三个分量,最高字节置零。
// 而Windows的COLORREF则是最低字节置零,所以必要时要做转换。
typedef DWORD DIB_COLOR;
// 滤波器回调函数类型。可以与DIB_Filter()函数配合使用,以实现多种滤波算法。
// DIB_Filter()函数对每个像素回调该函数。
typedef void (CALLBACK* DIB_FILTERPROC)(CDib *pDib, // 用这个参数配合下面的x 和 y,
int x, // 可以访问和本像素相关的其它像素。
int y, // 其实如果你愿意,是可以访问任何一个像素数据的。
BYTE *pixel, // 这是个快捷方式,如果你只对当前像素感兴趣。
void *filterParam); // 回调函数自定义参数,从DIB_Filter()简单传递而来。
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常量定义,包括常用颜色和每像素长度
//////////////////////////////////////////////////////////////////////
// 常用的几种颜色
#define COLOR_BLACK ((DIB_COLOR)0x00000000)
#define COLOR_WHITE ((DIB_COLOR)0x00ffffff)
#define COLOR_BLUE ((DIB_COLOR)0x000000ff)
#define COLOR_GREEN ((DIB_COLOR)0x0000ff00)
#define COLOR_RED ((DIB_COLOR)0x00ff0000)
// 每像素的字节数
#define PIXELSIZE 3
// DIB_LoadImage的options
#define LOAD_FROMFILE 0x01
#define LOAD_FROMRES 0x02
// DIB_Flip的options
#define FLIP_HORIZONTAL 0x01
#define FLIP_VERTICAL 0x02
// DIB_Blt和DIB_BltFast的options
#define BLT_COLORKEY 0x01
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用宏定义
//////////////////////////////////////////////////////////////////////
// 从扫描行的像素数得到字节数。DIB的扫描行是双字(DWORD)对齐的
#define DIB_WIDTH2PITCH(w) (((w)+(w)+(w)+3) & 0xfffffffc)
// 得到颜色的RED分量
#define DIB_RVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_RED)>>16))
// 得到颜色的GREEN分量
#define DIB_GVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_GREEN)>>8))
// 得到颜色的BLUE分量
#define DIB_BVALUE(color) ((BYTE)((DIB_COLOR)(color) & COLOR_BLUE))
// 把三个BYTE分量重新组合成一个DIB_COLOR
#define DIB_RGB(r, g, b) (0 | (((r)<<16)&COLOR_RED) | (((g)<<8)&COLOR_GREEN) | ((b)&COLOR_BLUE))
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用辅助函数
//////////////////////////////////////////////////////////////////////
// 用一个DIB_COLOR(4 Bytes)型参数快速给一个像素(3 Bytes)赋值
inline void dib_SetColor(BYTE *pPixel, DIB_COLOR color) {
*((DIB_COLOR*)pPixel) &= 0xff000000; // 把本像素清0,而下一个像素的首字节要保护起来
*((DIB_COLOR*)pPixel) |= color; // 这时像素的三个字节都为0,用or操作就可以了
}
// 把一个像素快速转换为DIB_COLOR类型
inline DIB_COLOR dib_GetColor(BYTE *pPixel) {
DIB_COLOR ret = *((DIB_COLOR*)pPixel); // 这样得到的值包含下一个像素的首字节
return ret & 0x00ffffff; // 把那个多余的字节屏蔽掉
}
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库的基本数据类型CDib的类定义和部分inline实现,
// 以及两个抽象的接口类,以便于灵活的扩展本库所支持的算法
// 和图形格式
//////////////////////////////////////////////////////////////////////
/**
* CDib类对设备无关位图(DIB)进行了简单的封装,比起GDI API中定义的DIB,
* 它更加简单而实用。
* CDib类以24位(3 bytes)表示一个像素,与GDI中的24位DIB格式兼容。即:
* 自底向上存储扫描行,每一扫描行长度DWORD对齐;
* 每像素3字节,存储顺序为bbggrr。
* WannaPlayDIB实用图形库所提供的所有算法都以CDib类作为操作对象和存储结构。
*/
class CDib {
public:
/**
* 缺省的构造函数
*/
CDib() : m_nWidth(0), m_nHeight(0), m_nPitch(0), m_pBits(NULL) {}
/**
* 根据给定的大小和颜色构造一个CDib对象
*/
CDib(int w, int h, DIB_COLOR colorInit);
/**
* 根据给定的大小和像素数据构造一个CDib对象
*/
CDib(int w, int h, BYTE *pBits) :
m_nWidth(w),
m_nHeight(h),
m_nPitch(DIB_WIDTH2PITCH(w)),
m_pBits(pBits) {}
/**
* 根据另一个CDib对象构造一个新的CDib对象
*/
CDib(CDib &refDib);
virtual ~CDib();
CDib operator =(CDib &refDib);
public:
DIB_COLOR GetPixel(int x, int y) {
return dib_GetColor(m_pBits+m_nPitch*y+x+x+x);
}
DIB_COLOR SetPixel(int x, int y, DIB_COLOR c) {
dib_SetColor((BYTE*)(m_pBits+m_nPitch*y+x+x+x), c);
}
public:
int m_nWidth;
int m_nHeight;
int m_nPitch;
BYTE *m_pBits;
};
/**
* 实现这个接口,与DIB_Filter()函数配合使用,
* 以支持更复杂的滤波算法(比如当像素间的互相关性较大时)
*/
class IAbstractFilter {
public:
virtual void Filter(CDib *pDib, int x, int y, BYTE *pixel) = 0;
};
/**
* 实现这个接口以支持更多的图形文件格式。
* 可以在子类中保存图形的更多信息,以便定制载入和保存操作
*/
class IImageWrapper {
public:
virtual CDib* LoadDib() = 0;
virtual void SaveDib(CDib *pDib) = 0;
};
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库API定义
//////////////////////////////////////////////////////////////////////
CDib* DIB_LoadImage(IImageWrapper *loader);
void DIB_SaveImage(CDib *pDib, IImageWrapper *writer);
void DIB_Filter(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam);
void DIB_Filter(CDib *pDib, IAbstractFilter *filter);
void DIB_FilterRect(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam, LPRECT pRect);
void DIB_SetColorKey(int rr, int gg, int bb);
void DIB_SetColorKey(DIB_COLOR colorKey);
DIB_COLOR DIB_GetColorKey();
void DIB_RotateFast(CDib *pDib, int nAngle);
void DIB_Rotate(CDib *pDib, double dAngle);
void DIB_StretchFast(CDib *pDib, int newWidth, int newHeight);
void DIB_Stretch(CDib *pDib, int newWidth, int newHeight);
void DIB_Flip(CDib *pDib, UINT uOption);
void DIB_BltFast(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
UINT uOptions);
void DIB_AlphaBlend(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
CDib *pDibAlpha,
int nXAlpha,
int nYAlpha);
void DIB_ClearColorRange(CDib *pDib,
DIB_COLOR colorLow,
DIB_COLOR colorHigh);
void DIB_Line(CDib *pDib, int x0, int y0, int x1, int y1);
#endif//__WANNAPLAY_DIBCORE_H__
dibcore.h WannaPlayDIB实用图形库 类、接口和核心API声明
版权所有(C) 2001 WannaPlay
WannaPlay实用图形函数库完全*发放。
任何人都可以没有限制的使用、修改和再发布本代码。
同时作者也没有义务为代码可能对你的应用和系统造
成的任何损害承担责任。
发现任何Bug,缺陷,或有任何意见和建议,请联系作者。
谢谢。
Home Page: http://wannaplay.51.net
eMail: rocks_lee@263.net
OICQ: 17219193
***********************************************************/
#ifndef __WANNAPLAY_DIBCORE_H__
#define __WANNAPLAY_DIBCORE_H__
#include "dibstruct.h"
class CDib;
class IAbstractFilter;
class IImageWrapper;
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库自定义类型
//////////////////////////////////////////////////////////////////////
// 颜色数据。CDib每像素由3 bytes组成,在内存中的排列顺序是bbggrr,
// 这是与GDI的24位DIB完全相同的。
// 用这个类型可以一次得到全部三个分量,最高字节置零。
// 而Windows的COLORREF则是最低字节置零,所以必要时要做转换。
typedef DWORD DIB_COLOR;
// 滤波器回调函数类型。可以与DIB_Filter()函数配合使用,以实现多种滤波算法。
// DIB_Filter()函数对每个像素回调该函数。
typedef void (CALLBACK* DIB_FILTERPROC)(CDib *pDib, // 用这个参数配合下面的x 和 y,
int x, // 可以访问和本像素相关的其它像素。
int y, // 其实如果你愿意,是可以访问任何一个像素数据的。
BYTE *pixel, // 这是个快捷方式,如果你只对当前像素感兴趣。
void *filterParam); // 回调函数自定义参数,从DIB_Filter()简单传递而来。
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常量定义,包括常用颜色和每像素长度
//////////////////////////////////////////////////////////////////////
// 常用的几种颜色
#define COLOR_BLACK ((DIB_COLOR)0x00000000)
#define COLOR_WHITE ((DIB_COLOR)0x00ffffff)
#define COLOR_BLUE ((DIB_COLOR)0x000000ff)
#define COLOR_GREEN ((DIB_COLOR)0x0000ff00)
#define COLOR_RED ((DIB_COLOR)0x00ff0000)
// 每像素的字节数
#define PIXELSIZE 3
// DIB_LoadImage的options
#define LOAD_FROMFILE 0x01
#define LOAD_FROMRES 0x02
// DIB_Flip的options
#define FLIP_HORIZONTAL 0x01
#define FLIP_VERTICAL 0x02
// DIB_Blt和DIB_BltFast的options
#define BLT_COLORKEY 0x01
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用宏定义
//////////////////////////////////////////////////////////////////////
// 从扫描行的像素数得到字节数。DIB的扫描行是双字(DWORD)对齐的
#define DIB_WIDTH2PITCH(w) (((w)+(w)+(w)+3) & 0xfffffffc)
// 得到颜色的RED分量
#define DIB_RVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_RED)>>16))
// 得到颜色的GREEN分量
#define DIB_GVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_GREEN)>>8))
// 得到颜色的BLUE分量
#define DIB_BVALUE(color) ((BYTE)((DIB_COLOR)(color) & COLOR_BLUE))
// 把三个BYTE分量重新组合成一个DIB_COLOR
#define DIB_RGB(r, g, b) (0 | (((r)<<16)&COLOR_RED) | (((g)<<8)&COLOR_GREEN) | ((b)&COLOR_BLUE))
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用辅助函数
//////////////////////////////////////////////////////////////////////
// 用一个DIB_COLOR(4 Bytes)型参数快速给一个像素(3 Bytes)赋值
inline void dib_SetColor(BYTE *pPixel, DIB_COLOR color) {
*((DIB_COLOR*)pPixel) &= 0xff000000; // 把本像素清0,而下一个像素的首字节要保护起来
*((DIB_COLOR*)pPixel) |= color; // 这时像素的三个字节都为0,用or操作就可以了
}
// 把一个像素快速转换为DIB_COLOR类型
inline DIB_COLOR dib_GetColor(BYTE *pPixel) {
DIB_COLOR ret = *((DIB_COLOR*)pPixel); // 这样得到的值包含下一个像素的首字节
return ret & 0x00ffffff; // 把那个多余的字节屏蔽掉
}
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库的基本数据类型CDib的类定义和部分inline实现,
// 以及两个抽象的接口类,以便于灵活的扩展本库所支持的算法
// 和图形格式
//////////////////////////////////////////////////////////////////////
/**
* CDib类对设备无关位图(DIB)进行了简单的封装,比起GDI API中定义的DIB,
* 它更加简单而实用。
* CDib类以24位(3 bytes)表示一个像素,与GDI中的24位DIB格式兼容。即:
* 自底向上存储扫描行,每一扫描行长度DWORD对齐;
* 每像素3字节,存储顺序为bbggrr。
* WannaPlayDIB实用图形库所提供的所有算法都以CDib类作为操作对象和存储结构。
*/
class CDib {
public:
/**
* 缺省的构造函数
*/
CDib() : m_nWidth(0), m_nHeight(0), m_nPitch(0), m_pBits(NULL) {}
/**
* 根据给定的大小和颜色构造一个CDib对象
*/
CDib(int w, int h, DIB_COLOR colorInit);
/**
* 根据给定的大小和像素数据构造一个CDib对象
*/
CDib(int w, int h, BYTE *pBits) :
m_nWidth(w),
m_nHeight(h),
m_nPitch(DIB_WIDTH2PITCH(w)),
m_pBits(pBits) {}
/**
* 根据另一个CDib对象构造一个新的CDib对象
*/
CDib(CDib &refDib);
virtual ~CDib();
CDib operator =(CDib &refDib);
public:
DIB_COLOR GetPixel(int x, int y) {
return dib_GetColor(m_pBits+m_nPitch*y+x+x+x);
}
DIB_COLOR SetPixel(int x, int y, DIB_COLOR c) {
dib_SetColor((BYTE*)(m_pBits+m_nPitch*y+x+x+x), c);
}
public:
int m_nWidth;
int m_nHeight;
int m_nPitch;
BYTE *m_pBits;
};
/**
* 实现这个接口,与DIB_Filter()函数配合使用,
* 以支持更复杂的滤波算法(比如当像素间的互相关性较大时)
*/
class IAbstractFilter {
public:
virtual void Filter(CDib *pDib, int x, int y, BYTE *pixel) = 0;
};
/**
* 实现这个接口以支持更多的图形文件格式。
* 可以在子类中保存图形的更多信息,以便定制载入和保存操作
*/
class IImageWrapper {
public:
virtual CDib* LoadDib() = 0;
virtual void SaveDib(CDib *pDib) = 0;
};
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库API定义
//////////////////////////////////////////////////////////////////////
CDib* DIB_LoadImage(IImageWrapper *loader);
void DIB_SaveImage(CDib *pDib, IImageWrapper *writer);
void DIB_Filter(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam);
void DIB_Filter(CDib *pDib, IAbstractFilter *filter);
void DIB_FilterRect(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam, LPRECT pRect);
void DIB_SetColorKey(int rr, int gg, int bb);
void DIB_SetColorKey(DIB_COLOR colorKey);
DIB_COLOR DIB_GetColorKey();
void DIB_RotateFast(CDib *pDib, int nAngle);
void DIB_Rotate(CDib *pDib, double dAngle);
void DIB_StretchFast(CDib *pDib, int newWidth, int newHeight);
void DIB_Stretch(CDib *pDib, int newWidth, int newHeight);
void DIB_Flip(CDib *pDib, UINT uOption);
void DIB_BltFast(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
UINT uOptions);
void DIB_AlphaBlend(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
CDib *pDibAlpha,
int nXAlpha,
int nYAlpha);
void DIB_ClearColorRange(CDib *pDib,
DIB_COLOR colorLow,
DIB_COLOR colorHigh);
void DIB_Line(CDib *pDib, int x0, int y0, int x1, int y1);
#endif//__WANNAPLAY_DIBCORE_H__
#10
//////////////////////////////////////////////////////////////////////
// CDib类的成员函数实现
//////////////////////////////////////////////////////////////////////
/**
* 创建指定大小的单色图像。
* @param w 宽度
* @param h 高度
* @param colorInit 初始化颜色
* 注意,如果你只是想创建一块用来绘图的数据缓冲,
* 那么请用黑色作为参数,效率将更高。
*/
CDib::CDib(int w, int h, DIB_COLOR colorInit) {
m_nWidth = w;
m_nHeight = h;
m_nPitch = DIB_WIDTH2PITCH(w);
int size = h*m_nPitch;
m_pBits = new BYTE[size]; // 分配图像数据内存
memset(m_pBits, 0, size); // 把这块得到的内存清0
if (colorInit == COLOR_BLACK) {
return; // 因为黑色实际就是全0,所以这里就可以快速返回了
}
// 下面将用一个二重循环访问每一个像素,并用指定的颜色赋值
int i = 0, j = 0; // 循环计数器
// 垂直方向的增量指针。每操作完一行数据,它就被指向下一个扫描行
BYTE *pVInc = m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
for (i = 0; i < h; i++) {
pHInc = pVInc; // 把水平增量指针初始化为当前扫描行的首址
for (j = 0; j < w; j++) {
dib_SetColor(pHInc, colorInit);
pHInc += PIXELSIZE; // 一个像素数据赋值完成,指针指向下一个
}
pVInc += m_nPitch; // 一个扫描行处理完,指针指向下一行
}
}
/**
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib::CDib(CDib &refDib) {
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
}
/**
* 析构函数。
* 把为这个CDib对象的图像数据分配的内存释放掉。
*/
CDib::~CDib() {
if (m_pBits != NULL) {
delete[] m_pBits;
}
}
/**
* 重载等号运算符。
* 这样你可以像对一个一般变量一样直接对一个CDib赋值。
* 和上面的第二个构造函数一样,
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib CDib::operator =(CDib &refDib) {
if (this == &refDib) {
return *this;
}
if (m_pBits != NULL) {
delete[] m_pBits;
}
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
return *this;
}
// CDib类的成员函数实现
//////////////////////////////////////////////////////////////////////
/**
* 创建指定大小的单色图像。
* @param w 宽度
* @param h 高度
* @param colorInit 初始化颜色
* 注意,如果你只是想创建一块用来绘图的数据缓冲,
* 那么请用黑色作为参数,效率将更高。
*/
CDib::CDib(int w, int h, DIB_COLOR colorInit) {
m_nWidth = w;
m_nHeight = h;
m_nPitch = DIB_WIDTH2PITCH(w);
int size = h*m_nPitch;
m_pBits = new BYTE[size]; // 分配图像数据内存
memset(m_pBits, 0, size); // 把这块得到的内存清0
if (colorInit == COLOR_BLACK) {
return; // 因为黑色实际就是全0,所以这里就可以快速返回了
}
// 下面将用一个二重循环访问每一个像素,并用指定的颜色赋值
int i = 0, j = 0; // 循环计数器
// 垂直方向的增量指针。每操作完一行数据,它就被指向下一个扫描行
BYTE *pVInc = m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
for (i = 0; i < h; i++) {
pHInc = pVInc; // 把水平增量指针初始化为当前扫描行的首址
for (j = 0; j < w; j++) {
dib_SetColor(pHInc, colorInit);
pHInc += PIXELSIZE; // 一个像素数据赋值完成,指针指向下一个
}
pVInc += m_nPitch; // 一个扫描行处理完,指针指向下一行
}
}
/**
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib::CDib(CDib &refDib) {
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
}
/**
* 析构函数。
* 把为这个CDib对象的图像数据分配的内存释放掉。
*/
CDib::~CDib() {
if (m_pBits != NULL) {
delete[] m_pBits;
}
}
/**
* 重载等号运算符。
* 这样你可以像对一个一般变量一样直接对一个CDib赋值。
* 和上面的第二个构造函数一样,
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib CDib::operator =(CDib &refDib) {
if (this == &refDib) {
return *this;
}
if (m_pBits != NULL) {
delete[] m_pBits;
}
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
return *this;
}
#11
用GDI+解决:
REAL PosX,PosY; //图像的初始位置
REAL centerX,centerY; //旋转中心
REAL Rangle; //旋转角度
PointF CenterPoint(centerX,centerY);
Graphics graphics(hdc);
Image newImage(L("filename")); //要旋转的图像
Matrix RotateMatrix; //旋转矩阵
graphics.DrawImage (newImage,PosX,PosY);
rotateMatrix.RotateAt(Rangle,CenterPoint,MatrixOrderPrepend)
graphics.SetTransform(RotateMatrix);
REAL PosX,PosY; //图像的初始位置
REAL centerX,centerY; //旋转中心
REAL Rangle; //旋转角度
PointF CenterPoint(centerX,centerY);
Graphics graphics(hdc);
Image newImage(L("filename")); //要旋转的图像
Matrix RotateMatrix; //旋转矩阵
graphics.DrawImage (newImage,PosX,PosY);
rotateMatrix.RotateAt(Rangle,CenterPoint,MatrixOrderPrepend)
graphics.SetTransform(RotateMatrix);
#1
例子:
http://www.vckbase.com/document/viewdoc.asp?id=451
http://www.vckbase.com/document/viewdoc.asp?id=451
#2
请用GDI+,里面旋转已经封装了,用matiax实现
#3
你传进来的是HBITMAP,那为什么又要转换成CDC呢?这不是绕了个弯吗?
#4
我是在CE下实现,CE下好象不支持这些吧?他的哪个EVC++,功能没有VC++强大。
#5
请问 jszj: 那我怎么直接用HBITMAP进行转换呢?
#6
help 呀...........
#7
/**
* 快速旋转指定的Dib对象
* @param pDib 待旋转的Dib对象
* @param nAngle 旋转角度(角度制)
*/
void DIB_RotateFast(CDib *pDib, int nAngle) {
int i, j;
CDib *pTmp;
nAngle %= 360;
BYTE **scanLines = new BYTE*[pDib->m_nHeight];
BYTE *pScanLine = pDib->m_pBits;
for (i = 0; i < pDib->m_nHeight; i++) {
*(scanLines+i) = pScanLine;
pScanLine += pDib->m_nPitch;
}
switch (nAngle) {
case 0:
delete scanLines;
return;
case 90:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate90Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
case 180:
DIB_Flip(pDib, FLIP_HORIZONTAL | FLIP_VERTICAL);
return;
case 270:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate270Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
default:
break;
}
double dAngle = nAngle/180.0 * PI;
int nSin = (int)(sin(dAngle)*65536.0+0.5);
int nCos = (int)(cos(dAngle)*65536.0+0.5);
POINT vertex[] = {
{0, 0},
{(pDib->m_nWidth*nCos) >> 16, (pDib->m_nWidth*nSin) >> 16},
{(pDib->m_nWidth*nCos + pDib->m_nHeight*nSin) >> 16, (pDib->m_nWidth*nSin - pDib->m_nHeight*nCos) >> 16},
{(pDib->m_nHeight*nSin) >> 16, (-pDib->m_nHeight*nCos) >> 16}
};
POINT newVertex[4];
if (nAngle > 0 && nAngle < 90) {
newVertex[0] = vertex[0];
newVertex[1] = vertex[1];
newVertex[2] = vertex[2];
newVertex[3] = vertex[3];
} else if (nAngle > 90 && nAngle < 180) {
newVertex[0] = vertex[1];
newVertex[1] = vertex[2];
newVertex[2] = vertex[3];
newVertex[3] = vertex[0];
} else if (nAngle > 180 && nAngle < 270) {
newVertex[0] = vertex[2];
newVertex[1] = vertex[3];
newVertex[2] = vertex[0];
newVertex[3] = vertex[1];
} else {
newVertex[0] = vertex[3];
newVertex[1] = vertex[0];
newVertex[2] = vertex[1];
newVertex[3] = vertex[2];
}
SIZE newSize;
int edgeSlope[4];
int edgeConst[4];
int deltaX = nCos*newVertex[0].x+nSin*newVertex[1].y;
int deltaY = nCos*newVertex[1].y-nSin*newVertex[0].x;
dib_GetEdgeFormulas(newVertex, &newSize, edgeSlope, edgeConst);
pTmp = new CDib(newSize.cx, newSize.cy, g_colorKey);
int ox, oy;
int boundLeft, boundRight;
BYTE *pVInc = pTmp->m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
int actualY = -pTmp->m_nHeight;
for (i = 0; i > actualY; i--) {
if (i > newVertex[0].y) {
boundLeft = (edgeSlope[0]*i + edgeConst[0]) >> 16;
} else {
boundLeft = (edgeSlope[1]*i + edgeConst[1]) >> 16;
}
if (i > newVertex[2].y) {
boundRight = (edgeSlope[2]*i + edgeConst[2]) >> 16;
} else {
boundRight = (edgeSlope[3]*i + edgeConst[3]) >> 16;
}
pHInc = pVInc+boundLeft+boundLeft+boundLeft; // 把水平增量指针初始化为当前扫描行的首址
for (j = boundLeft; j < boundRight; j++) {
ox = (nCos*j+nSin*i+deltaX) >> 16;
oy = -((nCos*i-nSin*j+deltaY) >> 16);
ox = ox < 0 ? 0 : ox;
ox = ox >= pDib->m_nWidth ? pDib->m_nWidth-1 : ox;
oy = oy < 0 ? 0 : oy;
oy = oy >= pDib->m_nHeight ? pDib->m_nHeight-1 : oy;
dib_SetColor(pHInc, dib_GetColor(*(scanLines+oy)+ox+ox+ox));
pHInc += PIXELSIZE; // 一个像素数据过滤完成,指针指向下一个
}
pVInc += pTmp->m_nPitch; // 一个扫描行处理完,指针指向下一行
}
*pDib = *pTmp;
delete scanLines;
delete pTmp;
}
* 快速旋转指定的Dib对象
* @param pDib 待旋转的Dib对象
* @param nAngle 旋转角度(角度制)
*/
void DIB_RotateFast(CDib *pDib, int nAngle) {
int i, j;
CDib *pTmp;
nAngle %= 360;
BYTE **scanLines = new BYTE*[pDib->m_nHeight];
BYTE *pScanLine = pDib->m_pBits;
for (i = 0; i < pDib->m_nHeight; i++) {
*(scanLines+i) = pScanLine;
pScanLine += pDib->m_nPitch;
}
switch (nAngle) {
case 0:
delete scanLines;
return;
case 90:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate90Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
case 180:
DIB_Flip(pDib, FLIP_HORIZONTAL | FLIP_VERTICAL);
return;
case 270:
pTmp = new CDib(pDib->m_nHeight, pDib->m_nWidth, COLOR_BLACK);
DIB_Filter(pTmp, dib_Rotate270Filter, scanLines);
*pDib = *pTmp;
delete scanLines;
delete pTmp;
return;
default:
break;
}
double dAngle = nAngle/180.0 * PI;
int nSin = (int)(sin(dAngle)*65536.0+0.5);
int nCos = (int)(cos(dAngle)*65536.0+0.5);
POINT vertex[] = {
{0, 0},
{(pDib->m_nWidth*nCos) >> 16, (pDib->m_nWidth*nSin) >> 16},
{(pDib->m_nWidth*nCos + pDib->m_nHeight*nSin) >> 16, (pDib->m_nWidth*nSin - pDib->m_nHeight*nCos) >> 16},
{(pDib->m_nHeight*nSin) >> 16, (-pDib->m_nHeight*nCos) >> 16}
};
POINT newVertex[4];
if (nAngle > 0 && nAngle < 90) {
newVertex[0] = vertex[0];
newVertex[1] = vertex[1];
newVertex[2] = vertex[2];
newVertex[3] = vertex[3];
} else if (nAngle > 90 && nAngle < 180) {
newVertex[0] = vertex[1];
newVertex[1] = vertex[2];
newVertex[2] = vertex[3];
newVertex[3] = vertex[0];
} else if (nAngle > 180 && nAngle < 270) {
newVertex[0] = vertex[2];
newVertex[1] = vertex[3];
newVertex[2] = vertex[0];
newVertex[3] = vertex[1];
} else {
newVertex[0] = vertex[3];
newVertex[1] = vertex[0];
newVertex[2] = vertex[1];
newVertex[3] = vertex[2];
}
SIZE newSize;
int edgeSlope[4];
int edgeConst[4];
int deltaX = nCos*newVertex[0].x+nSin*newVertex[1].y;
int deltaY = nCos*newVertex[1].y-nSin*newVertex[0].x;
dib_GetEdgeFormulas(newVertex, &newSize, edgeSlope, edgeConst);
pTmp = new CDib(newSize.cx, newSize.cy, g_colorKey);
int ox, oy;
int boundLeft, boundRight;
BYTE *pVInc = pTmp->m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
int actualY = -pTmp->m_nHeight;
for (i = 0; i > actualY; i--) {
if (i > newVertex[0].y) {
boundLeft = (edgeSlope[0]*i + edgeConst[0]) >> 16;
} else {
boundLeft = (edgeSlope[1]*i + edgeConst[1]) >> 16;
}
if (i > newVertex[2].y) {
boundRight = (edgeSlope[2]*i + edgeConst[2]) >> 16;
} else {
boundRight = (edgeSlope[3]*i + edgeConst[3]) >> 16;
}
pHInc = pVInc+boundLeft+boundLeft+boundLeft; // 把水平增量指针初始化为当前扫描行的首址
for (j = boundLeft; j < boundRight; j++) {
ox = (nCos*j+nSin*i+deltaX) >> 16;
oy = -((nCos*i-nSin*j+deltaY) >> 16);
ox = ox < 0 ? 0 : ox;
ox = ox >= pDib->m_nWidth ? pDib->m_nWidth-1 : ox;
oy = oy < 0 ? 0 : oy;
oy = oy >= pDib->m_nHeight ? pDib->m_nHeight-1 : oy;
dib_SetColor(pHInc, dib_GetColor(*(scanLines+oy)+ox+ox+ox));
pHInc += PIXELSIZE; // 一个像素数据过滤完成,指针指向下一个
}
pVInc += pTmp->m_nPitch; // 一个扫描行处理完,指针指向下一行
}
*pDib = *pTmp;
delete scanLines;
delete pTmp;
}
#8
void DIB_RotateFast(CDib *pDib, int nAngle)
这里的CDib是哪里来的呢,没有这个类呀。
这里的CDib是哪里来的呢,没有这个类呀。
#9
/**********************************************************
dibcore.h WannaPlayDIB实用图形库 类、接口和核心API声明
版权所有(C) 2001 WannaPlay
WannaPlay实用图形函数库完全*发放。
任何人都可以没有限制的使用、修改和再发布本代码。
同时作者也没有义务为代码可能对你的应用和系统造
成的任何损害承担责任。
发现任何Bug,缺陷,或有任何意见和建议,请联系作者。
谢谢。
Home Page: http://wannaplay.51.net
eMail: rocks_lee@263.net
OICQ: 17219193
***********************************************************/
#ifndef __WANNAPLAY_DIBCORE_H__
#define __WANNAPLAY_DIBCORE_H__
#include "dibstruct.h"
class CDib;
class IAbstractFilter;
class IImageWrapper;
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库自定义类型
//////////////////////////////////////////////////////////////////////
// 颜色数据。CDib每像素由3 bytes组成,在内存中的排列顺序是bbggrr,
// 这是与GDI的24位DIB完全相同的。
// 用这个类型可以一次得到全部三个分量,最高字节置零。
// 而Windows的COLORREF则是最低字节置零,所以必要时要做转换。
typedef DWORD DIB_COLOR;
// 滤波器回调函数类型。可以与DIB_Filter()函数配合使用,以实现多种滤波算法。
// DIB_Filter()函数对每个像素回调该函数。
typedef void (CALLBACK* DIB_FILTERPROC)(CDib *pDib, // 用这个参数配合下面的x 和 y,
int x, // 可以访问和本像素相关的其它像素。
int y, // 其实如果你愿意,是可以访问任何一个像素数据的。
BYTE *pixel, // 这是个快捷方式,如果你只对当前像素感兴趣。
void *filterParam); // 回调函数自定义参数,从DIB_Filter()简单传递而来。
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常量定义,包括常用颜色和每像素长度
//////////////////////////////////////////////////////////////////////
// 常用的几种颜色
#define COLOR_BLACK ((DIB_COLOR)0x00000000)
#define COLOR_WHITE ((DIB_COLOR)0x00ffffff)
#define COLOR_BLUE ((DIB_COLOR)0x000000ff)
#define COLOR_GREEN ((DIB_COLOR)0x0000ff00)
#define COLOR_RED ((DIB_COLOR)0x00ff0000)
// 每像素的字节数
#define PIXELSIZE 3
// DIB_LoadImage的options
#define LOAD_FROMFILE 0x01
#define LOAD_FROMRES 0x02
// DIB_Flip的options
#define FLIP_HORIZONTAL 0x01
#define FLIP_VERTICAL 0x02
// DIB_Blt和DIB_BltFast的options
#define BLT_COLORKEY 0x01
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用宏定义
//////////////////////////////////////////////////////////////////////
// 从扫描行的像素数得到字节数。DIB的扫描行是双字(DWORD)对齐的
#define DIB_WIDTH2PITCH(w) (((w)+(w)+(w)+3) & 0xfffffffc)
// 得到颜色的RED分量
#define DIB_RVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_RED)>>16))
// 得到颜色的GREEN分量
#define DIB_GVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_GREEN)>>8))
// 得到颜色的BLUE分量
#define DIB_BVALUE(color) ((BYTE)((DIB_COLOR)(color) & COLOR_BLUE))
// 把三个BYTE分量重新组合成一个DIB_COLOR
#define DIB_RGB(r, g, b) (0 | (((r)<<16)&COLOR_RED) | (((g)<<8)&COLOR_GREEN) | ((b)&COLOR_BLUE))
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用辅助函数
//////////////////////////////////////////////////////////////////////
// 用一个DIB_COLOR(4 Bytes)型参数快速给一个像素(3 Bytes)赋值
inline void dib_SetColor(BYTE *pPixel, DIB_COLOR color) {
*((DIB_COLOR*)pPixel) &= 0xff000000; // 把本像素清0,而下一个像素的首字节要保护起来
*((DIB_COLOR*)pPixel) |= color; // 这时像素的三个字节都为0,用or操作就可以了
}
// 把一个像素快速转换为DIB_COLOR类型
inline DIB_COLOR dib_GetColor(BYTE *pPixel) {
DIB_COLOR ret = *((DIB_COLOR*)pPixel); // 这样得到的值包含下一个像素的首字节
return ret & 0x00ffffff; // 把那个多余的字节屏蔽掉
}
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库的基本数据类型CDib的类定义和部分inline实现,
// 以及两个抽象的接口类,以便于灵活的扩展本库所支持的算法
// 和图形格式
//////////////////////////////////////////////////////////////////////
/**
* CDib类对设备无关位图(DIB)进行了简单的封装,比起GDI API中定义的DIB,
* 它更加简单而实用。
* CDib类以24位(3 bytes)表示一个像素,与GDI中的24位DIB格式兼容。即:
* 自底向上存储扫描行,每一扫描行长度DWORD对齐;
* 每像素3字节,存储顺序为bbggrr。
* WannaPlayDIB实用图形库所提供的所有算法都以CDib类作为操作对象和存储结构。
*/
class CDib {
public:
/**
* 缺省的构造函数
*/
CDib() : m_nWidth(0), m_nHeight(0), m_nPitch(0), m_pBits(NULL) {}
/**
* 根据给定的大小和颜色构造一个CDib对象
*/
CDib(int w, int h, DIB_COLOR colorInit);
/**
* 根据给定的大小和像素数据构造一个CDib对象
*/
CDib(int w, int h, BYTE *pBits) :
m_nWidth(w),
m_nHeight(h),
m_nPitch(DIB_WIDTH2PITCH(w)),
m_pBits(pBits) {}
/**
* 根据另一个CDib对象构造一个新的CDib对象
*/
CDib(CDib &refDib);
virtual ~CDib();
CDib operator =(CDib &refDib);
public:
DIB_COLOR GetPixel(int x, int y) {
return dib_GetColor(m_pBits+m_nPitch*y+x+x+x);
}
DIB_COLOR SetPixel(int x, int y, DIB_COLOR c) {
dib_SetColor((BYTE*)(m_pBits+m_nPitch*y+x+x+x), c);
}
public:
int m_nWidth;
int m_nHeight;
int m_nPitch;
BYTE *m_pBits;
};
/**
* 实现这个接口,与DIB_Filter()函数配合使用,
* 以支持更复杂的滤波算法(比如当像素间的互相关性较大时)
*/
class IAbstractFilter {
public:
virtual void Filter(CDib *pDib, int x, int y, BYTE *pixel) = 0;
};
/**
* 实现这个接口以支持更多的图形文件格式。
* 可以在子类中保存图形的更多信息,以便定制载入和保存操作
*/
class IImageWrapper {
public:
virtual CDib* LoadDib() = 0;
virtual void SaveDib(CDib *pDib) = 0;
};
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库API定义
//////////////////////////////////////////////////////////////////////
CDib* DIB_LoadImage(IImageWrapper *loader);
void DIB_SaveImage(CDib *pDib, IImageWrapper *writer);
void DIB_Filter(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam);
void DIB_Filter(CDib *pDib, IAbstractFilter *filter);
void DIB_FilterRect(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam, LPRECT pRect);
void DIB_SetColorKey(int rr, int gg, int bb);
void DIB_SetColorKey(DIB_COLOR colorKey);
DIB_COLOR DIB_GetColorKey();
void DIB_RotateFast(CDib *pDib, int nAngle);
void DIB_Rotate(CDib *pDib, double dAngle);
void DIB_StretchFast(CDib *pDib, int newWidth, int newHeight);
void DIB_Stretch(CDib *pDib, int newWidth, int newHeight);
void DIB_Flip(CDib *pDib, UINT uOption);
void DIB_BltFast(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
UINT uOptions);
void DIB_AlphaBlend(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
CDib *pDibAlpha,
int nXAlpha,
int nYAlpha);
void DIB_ClearColorRange(CDib *pDib,
DIB_COLOR colorLow,
DIB_COLOR colorHigh);
void DIB_Line(CDib *pDib, int x0, int y0, int x1, int y1);
#endif//__WANNAPLAY_DIBCORE_H__
dibcore.h WannaPlayDIB实用图形库 类、接口和核心API声明
版权所有(C) 2001 WannaPlay
WannaPlay实用图形函数库完全*发放。
任何人都可以没有限制的使用、修改和再发布本代码。
同时作者也没有义务为代码可能对你的应用和系统造
成的任何损害承担责任。
发现任何Bug,缺陷,或有任何意见和建议,请联系作者。
谢谢。
Home Page: http://wannaplay.51.net
eMail: rocks_lee@263.net
OICQ: 17219193
***********************************************************/
#ifndef __WANNAPLAY_DIBCORE_H__
#define __WANNAPLAY_DIBCORE_H__
#include "dibstruct.h"
class CDib;
class IAbstractFilter;
class IImageWrapper;
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库自定义类型
//////////////////////////////////////////////////////////////////////
// 颜色数据。CDib每像素由3 bytes组成,在内存中的排列顺序是bbggrr,
// 这是与GDI的24位DIB完全相同的。
// 用这个类型可以一次得到全部三个分量,最高字节置零。
// 而Windows的COLORREF则是最低字节置零,所以必要时要做转换。
typedef DWORD DIB_COLOR;
// 滤波器回调函数类型。可以与DIB_Filter()函数配合使用,以实现多种滤波算法。
// DIB_Filter()函数对每个像素回调该函数。
typedef void (CALLBACK* DIB_FILTERPROC)(CDib *pDib, // 用这个参数配合下面的x 和 y,
int x, // 可以访问和本像素相关的其它像素。
int y, // 其实如果你愿意,是可以访问任何一个像素数据的。
BYTE *pixel, // 这是个快捷方式,如果你只对当前像素感兴趣。
void *filterParam); // 回调函数自定义参数,从DIB_Filter()简单传递而来。
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常量定义,包括常用颜色和每像素长度
//////////////////////////////////////////////////////////////////////
// 常用的几种颜色
#define COLOR_BLACK ((DIB_COLOR)0x00000000)
#define COLOR_WHITE ((DIB_COLOR)0x00ffffff)
#define COLOR_BLUE ((DIB_COLOR)0x000000ff)
#define COLOR_GREEN ((DIB_COLOR)0x0000ff00)
#define COLOR_RED ((DIB_COLOR)0x00ff0000)
// 每像素的字节数
#define PIXELSIZE 3
// DIB_LoadImage的options
#define LOAD_FROMFILE 0x01
#define LOAD_FROMRES 0x02
// DIB_Flip的options
#define FLIP_HORIZONTAL 0x01
#define FLIP_VERTICAL 0x02
// DIB_Blt和DIB_BltFast的options
#define BLT_COLORKEY 0x01
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用宏定义
//////////////////////////////////////////////////////////////////////
// 从扫描行的像素数得到字节数。DIB的扫描行是双字(DWORD)对齐的
#define DIB_WIDTH2PITCH(w) (((w)+(w)+(w)+3) & 0xfffffffc)
// 得到颜色的RED分量
#define DIB_RVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_RED)>>16))
// 得到颜色的GREEN分量
#define DIB_GVALUE(color) ((BYTE)(((DIB_COLOR)(color) & COLOR_GREEN)>>8))
// 得到颜色的BLUE分量
#define DIB_BVALUE(color) ((BYTE)((DIB_COLOR)(color) & COLOR_BLUE))
// 把三个BYTE分量重新组合成一个DIB_COLOR
#define DIB_RGB(r, g, b) (0 | (((r)<<16)&COLOR_RED) | (((g)<<8)&COLOR_GREEN) | ((b)&COLOR_BLUE))
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库常用辅助函数
//////////////////////////////////////////////////////////////////////
// 用一个DIB_COLOR(4 Bytes)型参数快速给一个像素(3 Bytes)赋值
inline void dib_SetColor(BYTE *pPixel, DIB_COLOR color) {
*((DIB_COLOR*)pPixel) &= 0xff000000; // 把本像素清0,而下一个像素的首字节要保护起来
*((DIB_COLOR*)pPixel) |= color; // 这时像素的三个字节都为0,用or操作就可以了
}
// 把一个像素快速转换为DIB_COLOR类型
inline DIB_COLOR dib_GetColor(BYTE *pPixel) {
DIB_COLOR ret = *((DIB_COLOR*)pPixel); // 这样得到的值包含下一个像素的首字节
return ret & 0x00ffffff; // 把那个多余的字节屏蔽掉
}
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库的基本数据类型CDib的类定义和部分inline实现,
// 以及两个抽象的接口类,以便于灵活的扩展本库所支持的算法
// 和图形格式
//////////////////////////////////////////////////////////////////////
/**
* CDib类对设备无关位图(DIB)进行了简单的封装,比起GDI API中定义的DIB,
* 它更加简单而实用。
* CDib类以24位(3 bytes)表示一个像素,与GDI中的24位DIB格式兼容。即:
* 自底向上存储扫描行,每一扫描行长度DWORD对齐;
* 每像素3字节,存储顺序为bbggrr。
* WannaPlayDIB实用图形库所提供的所有算法都以CDib类作为操作对象和存储结构。
*/
class CDib {
public:
/**
* 缺省的构造函数
*/
CDib() : m_nWidth(0), m_nHeight(0), m_nPitch(0), m_pBits(NULL) {}
/**
* 根据给定的大小和颜色构造一个CDib对象
*/
CDib(int w, int h, DIB_COLOR colorInit);
/**
* 根据给定的大小和像素数据构造一个CDib对象
*/
CDib(int w, int h, BYTE *pBits) :
m_nWidth(w),
m_nHeight(h),
m_nPitch(DIB_WIDTH2PITCH(w)),
m_pBits(pBits) {}
/**
* 根据另一个CDib对象构造一个新的CDib对象
*/
CDib(CDib &refDib);
virtual ~CDib();
CDib operator =(CDib &refDib);
public:
DIB_COLOR GetPixel(int x, int y) {
return dib_GetColor(m_pBits+m_nPitch*y+x+x+x);
}
DIB_COLOR SetPixel(int x, int y, DIB_COLOR c) {
dib_SetColor((BYTE*)(m_pBits+m_nPitch*y+x+x+x), c);
}
public:
int m_nWidth;
int m_nHeight;
int m_nPitch;
BYTE *m_pBits;
};
/**
* 实现这个接口,与DIB_Filter()函数配合使用,
* 以支持更复杂的滤波算法(比如当像素间的互相关性较大时)
*/
class IAbstractFilter {
public:
virtual void Filter(CDib *pDib, int x, int y, BYTE *pixel) = 0;
};
/**
* 实现这个接口以支持更多的图形文件格式。
* 可以在子类中保存图形的更多信息,以便定制载入和保存操作
*/
class IImageWrapper {
public:
virtual CDib* LoadDib() = 0;
virtual void SaveDib(CDib *pDib) = 0;
};
//////////////////////////////////////////////////////////////////////
// WannaPlayDIB实用图形库API定义
//////////////////////////////////////////////////////////////////////
CDib* DIB_LoadImage(IImageWrapper *loader);
void DIB_SaveImage(CDib *pDib, IImageWrapper *writer);
void DIB_Filter(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam);
void DIB_Filter(CDib *pDib, IAbstractFilter *filter);
void DIB_FilterRect(CDib *pDib, DIB_FILTERPROC filterProc, void *filterParam, LPRECT pRect);
void DIB_SetColorKey(int rr, int gg, int bb);
void DIB_SetColorKey(DIB_COLOR colorKey);
DIB_COLOR DIB_GetColorKey();
void DIB_RotateFast(CDib *pDib, int nAngle);
void DIB_Rotate(CDib *pDib, double dAngle);
void DIB_StretchFast(CDib *pDib, int newWidth, int newHeight);
void DIB_Stretch(CDib *pDib, int newWidth, int newHeight);
void DIB_Flip(CDib *pDib, UINT uOption);
void DIB_BltFast(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
UINT uOptions);
void DIB_AlphaBlend(CDib *pDibDest,
int nXDest,
int nYDest,
CDib *pDibSrc,
LPRECT pRectSrc,
CDib *pDibAlpha,
int nXAlpha,
int nYAlpha);
void DIB_ClearColorRange(CDib *pDib,
DIB_COLOR colorLow,
DIB_COLOR colorHigh);
void DIB_Line(CDib *pDib, int x0, int y0, int x1, int y1);
#endif//__WANNAPLAY_DIBCORE_H__
#10
//////////////////////////////////////////////////////////////////////
// CDib类的成员函数实现
//////////////////////////////////////////////////////////////////////
/**
* 创建指定大小的单色图像。
* @param w 宽度
* @param h 高度
* @param colorInit 初始化颜色
* 注意,如果你只是想创建一块用来绘图的数据缓冲,
* 那么请用黑色作为参数,效率将更高。
*/
CDib::CDib(int w, int h, DIB_COLOR colorInit) {
m_nWidth = w;
m_nHeight = h;
m_nPitch = DIB_WIDTH2PITCH(w);
int size = h*m_nPitch;
m_pBits = new BYTE[size]; // 分配图像数据内存
memset(m_pBits, 0, size); // 把这块得到的内存清0
if (colorInit == COLOR_BLACK) {
return; // 因为黑色实际就是全0,所以这里就可以快速返回了
}
// 下面将用一个二重循环访问每一个像素,并用指定的颜色赋值
int i = 0, j = 0; // 循环计数器
// 垂直方向的增量指针。每操作完一行数据,它就被指向下一个扫描行
BYTE *pVInc = m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
for (i = 0; i < h; i++) {
pHInc = pVInc; // 把水平增量指针初始化为当前扫描行的首址
for (j = 0; j < w; j++) {
dib_SetColor(pHInc, colorInit);
pHInc += PIXELSIZE; // 一个像素数据赋值完成,指针指向下一个
}
pVInc += m_nPitch; // 一个扫描行处理完,指针指向下一行
}
}
/**
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib::CDib(CDib &refDib) {
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
}
/**
* 析构函数。
* 把为这个CDib对象的图像数据分配的内存释放掉。
*/
CDib::~CDib() {
if (m_pBits != NULL) {
delete[] m_pBits;
}
}
/**
* 重载等号运算符。
* 这样你可以像对一个一般变量一样直接对一个CDib赋值。
* 和上面的第二个构造函数一样,
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib CDib::operator =(CDib &refDib) {
if (this == &refDib) {
return *this;
}
if (m_pBits != NULL) {
delete[] m_pBits;
}
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
return *this;
}
// CDib类的成员函数实现
//////////////////////////////////////////////////////////////////////
/**
* 创建指定大小的单色图像。
* @param w 宽度
* @param h 高度
* @param colorInit 初始化颜色
* 注意,如果你只是想创建一块用来绘图的数据缓冲,
* 那么请用黑色作为参数,效率将更高。
*/
CDib::CDib(int w, int h, DIB_COLOR colorInit) {
m_nWidth = w;
m_nHeight = h;
m_nPitch = DIB_WIDTH2PITCH(w);
int size = h*m_nPitch;
m_pBits = new BYTE[size]; // 分配图像数据内存
memset(m_pBits, 0, size); // 把这块得到的内存清0
if (colorInit == COLOR_BLACK) {
return; // 因为黑色实际就是全0,所以这里就可以快速返回了
}
// 下面将用一个二重循环访问每一个像素,并用指定的颜色赋值
int i = 0, j = 0; // 循环计数器
// 垂直方向的增量指针。每操作完一行数据,它就被指向下一个扫描行
BYTE *pVInc = m_pBits; // 初始化为第一个扫描行的首地址(也就是整个图像数据的首址)
// 水平方向的增量指针。每操作完一个像素,它就被指向下一个像素
BYTE *pHInc = NULL; // 它将在每次对一个扫描行开始处理之前被赋值
for (i = 0; i < h; i++) {
pHInc = pVInc; // 把水平增量指针初始化为当前扫描行的首址
for (j = 0; j < w; j++) {
dib_SetColor(pHInc, colorInit);
pHInc += PIXELSIZE; // 一个像素数据赋值完成,指针指向下一个
}
pVInc += m_nPitch; // 一个扫描行处理完,指针指向下一行
}
}
/**
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib::CDib(CDib &refDib) {
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
}
/**
* 析构函数。
* 把为这个CDib对象的图像数据分配的内存释放掉。
*/
CDib::~CDib() {
if (m_pBits != NULL) {
delete[] m_pBits;
}
}
/**
* 重载等号运算符。
* 这样你可以像对一个一般变量一样直接对一个CDib赋值。
* 和上面的第二个构造函数一样,
* 把给定的CDib对象“克隆”一份,包括图像数据。
* @param refDib 被clone对象的引用
*/
CDib CDib::operator =(CDib &refDib) {
if (this == &refDib) {
return *this;
}
if (m_pBits != NULL) {
delete[] m_pBits;
}
m_nWidth = refDib.m_nWidth;
m_nHeight = refDib.m_nHeight;
m_nPitch = DIB_WIDTH2PITCH(m_nWidth);
int size = m_nHeight * m_nPitch;
m_pBits = new BYTE[size];
memcpy(m_pBits, refDib.m_pBits, size);
return *this;
}
#11
用GDI+解决:
REAL PosX,PosY; //图像的初始位置
REAL centerX,centerY; //旋转中心
REAL Rangle; //旋转角度
PointF CenterPoint(centerX,centerY);
Graphics graphics(hdc);
Image newImage(L("filename")); //要旋转的图像
Matrix RotateMatrix; //旋转矩阵
graphics.DrawImage (newImage,PosX,PosY);
rotateMatrix.RotateAt(Rangle,CenterPoint,MatrixOrderPrepend)
graphics.SetTransform(RotateMatrix);
REAL PosX,PosY; //图像的初始位置
REAL centerX,centerY; //旋转中心
REAL Rangle; //旋转角度
PointF CenterPoint(centerX,centerY);
Graphics graphics(hdc);
Image newImage(L("filename")); //要旋转的图像
Matrix RotateMatrix; //旋转矩阵
graphics.DrawImage (newImage,PosX,PosY);
rotateMatrix.RotateAt(Rangle,CenterPoint,MatrixOrderPrepend)
graphics.SetTransform(RotateMatrix);