我一直在尝试使用旋转矩阵来旋转图像。以下是我一直在使用的代码。我一直试图这样做几天,而且每次看起来都有问题,但我无法看到我做错了什么。例如,我的图像变得倾斜,而不是旋转......
下面的代码分为两部分:实际旋转,向上移动图片使其出现在正确的位置(需要将其所有点都高于0才能正确保存)。它将像素数组(包含位置信息(x,y)和颜色信息(r,g,b)),图像(仅用于获取其像素数,即数组大小和宽度)作为输入。 ,以及旋转的弧度值。
负责旋转的部分本身就是线条上方的部分,而线条下方的部分则负责计算图像中的最低点,并将所有像素向上或向右移动以便完全适合(我需要)仍然要实现一个功能,以便在图像旋转45度或类似时改变图像大小。
void Rotate( Pixel *p_pixelsToRotate, prg::Image* img, float rad )
{
int imgLength = img->getPixelCount();
int width = img->getWidth();
int x { 0 }, y { 0 };
for( int i = 0; i < imgLength; i++ )
{
x = p_pixelsToRotate[i].x;
y = p_pixelsToRotate[i].y;
p_pixelsToRotate[i].x = round( cos( rad ) * x - sin( rad ) * y );
p_pixelsToRotate[i].y = round( sin( rad ) * x + sin( rad ) * y );
}
===========================================================================
Pixel* P1 = &p_pixelsToRotate[ width - 1 ]; // Definitions of these are in the supporting docs
Pixel* P3 = &p_pixelsToRotate[ imgLength - 1 ];
int xDiff = 0;
int yDiff = 0;
if( P1->x < 0 || P3->x < 0 )
{
(( P1->x < P3->x )) ? ( xDiff = abs( P1->x )) : ( xDiff = abs( P3->x ));
}
if( P1->y < 0 || P3->y < 0 )
{
(( P1->y < P3->y )) ? ( yDiff = abs( P1->y )) : ( yDiff = abs( P3->y ));
}
for( int i = 0; i < imgLength; i++ )
{
p_pixelsToRotate[i].x += xDiff;
p_pixelsToRotate[i].y += yDiff;
}
}
我宁愿自己解决这个问题,但是现在已经超过一个星期了。我不明白为什么函数没有旋转输入像素数组的位置信息。如果有人可以看一看,也许发现我的逻辑不起作用的原因,我将非常感激。谢谢。
答案 0 :(得分:4)
似乎你刚刚在旋转矩阵中犯了错误:
p_pixelsToRotate[i].y = round( sin( rad ) * x + sin( rad ) * y );
^^^---------------change to cos
答案 1 :(得分:3)
首先,这是一个错误:
p_pixelsToRotate[i].x = round( cos( rad ) * x - sin( rad ) * y );
p_pixelsToRotate[i].y = round( sin( rad ) * x + >>>sin<<<( rad ) * y );
>>>sin<<<
应为cos
。这可以解释得到剪切而不是旋转。
其他评论:在位图数据中存储像素坐标是解决位图旋转问题的极其昂贵的方法。更好的方法是逆变换采样。使用源图像X并希望使用变换R旋转它以获得Y,您当前正在考虑
Y = R X
其中X和Y具有明确存储的像素坐标。要使用反向采样,请考虑使用R的倒数在两侧乘以相同的等式。
R^(-1) Y = X
其中坐标是隐式的。也就是说,为了产生Y [j] [i],用逆R^(-1)
变换(j,i)以获得 X 图像中的坐标(x,y)。用它来对X中最近的像素X [round(x)] [round(y)]进行采样,并将其指定为Y [j] [i]。
(实际上,更复杂的算法不是简单的舍入,而是采用(x,y)周围X像素的加权平均值来获得更平滑的结果。如何选择权重是一个很大的附加主题。)
完成这项工作后,您可以更进一步。一些代数不是对每个像素进行完整的矩阵向量乘法,而是显示前一个采样坐标可以更新以获得相邻的一个(右侧或左侧,上方或下方),只需添加几个。这大大加快了速度。
旋转的反转是微不足道的计算!只是否定旋转角度。
最后一点是,您使用三元运算符o ? o : o
来选择分配是非常糟糕的风格。而不是:
(( P1->x < P3->x )) ? ( xDiff = abs( P1->x )) : ( xDiff = abs( P3->x ));
说
xDiff = ( P1->x < P3->x ) ? abs( P1->x ) : abs( P3->x );