织梦CMS - 轻松建站从此开始!

罗索

Windows Mobile上实现图片任意角度旋转

落鹤生 发布于 2010-07-29 11:07 点击:次 
通过介绍和实现旋转PNG图片,来说明实现图片旋转的方法。过程大概如下,先用Imaging读取并解码png图片,使之转成ARGB格式的位图。然后利用顶点旋转的公式,对位图矩阵进行旋转,旋转完成后,利用Imaging库,转换成IImage接口。最后利用IImage接口来画图。
TAG:

作者:金海建

目的:在Windows Mobile上,微软的API和库不支持图片的任意角度旋转,只支持90,180,270度旋转。既然它不支持我们只能自力更生了。

简介:通过介绍和实现旋转PNG图片,来说明实现图片旋转的方法。过程大概如下,先用Imaging读取并解码png图片,使之转成ARGB格式的位图。然后利用顶点旋转的公式,对位图矩阵进行旋转,旋转完成后,利用Imaging库,转换成IImage接口。最后利用IImage接口来画图。

 

    先来看下平面直角坐标变换的旋转坐标变换,其定义是

定义:若二坐标系{O;i,j}和{O′;i′,j′}满足O≡O′,另∠(i,j′)=θ

        则坐标系{O′;i′,j′}可看成是由坐标系{O;i,j}绕O旋转θ角得到的,称由{O;i,j}到{O′;i′,j′}的变换为旋转坐标变换。

旋转公式为:

X' =  X cosθ -  Y sinθ

Y' =  X sinθ  + Y cosθ

由于我们是用数组的下表来表示坐标的,所以最小的坐标是为(0,0)。我们需要先做坐标旋转,然后平移坐标。如下图所示:

平移的动作,是把所以的负坐标变成正坐标。用MinX和MinY来表示最小的X坐标和Y坐标。

X' =  X cosθ -  Y sinθ - MinX;

Y' =  X sinθ  + Y cosθ - MinY;

根据上面的公式我们推出

x = (x'+MinX)cosθ+ (y'+MinY)sinθ

y = (y'+MinY)conθ- (x'+MinX)sinθ

 

图片旋转后,会出现失真现象,需要用双线性内插值进行优化

 

双线性内插值:对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(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)处的的像素值,以此类推。

这就是双线性内插值法。双线性内插值法计算量大,但缩放后图像质量高,不会出现像素值不连续的的情况。由于双线性插值具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。

 

旋转代码

 

  1. void RotateImageBuf(const BYTE* src, int srcWidth, int srcHeight,
  2. BYTE*& dst, int& dstWidth, int& dstHeight, double angle)    
  3. {   
  4.     double cosA = cos(angle); 
  5.     double sinA = sin(angle); 
  6.  
  7.  
  8.     double x1 = srcWidth * cosA; 
  9.     double y1 = srcWidth * sinA; 
  10.     double x2 = srcWidth * cosA - srcHeight * sinA; 
  11.     double y2 = srcWidth * sinA + srcHeight * cosA; 
  12.     double x3 = - srcHeight * sinA; 
  13.     double y3 = srcHeight * cosA; 
  14.  
  15.     double minWidth = min(0,min(x3,min(x1,x2))); 
  16.     double minHeight = min(0,min(y3,min(y1,y2))); 
  17.  
  18.     double maxWidth = max(0,max(x3,max(x1,x2))); 
  19.     double maxHeight = max(0,max(y3,max(y1,y2))); 
  20.  
  21.     dstWidth = abs(maxWidth - minWidth) + 1; 
  22.     dstHeight = abs(maxHeight - minHeight) + 1;  
  23.  
  24.     double ndstX = 0; 
  25.     double ndstY = 0; 
  26.  
  27.     dst = new BYTE[dstWidth * dstHeight * 4]; 
  28.  
  29.     UINT32  *pDst = (UINT32 *)dst; 
  30.     UINT32  *pSrc = (UINT32 *)src; 
  31.     UINT32   crDefault = ((UINT32 *)src)[0]; 
  32.  
  33.     UINT32 color [2][2]; 
  34.     BYTE alpha[2][2]; 
  35.     BYTE rColor[2][2]; 
  36.     BYTE gColor[2][2]; 
  37.     BYTE bColor[2][2]; 
  38.  
  39.     BYTE afinal,rfinal,gfinal,bfinal; 
  40.     double ox,oy; 
  41.     
  42.     for(int y=0; y < dstHeight; y++) 
  43.     { 
  44.         for(int x=0; x < dstWidth; x++) 
  45.         { 
  46.             ndstX = (x + minWidth) * cosA + (y + minHeight) * sinA; 
  47.             ndstY = (y + minHeight) * cosA - (x +minWidth) * sinA; 
  48.             if((ndstX >= 0) && (ndstX < srcWidth) && (ndstY >= 0)
  49.  && (ndstY < srcHeight)) 
  50.             { 
  51.  
  52.                 color[0][0] = pSrc[ (int)((int)ndstY*srcWidth + ndstX) ];     
  53.                 if((int)ndstX + 1 >= srcWidth) 
  54.                     color[1][0] = crDefault; 
  55.                 else 
  56.                     color[1][0] = pSrc[ (int)((int)ndstY*srcWidth + ndstX +1) ];     
  57.  
  58.                 if((int)ndstY + 1 >= srcHeight) 
  59.                     color[0][1] = crDefault; 
  60.                 else 
  61.                     color[0][1] = pSrc[ (int)(((int)ndstY+1)*srcWidth + ndstX) ];     
  62.  
  63.                 if((int)ndstY + 1 >= srcHeight || (int)ndstX + 1 >= srcWidth) 
  64.                     color[1][1] = crDefault; 
  65.                 else 
  66.                     color[1][1] = pSrc[ (int)(((int)ndstY+1)*srcWidth + ndstX+1) ];    
  67.  
  68.  
  69.                 alpha[0][0]  = (color[0][0] & 0XFF000000) >> 24; 
  70.                 bColor[0][0] = (color[0][0] & 0XFF0000) >> 16; 
  71.                 gColor[0][0] = (color[0][0] & 0X00FF00) >> 8; 
  72.                 rColor[0][0] = color[0][0] & 0X0000FF; 
  73.  
  74.                 alpha[1][0]  = (color[1][0] & 0XFF000000) >> 24; 
  75.                 bColor[1][0] = (color[1][0] & 0XFF0000) >> 16; 
  76.                 gColor[1][0] = (color[1][0] & 0X00FF00) >> 8; 
  77.                 rColor[1][0] = color[1][0] & 0X0000FF; 
  78.  
  79.                 alpha[0][1]  = (color[0][1] & 0XFF000000) >> 24; 
  80.                 bColor[0][1] = (color[0][1] & 0XFF0000) >> 16; 
  81.                 gColor[0][1] = (color[0][1] & 0X00FF00) >> 8; 
  82.                 rColor[0][1] = color[0][1] & 0X0000FF; 
  83.  
  84.                 alpha[1][1]  = (color[1][1] & 0XFF000000) >> 24; 
  85.                 bColor[1][1] = (color[1][1] & 0XFF0000) >> 16; 
  86.                 gColor[1][1] = (color[1][1] & 0X00FF00) >> 8; 
  87.                 rColor[1][1] = color[1][1] & 0X0000FF; 
  88.  
  89.                 //f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1)
  90. // + u(1-v)f(i+1,j) + uvf(i+1,j+1) 
  91.                 ox = (ndstX - (int)ndstX);    
  92.                 oy = (ndstY - (int)ndstY); 
  93.                 rfinal = (1 - ox)*(1 - oy)*rColor[0][0] +
  94.  ox*(1 - oy)*rColor[1][0] + (1-ox)*oy*rColor[0][1] + ox*oy*rColor[1][1];    
  95.                 gfinal = (1 - ox)*(1 - oy)*gColor[0][0] +
  96.  ox*(1 - oy)*gColor[1][0] + (1-ox)*oy*gColor[0][1] + ox*oy*gColor[1][1];  
  97.                 bfinal = (1 - ox)*(1 - oy)*bColor[0][0] +
  98.  ox*(1 - oy)*bColor[1][0] + (1-ox)*oy*bColor[0][1] + ox*oy*bColor[1][1];  
  99.                 afinal = (1 - ox)*(1 - oy)*alpha[0][0] +
  100.  ox*(1 - oy)*alpha[1][0] + (1-ox)*oy*alpha[0][1] + ox*oy*alpha[1][1];  
  101.                  
  102.                 pDst[y * (int)dstWidth + x] = RGBA(rfinal,gfinal,bfinal,afinal); 
  103.             } 
  104.             else 
  105.             { 
  106.                 pDst[y * (int)dstWidth + x] = crDefault; 
  107.             } 
  108.         } 
  109.     } 

需要对浮点型运算,改为整形预算。在模拟上测试过,旋转一张图片,整形预算要比浮点型预算快20倍。

改为整形运算代码。

  1. void RotateImageZhenxingBuf(const BYTE* src, int srcWidth, int srcHeight,
  2.  BYTE*& dst, int& dstWidth, int& dstHeight, double angle)    
  3. {   
  4.     double cosA = cos(angle); 
  5.     double sinA = sin(angle); 
  6.  
  7.  
  8.     double x1 = srcWidth * cosA; 
  9.     double y1 = srcWidth * sinA; 
  10.     double x2 = srcWidth * cosA - srcHeight * sinA; 
  11.     double y2 = srcWidth * sinA + srcHeight * cosA; 
  12.     double x3 = - srcHeight * sinA; 
  13.     double y3 = srcHeight * cosA; 
  14.  
  15.     double minWidthD = min(0,min(x3,min(x1,x2))); 
  16.     double minHeightD = min(0,min(y3,min(y1,y2))); 
  17.  
  18.     double maxWidthD = max(0,max(x3,max(x1,x2))); 
  19.     double maxHeightD = max(0,max(y3,max(y1,y2))); 
  20.  
  21.     dstWidth = abs(minWidthD - maxWidthD) + 1; 
  22.     dstHeight = abs(maxHeightD - minHeightD) + 1;  
  23.  
  24.     int minWidth= minWidthD; 
  25.     int minHeight=  minHeightD; 
  26.  
  27.     int maxWidth =  maxWidthD; 
  28.     int maxHeight =  maxHeightD; 
  29.     int ndstX = 0; 
  30.     int ndstY = 0; 
  31.  
  32.     dst = new BYTE[dstWidth * dstHeight * 4]; 
  33.  
  34.     UINT32  *pDst = (UINT32 *)dst; 
  35.     UINT32  *pSrc = (UINT32 *)src; 
  36.     UINT32   crDefault = ((UINT32 *)src)[0]; 
  37.  
  38.     UINT32 color [2][2]; 
  39.     BYTE alpha[2][2]; 
  40.     BYTE rColor[2][2]; 
  41.     BYTE gColor[2][2]; 
  42.     BYTE bColor[2][2]; 
  43.  
  44.     int afinal,rfinal,gfinal,bfinal; 
  45.      
  46.     long icosA = cosA * 256 * 256; 
  47.     long isinA = sinA * 256 * 256; 
  48.  
  49.     int x;    
  50.     int y;    
  51.     int kx;    
  52.     int ky; 
  53.     for(int j=0; j < dstHeight; j++) 
  54.     { 
  55.         for(int i=0; i < dstWidth; i++) 
  56.         { 
  57.             ndstX = (i + minWidth) * icosA + (j + minHeight) * isinA; 
  58.             ndstY = (j + minHeight) * icosA - (i +minWidth) * isinA; 
  59.             ndstX = ndstX >> 8; 
  60.             ndstY = ndstY >> 8; 
  61.             if ( (ndstX >> 8) < srcWidth && (ndstX >> 8) >=0
  62.  && (ndstY >> 8) < srcHeight && (ndstY >> 8) >= 0)    
  63.             {   
  64.  
  65.                 kx = ndstX >> 8;    
  66.                 ky = ndstY >> 8;    
  67.                 x = ndstX & 0xFF;    
  68.                 y = ndstY & 0xFF;    
  69.  
  70.                 color[0][0] = pSrc[ ky*srcWidth + kx ];  
  71.                 if(kx + 1 >= srcWidth) 
  72.                     color[1][0] = crDefault; 
  73.                 else 
  74.                     color[1][0] = pSrc[ ky*srcWidth + kx +1 ]; 
  75.  
  76.                 if(ky + 1 >= srcHeight) 
  77.                     color[0][1] = crDefault; 
  78.                 else 
  79.                     color[0][1] = pSrc[ (ky+1)*srcWidth + kx ];  
  80.  
  81.                 if(ky + 1 >= srcHeight || kx + 1 >= srcWidth) 
  82.                     color[1][1] = crDefault; 
  83.                 else 
  84.                     color[1][1] = pSrc[ (ky+1)*srcWidth + kx+1 ];   
  85.  
  86.                 alpha[0][0]  = (color[0][0] & 0XFF000000) >> 24; 
  87.                 bColor[0][0] = (color[0][0] & 0XFF0000) >> 16; 
  88.                 gColor[0][0] = (color[0][0] & 0X00FF00) >> 8; 
  89.                 rColor[0][0] = color[0][0] & 0XFF; 
  90.  
  91.                 alpha[1][0]  = (color[1][0] & 0XFF000000) >> 24; 
  92.                 bColor[1][0] = (color[1][0] & 0XFF0000) >> 16; 
  93.                 gColor[1][0] = (color[1][0] & 0X00FF00) >> 8; 
  94.                 rColor[1][0] = color[1][0] & 0XFF; 
  95.  
  96.                 alpha[0][1]  = (color[0][1] & 0XFF000000) >> 24; 
  97.                 bColor[0][1] = (color[0][1] & 0XFF0000) >> 16; 
  98.                 gColor[0][1] = (color[0][1] & 0X00FF00) >> 8; 
  99.                 rColor[0][1] = color[0][1] & 0XFF; 
  100.  
  101.                 alpha[1][1]  = (color[1][1] & 0XFF000000) >> 24; 
  102.                 bColor[1][1] = (color[1][1] & 0XFF0000) >> 16; 
  103.                 gColor[1][1] = (color[1][1] & 0X00FF00) >> 8; 
  104.                 rColor[1][1] = color[1][1] & 0XFF; 
  105.  
  106.                 afinal = (0x100 - x)*(0x100 - y)*alpha[0][0]
  107.  + x*(0x100 - y)*alpha[1][0] + (0x100-x)*y*alpha[0][1] + x*y*alpha[1][1];    
  108.                 rfinal = (0x100 - x)*(0x100 - y)*rColor[0][0]
  109.  + x*(0x100 - y)*rColor[1][0] + (0x100-x)*y*rColor[0][1] + x*y*rColor[1][1];    
  110.                 gfinal = (0x100 - x)*(0x100 - y)*gColor[0][0]
  111.  + x*(0x100 - y)*gColor[1][0] + (0x100-x)*y*gColor[0][1] + x*y*gColor[1][1];    
  112.                 bfinal = (0x100 - x)*(0x100 - y)*bColor[0][0]
  113.  + x*(0x100 - y)*bColor[1][0] + (0x100-x)*y*bColor[0][1] + x*y*bColor[1][1];    
  114.  
  115.                 afinal = afinal >> 16;    
  116.                 if (afinal>255)    
  117.                     afinal = 255;    
  118.                 if (afinal<0)    
  119.                     afinal = 0;    
  120.  
  121.                 rfinal = rfinal >> 16;    
  122.                 if (rfinal>255)    
  123.                     rfinal = 255;    
  124.                 if (rfinal<0)    
  125.                     rfinal = 0;   
  126.  
  127.                 gfinal = gfinal >> 16;    
  128.                 if (gfinal>255)    
  129.                     gfinal = 255;    
  130.                 if (gfinal<0)    
  131.                     gfinal = 0;   
  132.  
  133.                 bfinal = bfinal >> 16;    
  134.                 if (bfinal>255)    
  135.                     bfinal = 255;    
  136.                 if (bfinal<0)    
  137.                     bfinal = 0;   
  138.                 pDst[j * dstWidth + i] = RGBA(rfinal,gfinal,bfinal,afinal); 
  139.             } 
  140.             else 
  141.             { 
  142.                 pDst[j * dstWidth + i] = crDefault; 
  143.             } 
  144.         } 
  145.     } 

用Imaging接口加载png图片,并调用RotateImageBuf进行旋转,最后返回IImage接口。

  1. // need to delete pImagebuf; 
  2. HRESULT RotateImage(IImagingFactory *pImgFactory, IImage *pImage
  3. , IImage * &pImageOut, LPBYTE &pImageBuf, double angle) 
  4.     HRESULT hr = S_OK; 
  5.  
  6.     IBitmapImage *pIBitmap = NULL; 
  7.     ImageInfo ImInfo; 
  8.     pImage->GetImageInfo(&ImInfo); 
  9.  
  10.     if((ImInfo.PixelFormat & 0xFF00)>>8 != 32) 
  11.     { 
  12.         hr = S_FALSE; 
  13.         goto Error; 
  14.     } 
  15.     if(S_OK != pImgFactory->CreateBitmapFromImage( 
  16.         pImage, ImInfo.Width, ImInfo.Height, ImInfo.PixelFormat
  17. , InterpolationHintDefault, &pIBitmap)) 
  18.     { 
  19.         hr = S_FALSE; 
  20.         goto Error; 
  21.     } 
  22.      
  23.     RECT rcLocked ={0,0,ImInfo.Width,ImInfo.Height}; 
  24.     BitmapData bmpData; 
  25.  
  26.     if(S_OK != pIBitmap->LockBits(&rcLocked,
  27.  ImageLockModeRead | ImageLockModeWrite, ImInfo.PixelFormat, &bmpData)) 
  28.     { 
  29.         hr = S_FALSE; 
  30.         goto Error; 
  31.     } 
  32.  
  33.     BYTE *pDst = NULL; 
  34.     int nDstWidth=0,nDstHeight=0; 
  35.     RotateImageZhenxingBuf((BYTE *)bmpData.Scan0,
  36.  ImInfo.Width, ImInfo.Height, pDst, nDstWidth, nDstHeight, angle); 
  37.      
  38.     pIBitmap->UnlockBits(&bmpData); 
  39.  
  40.     BitmapData bmpDataNew; 
  41.     bmpDataNew.Height = nDstHeight; 
  42.     bmpDataNew.Width = nDstWidth; 
  43.     bmpDataNew.PixelFormat = ImInfo.PixelFormat; 
  44.     bmpDataNew.Stride = nDstWidth * 4; 
  45.     bmpDataNew.Reserved = 0; 
  46.     bmpDataNew.Scan0 = (void *)pDst; 
  47.  
  48.     IBitmapImage *pBmpImageNew = NULL; 
  49.     hr = pImgFactory->CreateBitmapFromBuffer(&bmpDataNew, &pBmpImageNew); 
  50.  
  51.     IImage * pImageNew = NULL; 
  52.     pBmpImageNew->QueryInterface(IID_IImage, (void **)&pImageNew); 
  53.      
  54.     pImageOut = pImageNew; 
  55.     pImageBuf = pDst; 
  56. Error: 
  57.      
  58.     if(pBmpImageNew) 
  59.         pBmpImageNew->Release(); 
  60.  
  61.     if(pIBitmap) 
  62.         pIBitmap->Release(); 
  63.     return hr; 

 

(jinhaijian)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201007/9897.html]
本文出处:CSDN博客 作者:jinhaijian
顶一下
(6)
54.5%
踩一下
(5)
45.5%
------分隔线----------------------------
相关文章
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容