如何在C中以90度的增量旋转bmp图像?

如何在C中以90度的增量旋转bmp图像?,c,rotation,C,Rotation,我正试图编写一个用C语言处理bmp图像的程序,到目前为止,我已经成功地将其旋转如下: for (row=0; row < rows; row++) for (col=0; col < cols; col++) { (*new) + rows*col + (rows - row -1) = original + row*cols + col; } for(行=0;行

我正试图编写一个用C语言处理bmp图像的程序,到目前为止,我已经成功地将其旋转如下:

 for (row=0; row < rows; row++)
      for (col=0; col < cols; col++) 
        {
          (*new) + rows*col + (rows - row -1) = original + row*cols + col;
        }
for(行=0;行<行;行++)
for(col=0;col
其中:Original=原始bmp,new=新bmp,其大小取决于我要应用的旋转量。两者都是指向bmp的指针,new是指向指针的指针。 我已经做了好几次了,当它应该顺时针旋转时,它会逆时针旋转。这是一个问题,但我想我可以逆时针翻转它足够长的时间,让它看起来是顺时针旋转。我的问题是:如何从原始bmp图像进行多次旋转,并使其在我正在创建的新bmp图像上结束。 也就是说,如何执行上述操作多次,但仍然只有1个大小正确的输入和1个输出文件。 我希望使用指针来实现这一点,因为这将使我更容易在其他过程中操作输出。 我希望这足够详细


谢谢。

使用矩阵。伪代码:

class Matrix {
    double m11,m12,m21,m22;
};

dest.x = matrix.m11*src.x + matrix.m12*src.y;
dest.y = matrix.m21*src.x + matrix.m22*src.y;
其中
x=x-image.width/2和y=y-image.height/2


下面的代码演示浮点数组旋转90度的倍数。后来我将浮点数组转换为字节数组,以便生成测试图像来验证结果;我没有包括代码的这一部分,因为它只会混淆要点,而不是你真正想问的。如果你需要那部分,让我知道我会贴出来的

请注意,我的旋转是“不到位”而不是“到位”。我相信后者是您真正感兴趣的,但即使如此,下面的方法对您来说应该是一个良好的开端。关于就地转换的附加讨论可以是,它围绕转置类型操作(内存交换)的使用展开,但我没有时间整理所有这些细节,我将这部分留给您

回想一下,对于n*90度的逆时针旋转,变换由以下公式给出:

那么当然:

但在实际代码中,您需要分别按imageHeight/2和imageWidth/2转换行“和列”,如下面的代码所示,以避免向数组传递负索引

将row_p和col_p表示为row'和col',代码如下所示:

// Note:  nX = pixels wide, nY = pixels tall
float *dataVector = // some data source, arbitrary

// Setup the array for the out-of-place transformation:
float *dataVector2 = new float[nX*nY]; 

int n = -2;  // Example: set n = -2 to rotate counter-clockwise 180 deg
for (int row = 0; row < nY; row++) {
    for (int col = 0; col < nX; col++) {
        int row_p = cosf(n*M_PI_2)*(row-nY/2) - sinf(n*M_PI_2)*(col-nX/2) + nY/2;
        int col_p = sinf(n*M_PI_2)*(row-nY/2) + cosf(n*M_PI_2)*(col-nX/2) + nX/2;
        dataVector2[row*nX + col] = dataVector[row_p*nX + col_p];
    }
}

// Later convert float array to image ...
其结果是+n值给出顺时针旋转;如果需要逆时针旋转,只需将负值n,即-n传递给代码,如上面的示例所示。这样做的效果是只更改上面旋转矩阵的非对角项的符号


希望这能有所帮助。

简化代码的一种方法是定义两个沿循环运行的2D基准:

原基:

  • x0=0
  • y0=0
  • dx=1
  • dy=cols
新基地

  • x0=行-1
  • y0=0
  • dx=行
  • dy=-1
用这些重写代码应该容易得多。它还具有从内部循环中移除乘法的优点

PIXEL *source = original;
PIXEL *target = new + (rows - 1) + (0 * cols);

int source_di = 1;
int source_dj = cols;

int target_di = rows;
int target_dj = -1;

for (int j = 0; j < rows; ++j) {
    int saved_source = source;
    int saved_target = target;

    for (int i = 0; i < cols; ++i) {
        *target = *source;
        source += source_di;
        target += target_di;
    }

    source = saved_source + source_dj;
    target = saved_target + target_dj;
}
像素*源=原始;
像素*目标=新+(行-1)+(0*cols);
int source_di=1;
int source_dj=cols;
int target_di=行;
int target_dj=-1;
对于(int j=0;j
我建议您在方格纸上画一个简单的矩形,并用唯一的数字填充矩形中的正方形。然后你“旋转”这个矩形。这样你会看到它实际上非常简单。对,我已经做了,我知道了旋转是如何工作的。我的问题不是旋转它,而是如何旋转几次。我必须为每次迭代创建新指针,但我不确定如何多次创建新指针,如果我想实现270度旋转,我必须为原始指针和新指针创建新指针。这是一样的。例如,旋转180度实际上比旋转90度更简单。对于270度旋转,做180度和90度旋转。你只需要两个“指针”,源位图和目标位图,它们都是同样大的(除了90度和270度的宽度和高度切换)。我想我只是不明白,我不知道如何在一次坐姿中旋转几次,因为我会有原始bmp,输出bmp,内存中有两个不同的位置。我必须再次应用旋转,但我不能从原始图像进行旋转,我必须从输出进行旋转,否则它只会再次旋转原始图像。所以我需要内存中的第三个位置来存储新的输出,然后将已经转换的图像再次旋转到新的输出中。我有原始文件,90度的输出和下一个输出。下面继续…是的,我可以通过将90和180的旋转相加来完成所有旋转,但是我仍然需要我在内存中的第三个位置。我真的看不出有什么其他的方法可以解决这个问题,而且我觉得这样做效率很低。
PIXEL *source = original;
PIXEL *target = new + (rows - 1) + (0 * cols);

int source_di = 1;
int source_dj = cols;

int target_di = rows;
int target_dj = -1;

for (int j = 0; j < rows; ++j) {
    int saved_source = source;
    int saved_target = target;

    for (int i = 0; i < cols; ++i) {
        *target = *source;
        source += source_di;
        target += target_di;
    }

    source = saved_source + source_dj;
    target = saved_target + target_dj;
}