图形旋转好玩又有实用性, 这里介绍一种简单的图形旋转算法.

具体步骤如下:

1. 首先将原图和旋转图的坐标原点都变换到图形的中心位置处.
2. 历遍旋转图形中的每一个pixel, 将pixel的坐标(j,i)反向旋转映射到原图, 得到原图对应的坐标值(Xr,Yr).
3. 考虑到旋转图的尺寸可能大于原图,这时需要检测(Xr,Yr)是否在原图范围内,如果不是,则忽略下面步骤.
4. (Xr,Yr)通常并不是正好对应到原图中一个整点的像素, 而是会夹在四个像素中(如图), 对四个像素的位置进行插值计算(也即所谓的双线性插值), 可以得到对应位置的RGBA值.

5. 由于内存中的图形数据是以左上角为坐标原点逐行记录的, 我们需将(j,i)变换到此坐标系统下(步骤1的反向操作), 得到其对应的内存位置, 然后将RGBA数值存入此处.
6. 通过逐点计算,最终可以得到完整的旋转后的图形.
7. 待改进处: 这里由于对图形边缘点的采样不够密集,因此得到的旋转图形边缘会出现锯齿现象. 可以细化映射颗粒度,如以1/4像素为单位进行映射计算.

更普遍的情况是,我们需要对原图中的指定区域进行旋转操作, 即进行旋转抠图. 下面是这一算法的C语言实现:

/*-----------------------------------------------------------------
@eimg:         输入图像
@oimg:         输出图像(NULL忽略)
@height,width:     输出图像的尺寸
@px,py:        抠图相对原图的位置
@angle:        旋转角度
-------------------------------------------------------------------*/
EGI_IMGBUF* egi_imgbuf_rotBlockCopy2( EGI_IMGBUF *eimg, EGI_IMGBUF *oimg, int height, int width,int px, int py, float angle)
{int i,j;float xr,yr;           int index_out;EGI_IMGBUF      *outimg=NULL;float sina=sin(MATH_PI*angle/180);float cosa=cos(MATH_PI*angle/180);/* 1. Check input eimg */if(eimg==NULL || eimg->imgbuf==NULL || eimg->height<=0 || eimg->width<=0 ) {egi_dpstd("Input holding eimg is NULL or uninitiliazed!\n");return NULL;}/* 2. Input oimg is NULL *//* 注:这里将输出图像的长宽均设为奇数,这样中心点是个整点位置,便于计算. */if(oimg==NULL) {/* Make H/W an odd value, then it has a symmetrical center point. */height |= 0x1;width |= 0x1;if(height<3)height=3;if(width<3)width=3;/* Create an imgbuf accordingly */outimg=egi_imgbuf_create(height, width, 0, 0); /* H, W, alpah, color */if(outimg==NULL) {egi_dpstd("Fail to create outimg!\n");return NULL;}/* Check ALPHA data */if(eimg->alpha==NULL) {free(outimg->alpha);outimg->alpha=NULL;}}/* Input oimg is NOT NULL */else {height=oimg->height;width=oimg->width;outimg=oimg;}/* 3. Clear outimg first. ALPHA to be 0, OR same as eimg. 如果是RGBA格式,可以在这里设置背景色. */egi_imgbuf_resetColorAlpha(outimg, WEGI_COLOR_GRAY2, outimg->alpha==NULL ? -1:0 );  /* img, color, alpha *//* 4. Map back point coordinates to eimg 以旋转图片中心为原点, 历遍旋转图形中的每一个像素点. 反向映射并插值计算得RGBA. */int m=height>>1;int n=width>>1;for(i=-m; i<=m; i++) {for(j=-n; j<=n; j++) {/* 4.1 Map to original coordiante (xr,yr), Origin at center.* 2D point rotation formula ( a positive: Right_hand Rule. ):*      x'=x*cos(a)-y*sin(a)*      y'=x*sin(a)+y*cos(a)*   Coord axis anti_clockwise, point colokwise rotate.*   points coordinates relative to up_right block coord.*  旋转变换公式, 可以查数学手册.*/xr=cosa*j-sina*i;yr=sina*j+cosa*i;/* 4.2 Shift Origin to left_top, as of eimg->imgbuf 变换到原图坐标下 */xr += px;yr += py;/* 4.3 Copy pixel alpha and color.  Limit xr,yr, ignore if they are out of original imgbuf area. */if( xr >= 0.0 && xr <= eimg->width-1 && yr >=0.0 && yr <= eimg->height-1) {index_out=width*(i+m)+(j+n);/* 4.3.1 的到相互邻的4个像数 */int indx1 = eimg->width*floorf(yr)+floorf(xr);int indx2 = eimg->width*floorf(yr)+ceilf(xr);int indx3 = eimg->width*ceilf(yr)+floorf(xr);int indx4 = eimg->width*ceilf(yr)+ceilf(xr);EGI_16BIT_COLOR  pcolor;EGI_8BIT_ALPHA  palpha;float pft;/* 4.3.2 Interpolate within 4 pixles  4点插值得到RGBA */if(eimg->alpha!=NULL && outimg->alpha!=NULL) {egi_16bitColor_interplt4p(eimg->imgbuf[indx1], eimg->imgbuf[indx2],  /* color1, color2 */eimg->imgbuf[indx3], eimg->imgbuf[indx4],       /* color3, color4 */eimg->alpha[indx1], eimg->alpha[indx2],         /* alpha1, alpha2 */eimg->alpha[indx3], eimg->alpha[indx4],         /* alpha3, alpah4 */modff(xr,&pft)*(1<<15), modff(yr, &pft)*(1<<15),  /* f15_x, f15_y */&pcolor, &palpha );outimg->imgbuf[index_out]=pcolor;outimg->alpha[index_out]=palpha;}else {egi_16bitColor_interplt4p(eimg->imgbuf[indx1], eimg->imgbuf[indx2],  /* color1, color2 */eimg->imgbuf[indx3], eimg->imgbuf[indx4],       /* color3, color4 */0, 0, 0, 0,     /* alpha1, alpha2, alpha3, alpha4 */modff(xr,&pft)*(1<<15), modff(yr, &pft)*(1<<15),  /* f15_x, f15_y */&pcolor, NULL );outimg->imgbuf[index_out]=pcolor;}}}}return outimg;
}

(更多代码见 https://github.com/widora/wegi)

效果:

一种简单的图形旋转算法相关推荐

  1. 选择排序(Selection sort)是一种简单直观的排序算法

    选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大 ...

  2. 一种简单的抗锯齿算法

    在LCD等显示器上逐点绘制几何图像的时候, 往往对几何体的边缘采样不足, 这就会导致出现锯齿状不平滑的边缘. 为了尽量减弱这种现象,需要在斜线或物体边缘进行更密集的采样,然后根据一定的权重比例将色彩/ ...

  3. 一种简单的抽签/抽奖算法逻辑

    1.抽签计算方法步骤: 注:A:基数:B:翻转数: X:报名次数:Y:种子号,即起始中签号:Z:阶数: (1)A=(抽签日的上一个工作日的深圳证券交易所深证成指"今收"指数×100 ...

  4. 一种简单的地图聚合算法

    百度地图的聚合算法 这段百度算法的描述来自博客:https://blog.csdn.net/javine/article/details/51195014 总结如下: 百度地图把整个地球是按照一个平面 ...

  5. 一种简单的图像LDR->HDR算法

    算法比较简单,尽量简单说. 文章:Fully-automatic inverse tone mapping algorithm based on dynamic mid-level tone mapp ...

  6. python素数最优算法_几种简单的求素数算法的复杂度分析

    素数的算法有很多种,现在主要讲两种算法及其改进版本的复杂度分析,解释性能提升的幅度.同时应用一个素数定理:素数的平方一定是合数,那么在范围内最大数的开方范围内找不到能整除的数,那么这个数是素数.应用这 ...

  7. java 路由算法_几种简单的负载均衡算法及其Java代码实现

    什么是负载均衡 负载均衡,英文 名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助.通过某种 负载分 ...

  8. 排序算法(01)— 三种简单排序(冒泡、插入、选择)

    一.概述 排序是数据处理中十分常见且核心的操作,虽说实际项目开发中很小几率会需要我们手动实现,毕竟每种语言的类库中都有n多种关于排序算法的实现.但是了解这些精妙的思想对我们还是大有裨益的. 1.1 排 ...

  9. 快速图像旋转算法的c++实现

    0 引言 在数字图像处理技术中,图像旋转算法是最基本的操作之一.本文实现一种快速的图像旋转算法,并和原始方法以及opencv提供的旋转方案进行速度上的比较. 1 基本原理 图像旋转有两种计算坐标的思路 ...

最新文章

  1. vue.js学习系列-第二篇
  2. FireDAC 下的 Sqlite [4] - 创建数据库
  3. 【Paper】2021_Observer-based distributed consensus for multi-agent systems with directed networks and
  4. boost::lambda模块ll_static_cast,ll_dynamic_cast,ll_const_cast,ll_reinterpret_cast的测试程序
  5. flask和ajax通信详细步骤与完整代码
  6. java 固定listview_listview Button始终放在底部示例
  7. glup node 内存不够_Redis:内存被我用完了!该怎么办?
  8. CSUOJ修墙壁C语言,棋牌挂怎么编写 -棋牌挂怎么编写V6.1.16
  9. matlab三角函数降次,三角函数降次公式及推导过程
  10. 深度学习自学(十九):caffe添加深度可分离卷积
  11. as3 socket 跨域连接
  12. gitolite安装及配置
  13. 简述osi参考模型各层主要功能_简述OSI参考模型及各层的功能
  14. C语言ascii对照表
  15. 二分类最优阈值确定_结合mRMR选择和IFCM聚类的遥感影像分类算法
  16. 带参数的公众号二维码 生成+后台拦截java
  17. 数据分析入门篇(一)
  18. 阅读源码-理解torch.utils.data、torch.utils.data.Dataset、torch.utils.data.DataLoader的工作方式
  19. 计算机网络是计算机科学技术和结合的产物,计算机网络是计算机技术和什么
  20. 诺基亚如何利用计算机上网,诺基亚S60怎么通过笔记本的WIFI上网?

热门文章

  1. 浅析供应链金融业务发展态势及提升路径
  2. 2022-2028全球快餐肉汤食品行业调研及趋势分析报告
  3. 啥?以后找工作面试求职者的将不是人!那是啥?道翰天琼认知智能机器人平台API接口为您揭秘。
  4. EndeavourOS安装配置全攻略!
  5. 图像编辑、图像修饰及修补_如何增强和修饰图像[Photoshop教程]
  6. 【ROS小车课设】虚拟机端编译riki工作空间问题解决
  7. 《绝地求生》玩家排名预测(2万5千字~大型综合实战)
  8. 以前常用的攻击软件源代码
  9. OpenHarmony轻量系统 子系统,组件那点事
  10. Ubuntu20.04安装英伟达驱动