日期:2014-05-20  浏览次数:20727 次

J2me中任意角度图片旋转(三)

? J2me中任意角度图片旋转

作者:pandonix

日期:2007920

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明

原文地址:

http://pandonix.iteye.com/

本文主要讨论在J2me中如何实现任意角度的图片旋转。其实,早在几年前,minisoyouBB就已经给出了实现算法,相信做j2me游戏开发的朋友们也都收藏过该算法。本文从图像旋转的基本理论出发,详细讨论如何使用实现和优化该算法,希望对旋转算法感兴趣的朋友有帮助。

?

解决“坏点”仔细思考一下,坏点出现的主要原因在于,旋转公式的定义域是整个实数域,而像素点显然是离散点,因此,在进行映射时,会产生一定的误差,所以造成本该被定义的像素点,没有被映射到。其实,在图像处理领域,已经存在很多优化的算法,而且理论都基于数学的。

回到我们的问题,为了解决坏点,我们可以这样来考虑:改遍历原图像数组为遍历newPixels数组,这样就能保证所有的newPixels可以被覆盖。具体代码如下:

java 代码
  1. public?static?int[]?rotate(int[]?_pixels,int?_width,int?_height,double?_angle) ??
  2. { ??
  3. ????int?i,j; ??
  4. ????double?radius?=?Math.sqrt(_width*_width?+?_height*_height); ??
  5. ????int?r?=?(int)radius; ??
  6. ????int[]?newPixels?=?new?int[r*r]; ??
  7. ????for(i?=?0;?i?<?newPixels.length;i++) ??
  8. ????{ ??
  9. ????????????newPixels[i]?=?(TRANSPARENT)<<24; ??
  10. ????} ??
  11. ????double?x1,y1; ??
  12. ????int?x2,y2; ??
  13. ????double?cos?=?Math.cos(_angle); ??
  14. ????double?sin?=?Math.sin(_angle); ??
  15. ????for(i?=?0;i?<?r;i++) ??
  16. ????{ ??
  17. ????????for(j?=?0;j?<?r;j++) ??
  18. ????????{ ??
  19. ????????????x1?=?j?+?(-?r)/2; ??
  20. ????????????y1?=?i?+?(-?r)/2; ??
  21. ????????????x2?=?(int)(x1*cos?+?y1*sin); ??
  22. ????????????y2?=?(int)(-x1*sin?+?y1*cos); ??
  23. ????????????if(x2?>=?-_width/2&&x2<?_width/2&&y2?>=?-_height/2&&y2<?_height/2) ??
  24. ????????????{ ??
  25. ????????????????int?k?=?(y2?+?_height/2)*_width+x2+_width/2; ??
  26. ???????????????? ??
  27. ????????????????newPixels[i*r?+?j]?=?_pixels[k]; ??
  28. ????????????} ??
  29. ????????} ??
  30. ????} ??
  31. ????return?newPixels; ??
  32. } ??
? 效果如图所示,基本上解决图像中的坏点,失真度基本可以接受。如果你觉得不符合要求,没关系,下面会介绍BB的算法。速度优化

上面这种算法的时间复杂程度是O(n^2),那么对该算法是否可以优化呢?参考了《A Fast Algorithm for Rotating Bitmaps》一文,可以对算法作以下优化:

?
  1. public?static?int[]?rotate3(int[]?_pixels,int?_width,int?_height,double?_angle) ??
  2. { ??
  3. ????int?i,j; ??
  4. ????double?radius?=?Math.sqrt(_width*_width?+?_height*_height); ??
  5. ????int?r?=?(int)radius; ??
  6. ????int[]?newPixels?=?new?int[r*r]; ??
  7. ????for(i?=?0;?i?<?newPixels.length;i++) ??
  8. ????{ ??
  9. ????????????newPixels[i]?=?(TRANSPARENT)<<24; ??
  10. ????} ??
  11. ????double?x2,y2; ??
  12. ????int?x3,y3; ??
  13. ????double?cos?=?Math.cos(_angle); ??
  14. ????double?sin?=?Math.sin(_angle); ??
  15. ????for(i?=?0;i?<?r;i++) ??
  16. ????{ ??
  17. ????????x2?=?(-r/2)*cos?+?(i?-?r/2)*sin; ??
  18. ????????y2?=?(r/2)*sin?+?(i?-?r/2)*cos; ??
  19. ????????x3?=?(int)x2; ??
  20. ????????y3?=?(int)y2; ??
  21. ????????for(j?=?0;j?<?r;j++) ??
  22. ????????{ ??
  23. ????????????if(x3?>=?-_width/2&&x3<?_width/2&&y3?>=?-_height/2&&y3<?_height/2) ??
  24. ????????????{ ??
  25. ????????????????newPixels[i*r?+j]?=?_pixels[(y3?+?_height/2)*_width+x3+_width/2]; ??
  26. ????????????} ??
  27. ????????????x2?+=?cos; ??
  28. ????????????y2?-=?sin; ??
  29. ????????????x3?=?(int)x2; ??
  30. ????????????y3?=?(int)y2; ??
  31. ????????} ??
  32. ????} ??
  33. ????return?newPixels; ??
  34. } ??

?

使用定点数实现其实,主要就是实现SinCos的求值,基本思路是:将SinCos值放大255倍,进行计算以后,对结果再进行缩小处理,具体请参考代码Rotation2.javaBB的算法应该说,BB给出的算法的失真程度最小,他是对目标像素点进行了一个加权计算,但是,遗憾的是,翻阅了很多资料,我也没有找到该算法的相关理论介绍。若有朋友了解,请正解。具体代码请参考Rotation_4444.java总结与思考

总的说来,旋转后的位图都存在不同情况的失真,所以在实际开发过程中,需要视情况而定。除此之外,不同的终端对于透明的不同,例如,K700在透明方面问题就比较多。

1 楼 pandonix 2007-09-21  
网速太慢,代码明天再传
2 楼 wuhua 2007-10-05  
不错,支持写的很详细