怎样将1位的图片旋转90度后以另一个文件名保存 格式:1位的BMP文件.将它旋转90度后以另一个文件名保存, 要写成动态链接库的形式.(急) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 方法选其一[1]找bmp文件格式资料。搞懂后,旋转图片就难了。[2]试试GDI+,找找没有没对应的函数[3]试试开源的CxImage 利用Windows的坐标转换功能就可以了(需要在Windows2000或以上系统才可以运行)。这里示范如何将位图旋转90度。// hDC 屏幕或内存DC。// hBitmap 要转换的位图句柄。HDC hDCMem = CreateCompatibleDC(hDC);SetGraphicsMode(hDCMem, GM_ADVANCED)XFORM xf;xf.em11 = (float)0.0;xf.em12 = (float)1.0;xf.em21 = (float)-1.0;xf.em22 = (float)0.0;xf.eDx = 0;xf.eDy = 0;SetWorldTransform(hDCMem, &xf);BITMAP bm;HGDIOBJ hBmpPrev = SelectObject(hDCMem, hBitmap);GetObject(hBitmap, sizeof(bm), &bm);BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCCOPY);SelectObject(hDCMem, hBmpPrev);DeleteDC(hDCMem);// 将hDC中的HBITMAP分离出来并且保存成DIB就可以了。 /** * 快速旋转指定的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; } GDI+ DrawImage 有一个坐标系变换的 1位色的图像 只能旋转90度的整数倍,所以上面贴的那些什么旋转算法都是无用的。如果自己写算法,90度的旋转就是一个简单的行变列的过程,但是1位色不那么简单,原因就是这个字节对齐的东西,你需要特别处理原始行的最后几个字节。简单那的方法就是利用GDI+的GdipImageRotateFlip函数以及几个保存图像的函数。 看下这个帖子http://topic.csdn.net/u/20100518/10/c0083771-f5db-45ab-8249-10c1053905c2.html 谢谢各位,有了一点头绪,但有一个地方有些疑问:1位的bmp,bfOffBits 怎么计算,可以直接 bfOffBits = BITMAPINFOHEADER.bisizeimage 不是的。biSizelmage是该BMP 内图像数据占用的空间大小。若图像文件描述BI—RGB位图,则该字段的值必须设置为0。bfOffBits 它以字节为单位,指示图像数据在文件内的起始地址,即图像数据针对文件头的偏移量。具体,你看下这个http://blog.csdn.net/orangeman1982112/archive/2009/02/13/3887427.aspx C++读取文件 关于vector容器与stack适配器 等待高手解答一下关于网络编程问题? 把一个长整型long转换16进制形式,再取最后两位保存到String中应该怎么做? 怎么显示2进制数据 简单问题,但思路很难(关于 progid 的) 请问我的这段MoveWindow的代码有什么错误?(现在没分了,日后一定补上) interface 这个是什么意思? 谁有源代码发个 请问如何做'char *' to 'const unsigned short *'的转换 关于用vs2008编译的问题 如何实现一个对话框上treectrl控件上的项向listctrl上拖动?急!!!多谢大家!
[1]找bmp文件格式资料。搞懂后,旋转图片就难了。
[2]试试GDI+,找找没有没对应的函数
[3]试试开源的CxImage
// hDC 屏幕或内存DC。
// hBitmap 要转换的位图句柄。HDC hDCMem = CreateCompatibleDC(hDC);
SetGraphicsMode(hDCMem, GM_ADVANCED)
XFORM xf;
xf.em11 = (float)0.0;
xf.em12 = (float)1.0;
xf.em21 = (float)-1.0;
xf.em22 = (float)0.0;
xf.eDx = 0;
xf.eDy = 0;
SetWorldTransform(hDCMem, &xf);BITMAP bm;
HGDIOBJ hBmpPrev = SelectObject(hDCMem, hBitmap);
GetObject(hBitmap, sizeof(bm), &bm);BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCCOPY);SelectObject(hDCMem, hBmpPrev);
DeleteDC(hDCMem);// 将hDC中的HBITMAP分离出来并且保存成DIB就可以了。
* 快速旋转指定的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;
}
如果自己写算法,90度的旋转就是一个简单的行变列的过程,但是1位色不那么简单,原因就是这个字节对齐的东西,你需要特别处理原始行的最后几个字节。
简单那的方法就是利用GDI+的GdipImageRotateFlip函数以及几个保存图像的函数。
http://topic.csdn.net/u/20100518/10/c0083771-f5db-45ab-8249-10c1053905c2.html
可以直接 bfOffBits = BITMAPINFOHEADER.bisizeimage
biSizelmage是该BMP 内图像数据占用的空间大小。若图像文件描述BI—RGB位图,则该字段的值必须设置为0。bfOffBits 它以字节为单位,指示图像数据在文件内的起始地址,即图像数据针对文件头的偏移量。具体,你看下这个
http://blog.csdn.net/orangeman1982112/archive/2009/02/13/3887427.aspx