【问题标题】:How to rotate a bmp image in increments of 90 degrees in C?如何在 C 中以 90 度的增量旋转 bmp 图像?
【发布时间】:2013-10-29 04:34:06
【问题描述】:

我正在尝试编写这个在 C 中处理 bmp 图像的程序,到目前为止,我已经设法将其旋转:

 for (row=0; row < rows; row++)
      for (col=0; col < cols; col++) 
        {
          (*new) + rows*col + (rows - row -1) = original + row*cols + col;
        }

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

谢谢。

【问题讨论】:

  • 我建议你在方格纸上做一个简单的矩形,并用唯一的数字填充矩形中的正方形。然后你“旋转”那个矩形。这样你会发现其实很简单。
  • 对,我已经做到了,我了解了旋转的工作原理。我的问题实际上不是旋转它,而是如何多次旋转。我必须为每次迭代创建新指针,而且我不确定如何多次执行,如果我想实现,我必须多次为原始指针和新指针创建一个新指针,比如说, 270 度旋转。
  • 是一样的。例如,旋转 180 度实际上比旋转 90 度更简单。因此,对于 270 度旋转,执行 180 度和 90 度。您只需要两个“指针”,即源位图和目标位图,它们都将同样大(除了 90 度和 270 度的宽度和高度切换位置)。
  • 我想我只是不明白,我不知道如何在 1 次坐姿中进行多次旋转,因为我有原始 bmp,输出 bmp,这是 2 差异.内存中的位置。我必须再次应用旋转,但我不能从原始图像中执行此操作,我必须从输出中执行此操作,否则它只会再次旋转原始图像。因此,我需要内存中的第三个位置来存储新输出,然后将已经转换的图像再次旋转到新输出中。我有原始文件、90 度的输出和下一个输出。下面继续..
  • 是的,我可以通过将 90 和 180 的旋转相加来完成所有旋转,但是我仍然需要在内存中排名第三。我真的没有看到任何其他解决方法,并且有些事情告诉我这是低效的。

标签: c rotation


【解决方案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 and y = y - image.height/2

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

【讨论】:

    【解决方案2】:

    简化代码的一种方法是定义您将沿着循环行走的两个 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;
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

      那么当然:

      但在实际代码中,您需要将 row' 和 col' 分别转换为 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 ...
      

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

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

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

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2012-11-08
        • 1970-01-01
        • 1970-01-01
        • 2017-04-01
        • 1970-01-01
        • 2019-07-29
        • 1970-01-01
        • 1970-01-01
        • 2013-02-13
        相关资源
        最近更新 更多