图像旋转算法

图像旋转算法

cndg

图像旋转是将新旧坐标值转换以及像素间线性插值处理,由于坐标值转换时使用到乘法运算,本文使用加法运算替换乘法运算解决速度问题。

代码如下:

//函数功能:图象旋转

//参数说明:iSrc,表示原始图像;iDst,表示目标图像;Angle,表示旋转角度;nColorType,表示边界外区域填充颜色

//返回值:无
void  ImageRotate2(CxImage* iSrc,CxImage* iDst,double Angle,int nColorType)
{
 LONG nWidth,nHeight,nEffectWidth,nBpp,nXDpi,nYDpi,nNewEffectWidth,ImageHeight,ImageWidth;
 nWidth = iSrc->GetWidth();
 nHeight = iSrc->GetHeight();
 nEffectWidth = iSrc->GetEffWidth();
 nBpp = iSrc->GetBpp();
 nXDpi = iSrc->GetXDPI();
 nYDpi = iSrc->GetYDPI();

    BYTE *S = NULL,Value;
 S = iSrc->GetBits();
 double   vcos,vsin;
 double   cx,cy,vx,vy,cntx,cnty;
 LONG      off,off1,off2,nOffset;
 LONG      i,j,m,n;
 double   an,svx,svy;
 double   dx0,dy0,dx1,dy1,zz;

 an   = Angle*PI/180.0;
 vcos = cos(an);    vsin = sin(an);

 // 源图四个角的坐标(以图像中心为坐标系原点)
 float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
 // 旋转后四个角的坐标(以图像中心为坐标系原点)
 float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
 // 计算原图的四个角的坐标(以图像中心为坐标系原点)
 fSrcX1 = (float) (- (nWidth  - 1) / 2);
 fSrcY1 = (float) (  (nHeight - 1) / 2);
 fSrcX2 = (float) (  (nWidth  - 1) / 2);
 fSrcY2 = (float) (  (nHeight - 1) / 2);
 fSrcX3 = (float) (- (nWidth  - 1) / 2);
 fSrcY3 = (float) (- (nHeight - 1) / 2);
 fSrcX4 = (float) (  (nWidth  - 1) / 2);
 fSrcY4 = (float) (- (nHeight - 1) / 2);
 
 // 计算新图四个角的坐标(以图像中心为坐标系原点)
 fDstX1 =  vcos * fSrcX1 + vsin * fSrcY1;
 fDstY1 = -vsin * fSrcX1 + vcos * fSrcY1;
 fDstX2 =  vcos * fSrcX2 + vsin * fSrcY2;
 fDstY2 = -vsin * fSrcX2 + vcos * fSrcY2;
 fDstX3 =  vcos * fSrcX3 + vsin * fSrcY3;
 fDstY3 = -vsin * fSrcX3 + vcos * fSrcY3;
 fDstX4 =  vcos * fSrcX4 + vsin * fSrcY4;
 fDstY4 = -vsin * fSrcX4 + vcos * fSrcY4;
 // 计算旋转后的图像实际宽度
 ImageWidth  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
 // 计算旋转后的图像高度
 ImageHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);

 double f1,f2;
 f1 = (double) (-0.5 * (ImageWidth - 1) * vcos - 0.5 * (ImageHeight - 1) * vsin + 0.5 * (nWidth  - 1));
 f2 = (double) ( 0.5 * (ImageWidth - 1) * vsin - 0.5 * (ImageHeight - 1) * vcos + 0.5 * (nHeight - 1));

    ////////////////////////////////////////////////////////////////////////////////
 //分配空间
 nNewEffectWidth = (ImageWidth * nBpp + 31)/32 * 4;
 BYTE *D = new BYTE[nNewEffectWidth*ImageHeight];
 if(nColorType==1)//黑色
 {
  memset(D,0,sizeof(BYTE)*(nNewEffectWidth*ImageHeight));
 }
 else
 {
  memset(D,255,sizeof(BYTE)*(nNewEffectWidth*ImageHeight));
 }
 /////////////////////////////////////////////////////////////////////////////////
 cntx = f1+0.5;
 cnty = f2+0.5;
 cx  = 0; cy  = 0;
 svx = cx*vcos+cy*vsin+cntx;
 svy = -cx*vsin+cy*vcos+cnty;
 off = 0,off1 = 0;
 LONG i0,j0;
 for(i=0;i<ImageHeight;i++)   
 {
  vx = svx;
  vy = svy;
  off = i * nNewEffectWidth + 0;
  for(j=0;j<ImageWidth;j++)  
  {
   // 计算该象素在S中的坐标
  // vy = -j * vsin + i * vcos + f2 + 0.5;
  // vx =  j * vcos +  i * vsin + f1 + 0.5;
   m    = (LONG)vx;
   n = (LONG)vy;
            if((m<1)||(m>nWidth-2)||(n<1)||(n>nHeight-2))
            {
                zz = 0;
    if(nBpp==24)
    {
     if(nColorType==1)//黑色
     {
      zz = 0;
     }
     else
     {
      zz = 255;
     }
     D[off]=(int)zz;
     D[off+1]=(int)zz;
     D[off+2]=(int)zz;
    }
    else
    {
     if(nColorType==1)//黑色
     {
      zz = 0;
     }
     else
     {
      zz = 255;
     }
     D[off]=(int)zz;
    }
    
   }
            else 
            {
    if(nBpp==24)
    {
     dx0  = vx-m; dy0 = vy-n;
     dx1  = 1-dx0;dy1 = 1-dy0;    
     off1 = n*nEffectWidth+3*m;
     zz = 0;
     zz = S[off1]*dx1*dy1;
     off2 = off1+3;      
     zz += S[off2]*dx0*dy1;
     off2 = off1+nEffectWidth; 
     zz += S[off2]*dx1*dy0;
     off2 = off1+nEffectWidth+3;
     zz += S[off2]*dx0*dy0;
     if(zz>255)     
      zz= 255;
     if(zz<0)   
      zz = fabs(zz);
     D[off]=(int)zz; 
   
     off1 = n*nEffectWidth+3*m+1;
     zz = 0;
     zz = S[off1]*dx1*dy1;
     off2 = off1+3;      
     zz += S[off2]*dx0*dy1;
     off2 = off1+nEffectWidth; 
     zz += S[off2]*dx1*dy0;
     off2 = off1+nEffectWidth+3;
     zz += S[off2]*dx0*dy0;
     if(zz>255)     
      zz= 255;
     if(zz<0)   
      zz = fabs(zz);
        D[off+1]=(int)zz; 
   
     off1 = n*nEffectWidth+3*m+2;
     zz = 0;
     zz = S[off1]*dx1*dy1;
     off2 = off1+3;      
     zz += S[off2]*dx0*dy1;
     off2 = off1+nEffectWidth; 
     zz += S[off2]*dx1*dy0;
     off2 = off1+nEffectWidth+3;
     zz += S[off2]*dx0*dy0;
     if(zz>255)     
      zz= 255;
     if(zz<0)   
      zz = fabs(zz);
        D[off+2]=(int)zz; 
    }
    else
    {
     dx0  = vx-m; dy0 = vy-n;
     dx1  = 1-dx0;dy1 = 1-dy0;    
     off1 = n*nEffectWidth+m;
     zz = 0;
     zz = S[off1]*dx1*dy1;
     off2 = off1+1;      
     zz += S[off2]*dx0*dy1;
     off2 = off1+nEffectWidth; 
     zz += S[off2]*dx1*dy0;
     off2 = off1+nEffectWidth+1;
     zz += S[off2]*dx0*dy0;
     if(zz>255)     
      zz= 255;
     if(zz<0)   
      zz = fabs(zz);
     D[off]=(int)zz; 
    }
            }
   if(nBpp==24)
   {
     off +=3;
   }
   else
   {
       off++;  
   }
   vx = vx + vcos;
   vy = vy - vsin; 
  }
  svx=svx+vsin;
  svy=svy+vcos;
  }

 CxImage tmp;
 tmp.Copy(*iSrc);
 tmp.Create(ImageWidth,ImageHeight,nBpp,iSrc->GetType());
 tmp.SetPalette(iSrc->GetPalette());
// tmp.SetXDPI(nXDpi);
// tmp.SetYDPI(nYDpi);
 RGBQUAD color;
 for(i=0;i<ImageHeight;i++)
 {
  for(j=0;j<ImageWidth;j++)
  {
   nOffset = i * nNewEffectWidth + (nBpp/8) * j;
   if(nBpp==24)
   {
    //color = RGB(D[nOffset],D[nOffset+1],D[nOffset+2]);
    color.rgbRed = D[nOffset+2];
    color.rgbGreen = D[nOffset+1];
    color.rgbBlue = D[nOffset];
    color.rgbReserved = 0;
     tmp.SetPixelColor(j,i,color);
   }
   else
   {
    tmp.SetPixelIndex(j,i,D[nOffset]);
  } }
 }

 if(iDst)
  iDst->Copy(tmp);
 else
  iSrc->Copy(tmp);
 if(D)
 {
  delete []D;
  D = NULL;
 }
}

你可能感兴趣的:(算法,null,delete,float,byte)