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

时间:2013-10-20 19:21:24

标签: 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;
        }

其中:原始=原始bmp,new =比例大小的新bmp取决于我想要应用的旋转量。两者都是指向bmp的指针,而new是指向指针的指针。 我已经做了好几次数学运算并逆时针旋转它应该顺时针旋转它。这是一个问题,但我想我可以逆时针旋转它足够的时间使其外观顺时针旋转。我的问题是:我如何从原始的bmp图像中多次进行旋转,并将其放在我正在创建的新bmp图像上。 也就是说,我怎样才能多次执行上述操作,并且仍然只有1个输入和1个正确大小的输出文件。 我想用指针做这个,因为它会让我更容易在其他程序中操作输出。 我希望这足够详细。

谢谢。

3 个答案:

答案 0 :(得分:0)

使用矩阵。伪代码:

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 and y = y - image.height/2

http://en.wikipedia.org/wiki/Rotation_matrix#Common_rotations

答案 1 :(得分:0)

下面的代码演示了浮点数组旋转90度的倍数。我后来将float数组转换为字节数组,这样我就可以生成测试图像来验证结果;我没有包含代码的那一部分,因为它只是混淆了主要观点,并不是你真正要求的。如果你需要那个部分,请告诉我我会发布它。

请注意,我进行了“不合时宜”的轮换,而不是“就地”。我相信后者是你真正感兴趣的,但即便如此,下面的方法应该是一个良好的开端。关于就地转换的其他讨论可以是found here,它以转置类型操作(内存交换)的使用为中心,但我没有时间对所有这些细节进行分类,我留下了部分适合你。

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

enter image description here

当然那么:

enter image description here

但是在实际代码中,您需要分别按行imageHeight / 2和imageWidth / 2翻译row'和col',如下面的代码所示,以避免将负索引传递给数组。

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

// 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 ...

请注意,在上面的代码中,我使用旋转坐标来访问原始数组的元素,然后将这些值映射回原始行col坐标:

dataVector2[row*nX + col] = dataVector[row_p*nX + col_p]; 

结果是+ n值给出顺时针旋转;如果你想要逆时针旋转,只需将n的负值,即-n,传递给你的代码,如上例所示。这样做的结果就是改变上面旋转矩阵的非对角线项的符号。

希望这有帮助。

答案 2 :(得分:0)

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

原始基地:

  • x0 = 0
  • y0 = 0
  • dx = 1
  • dy = cols

新基地

  • x0 = rows - 1
  • y0 = 0
  • dx = rows
  • 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;
}