软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|开发客
您现在的位置:天极网 > 开发频道 > 在J2ME/MIDP中实现图像旋转
全文

在J2ME/MIDP中实现图像旋转

2006-07-27 07:00作者:王伟 李春雷出处:计算机与信息技术责任编辑:方舟
  一般图像的旋转算法

  1、算法思想

  为实现整个图像的旋转,我们首先获取源图像每个点的像素值。然后根据旋转点和角度的大小计算出新图像的大小。再逐点计算源图像中每个点经旋转后在新图像中对应点的坐标,并把相应的像素值赋给它。

  在图三中,阴影部分为源图像,O为旋转点,P、Q分别为旋转前后图像左上角的点,cx,cy为O相对于源图像左上角P点的坐标值。
这里我们以O为圆心,以O距图像4个顶点的距离的最大值作为半径dr画圆,这样图像无论以任何角度旋转都不会超出这个圆的范围。于是,我们就以该圆为画布绘制旋转所得新图像。由于实际中图像是用矩形表示的,于是我们生成和圆的外切正方形(图中虚线部分)等大小的新图像。

  对源图像中任一点(i,j),根据上面的公式,不难计算出旋转θ度在新图像中的位置,即相对于Q点的位置(destX , destY):

destX = dr + (i - cx) *cos(radian) - (j - cy)*sin(radian);
destY = dr + (j - cy) *cos(radian) + (i - cx)*sin(radian);

  计算出这个位置后,把该点的像素值赋值到这个位置,如此对每个点进行这种变换,即可实现整个图像的旋转。

  旋转后的图像较大,在实际绘制时需要做位置调整,不难看出,Q点相对于P点的偏移量为(cx-dr , cy-dr)。即假设源图像的屏幕位置为(a , b),则旋转后的图像位置应该为( (a + cx – dr) , (b + cy – dr) )。


图三 旋转算法示意图

  2、在J2ME中的算法实现

  我们将上面的思想具体化,得到算法的流程图(见图四示)


图四 算法流程图

  在MIDP2.0中,Image类提供了两个方法:getRGB()和createRGBImage(),分别完成获取图像象素信息和通过像素数组创建图像的功能。借助于这两个方法,结合上面的流程图,我们得到实现图像旋转算法的代码,如下面所示。

/**
*@param imgSource 源图像
*@param cx 旋转点相对于源图像坐上角横坐标
*@param cy 旋转点相对于源图像坐上角纵坐标
*@param theta 图像逆时针旋转的角度
*@param dd 含2个元素的整形数组,存放新图像相对源图像沿x轴和y轴的位置偏移量
*@return 旋转后的图像
**/
public Image rotate(Image imgSource, int cx, int cy, double theta, int[] dd) {
 if (Math.abs(theta % 360) < 0.1) return imgSource; //角度很小时直接返回
  int w1 = imgSource.getWidth(); //原始图像的高度和宽度
  int h1 = imgSource.getHeight();
  int[] srcMap = new int[w1 * h1];
  imgSource.getRGB(srcMap, 0, w1, 0, 0, w1, h1); //获取原始图像的像素信息
  int dx = cx > w1 / 2 ? cx : w1 - cx; //计算旋转半径
  int dy = cy > h1 / 2 ? cy : h1 - cy;
  double dr = Math.sqrt(dx * dx + dy * dy);
  int wh2 = (int) (2 * dr + 1); //旋转后新图像为正方形,其边长+1是为了防止数组越界
  int[] destMap = new int[wh2 * wh2]; //存放新图像象素的数组
  double destX, destY;
  double radian = theta * Math.PI / 180; //计算角度计算对应的弧度值
  for (int i = 0; i < w1; i++) {
   for (int j = 0; j < h1; j++) {
    if (srcMap[j * w1 + i] >> 24 != 0) { //对非透明点才进行处理
     // 得到当前点经旋转后相对于新图像左上角的坐标
     destX = dr + (i - cx) * Math.cos(radian) + (j - cy)* Math.sin(radian);
     destY = dr + (j - cy) * Math.cos(radian) - (i - cx)* Math.sin(radian);
     //从源图像中往新图像中填充像素
     destMap[(int) destY * wh2 + (int) destX] = srcMap[j * w1 + i];
    }
   }
  }
  dd[0] = cx-dr; //返回位置偏移分量
  dd[1] = cy-dr;
  return Image.createRGBImage(destMap, wh2, wh2, true); //返回旋转后的图像
}

  3、旋转失真问题

  因为旋转公式含有三角函数,所以求出的旋转坐标取整后有可能插入到先前已插入的位置中,而没有插入到它本应该插入的位置。例如:计算出旋转坐标(3.1,4)取整后插入到(3,4)中;如果计算下个旋转坐标为(3.4,4),取整后又被插入到(3,4)中,因此覆盖了原来的像素点,而且(3.4,4)对应的像素点没有办法插入到它应该插入的位置,造成失真。

  要解决这个问题,在不考虑牺牲额外资源的情况下,一般的方法是先将图像放大若干倍,然后再进行旋转,再等比例缩小。对于边界可考虑马赛克的处理方式或者用两行重描补偿误差的办法。

IT培训

软件资讯·软件下载尽在天极软件

相关搜索:
关注此文读者还看过
网友关注
软件下载
娱乐下载
驱动下载
文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868 023-63659988
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|52PK游戏网|IT分众