任意角度图像旋转,超高速!!!!

rockswang 2001-03-23 11:31:00
请体验WannaPlayDIB实用图形库带给你的高性能!!
你可以看到,代码并不复杂,但速度飞快,画面效果绝对可以达到图像处理软件的水平!!

3000*2250*24位图(文件体积达20M)任意角度旋转只要3.8秒!!
640*480*24只要0.22s!!!!
(测试机器PIII733+256M)

关于“实战图形编程”讲座和WannaPlayDIB图形库的更详细内容,
以及获得完整的源代码,请访问:
我的主页: http://wannaplay.51.net
我的email:rocks_lee@263.net

void CALLBACK dib_Rotate90Filter(CDib *pDib, int x, int y, BYTE *pixel, void *scanLines) {
BYTE *curLine = *((BYTE**)scanLines+x);
int mappedX = pDib->m_nHeight-1-y;
dib_SetColor(pixel, dib_GetColor(curLine+mappedX+mappedX+mappedX));
}

void CALLBACK dib_Rotate270Filter(CDib *pDib, int x, int y, BYTE *pixel, void *scanLines) {
BYTE *curLine = *((BYTE**)scanLines+pDib->m_nWidth-1-x);
dib_SetColor(pixel, dib_GetColor(curLine+y+y+y));
}

void dib_GetEdgeFormulas(POINT *vertex, LPSIZE pNewSize, int *edgeSlope, int *edgeConst) {
int xMin = vertex[0].x;
int yMax = vertex[1].y;
pNewSize->cx = vertex[2].x - xMin;
pNewSize->cy = yMax - vertex[3].y;
int i;
for (i = 0; i < 4; i++) {
vertex[i].x -= xMin;
vertex[i].y -= yMax;
}
int slopeLeft = (int)((vertex[1].x - vertex[0].x)/(float)(vertex[1].y - vertex[0].y) * 65536.0 + 0.5);
int slopeRight = (int)((vertex[2].x - vertex[1].x)/(float)(vertex[2].y - vertex[1].y) * 65536.0 + 0.5);
int slopes[] = {slopeLeft, slopeRight, slopeRight, slopeLeft};
memcpy(edgeSlope, slopes, sizeof(int)<<2);
int consts[] = {
(vertex[0].x << 16) - slopes[0] * vertex[0].y,
(vertex[0].x << 16) - slopes[1] * vertex[0].y,
(vertex[2].x << 16) - slopes[2] * vertex[2].y,
(vertex[2].x << 16) - slopes[3] * vertex[2].y
};
memcpy(edgeConst, consts, sizeof(int)<<2);
}

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, COLOR_BLACK);
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;
}
...全文
269 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
landdywu 2001-05-19
  • 打赏
  • 举报
回复
不错,真是厉害!
Luck04 2001-03-23
  • 打赏
  • 举报
回复
厉害
Jedi 2001-03-23
  • 打赏
  • 举报
回复
爽!!!

我要!!!

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧