【问题标题】:Is there a way to reverse the order of an array in C++?有没有办法在 C++ 中反转数组的顺序?
【发布时间】:2015-03-04 22:02:17
【问题描述】:

我正在制作一个小型照片程序,它采用 .ppm 文件,然后应用过滤器,例如否定红色、绿色、蓝色、水平翻转和灰度(用户选择要应用的过滤器)。除了水平翻转有困难之外,我想通了一切。我认为没有必要发布整个程序,因为我只是在制作一项功能时遇到困难。但是,如果需要,请告诉我,然后我会发布。

以下是否定红色、绿色和蓝色的示例函数。

void negate_red(int image[], int w, int h)
{
    for(int i = 0; i<h; i++)
        for(int j=0; j<w; j++)
    {
        image[(i*w+j)*3] = 255 - image[(i*w+j)*3];
    }
}

void negate_green(int image[], int w, int h)
{
    for(int i = 0; i<h; i++)
        for(int j=0; j<w; j++)
    {
        image[(i*w+j)*3+1] = 255 - image[(i*w+j)*3+1];
    }
}

void negate_blue(int image[], int w, int h)
{
    for(int i = 0; i<h; i++)
        for(int j=0; j<w; j++)
    {
        image[(i*w+j)*3+2] = 255 - image[(i*w+j)*3+2];
    }
}

据我了解,为了水平翻转图像,您必须颠倒数组的顺序。例如,第一个 RGB 值将是最后一个,对吗?有没有办法颠倒数组的顺序?在我问这个问题之前我做了一些搜索,我发现了这个: Correct flip/mirror of pixels of an image?

所以如果我解释正确,我应该像这样启动函数:

void flip (int image[], int w, int h)
{
for(int i = 0; i<h/2; i++)
     for(int j=0; j<w/2; j++)
  {
  //code
  }
}

现在有没有办法颠倒数组的顺序,让它从最后一个元素开始,到第一个?

感谢您的帮助,非常感谢!谢谢!

【问题讨论】:

  • 是的,有办法。
  • @Almo Epic 答案。只是史诗。
  • 我需要在这里澄清一下。你是如何阅读图像的?您是否一次读取 4 个字节,将单个 RGB 三元组读取为一个整数?还是您将 R 读入一个 int,将 G 读入下一个 int 并将 B 读入最后一个 int

标签: c++


【解决方案1】:

您需要遍历图像左侧的每个像素,并将其与右侧的相应像素翻转。这意味着您需要查看整幅图像中的每一行,但只能走到一半。

void swap_int (int *a, int *b)
{
    int temp = *b;
    *b = *a;
    *a = temp;
}

void h_flip (int image[], int w, int h)
{
    for(int i = 0; i<h; i++) // every row
         for(int j=0; j<w/2; j+=3) // halfway through the row
      {
          // We now swap this pixel (i,j) with its mirror pixel
          // on the right (i,w-j), swapping red, green, and blue values
          swap_int (&image [(i*w + j) * 3 + 0], &image [(i*w + (w-j)) * 3 + 0]);
          swap_int (&image [(i*w + j) * 3 + 1], &image [(i*w + (w-j)) * 3 + 1]);
          swap_int (&image [(i*w + j) * 3 + 2], &image [(i*w + (w-j)) * 3 + 2]);
      }
}

【讨论】:

  • 这是唯一一个似乎意识到图像是 2D 而不是 1D 的答案。
  • @DavidSchwartz 但是如果你这样做,你并没有交换像素!您只是在修改图像的左半部分。右半部分将保持不变。基本上,如果原始行类似于abcd,那么您想要的是dcba。您的代码将给出dccd。换句话说,您正在做的是镜像右半部分,而不是翻转整个图片。
【解决方案2】:

我会从&lt;algorithm&gt; 推荐std::reverse()。您可以通过使用(arr, arr+size) 调用它来将数组传递给它。它将反转数组。

为了解决下面的讨论:虽然用普通 C 以外的语言将 RGB 值表示为 3 个独立的整数有点奇怪,但这对于 OP 来说应该不是问题:确保数组的大小是3 的倍数,定义这样的结构:

struct rgb_value {
    int red;
    int green;
    int blue;
};

然后将数组转换为 struct rgb_value,并使用 (cast_array, cast_array + original_size/3) 调用反向。这样结构内部的顺序将保持不变。

我有点不喜欢自己做这样的转换的想法,但替代方法是编写一个自己的反向函数,它执行交换维护 rgb 顺序,或将数据复制到数据结构,其中rgb 值是这样表示并正确交换的。

编辑 2:首先我想指出,这不是“如何水平翻转图像?”的答案,而是“有没有办法在 C++ 中反转数组的顺序” ?”。因此我尽量避免OP的图像翻转算法是否正确的问题,以保持话题。

其次,即使假设 OP 的算法最初是错误的,反向算法也是首选算法。其他解决方案所暗示的只不过是一种相当复杂的说法:

rgb_color *pos = reinterpret_cast<rbg_color *>(image);
for (int i = 0; i < num_rows; ++i){
    pos += i * rgb_per_row //select row
    std::reverse(pos, pos + rgb_per_row);//reverse row
} 

rgb_per_row 是一行的长度除以sizeof(rgb_value)/sizeof(int)

【讨论】:

  • 每件事都有一个标准算法。
  • 这会反转 RGB 值,不是吗?
  • 它会颠倒数组中项目的顺序。它不会反转存储在数组中的值的字节顺序。第一项将成为最后一项,最后一项将成为第一项。
  • @BenKey 对。这是有道理的,因为 RGB 三元组将占用一个 int 的空间。出于某种原因,我在想char。但是反转一维阵列不会沿一个轴镜像图像。它会在两者之间翻转吗?
  • @BenKey:eigenchris 是对的。如果您查看 Aaron 的代码,您会看到每个 RGB 值都存储在 int 中,而图像是 ints 的数组。因此,如果您反转对应于一条线的数组,您不仅会水平翻转图片,还会交换颜色。 R1G1B1_R2G2B2,一旦恢复,将给出 B2G2R2_B1G1R1,但你想要的是 R2G2B2_R1G1B1。红色和蓝色将被交换,而绿色部分是正确的。
【解决方案3】:
Iterative way:
1) Initialize start and end indexes. 
start = 0, end = n-1
2) In a loop, swap arr[start] with arr[end] and change start and end as follows.
start = start +1; end = end – 1

/* Function to reverse arr[] from start to end*/
void reverseArray(int arr[], int start, int end)
{
  int temp;
  while(start < end)
  {
    temp = arr[start];   
    arr[start] = arr[end];
    arr[end] = temp;
    start++;
    end--;
  }   
}    

尝试将此解决方案应用于您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-24
    • 2021-03-30
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2020-01-11
    • 2019-11-20
    相关资源
    最近更新 更多