Gimp高斯模糊 - 代码解释

时间:2017-08-04 01:28:24

标签: c blur gaussian gimp

我试图了解Gimp中的高斯模糊是如何工作的。我下载了代码,我可以几乎了解一些事情......但我对其他事情感到困惑。

以下是代码:

make_rle_curve (gdouble   sigma,
            gint    **p_curve,
            gint     *p_length,
            gint    **p_sum,
            gint     *p_total)
{
  const gdouble  sigma2 = 2 * sigma * sigma;
  const gdouble  l      = sqrt (-sigma2 * log (1.0 / 255.0));
  gint           temp;
  gint           i, n;
  gint           length;
  gint          *sum;
  gint          *curve;

   n = ceil (l) * 2;
   if ((n % 2) == 0)
    n += 1;

   curve = g_new (gint, n);

  length = n / 2;
  curve += length; /* 'center' the curve[] */
  curve[0] = 255;

  for (i = 1; i <= length; i++)
  {
      temp = (gint) (exp (- (i * i) / sigma2) * 255);
      curve[-i] = temp;
      curve[i] = temp;
   }

  sum   = g_new (gint, 2 * length + 1);
  sum[0] = 0;
  for (i = 1; i <= length*2; i++)
   {
      sum[i] = curve[i-length-1] + sum[i-1];
   }

  sum += length; /* 'center' the sum[] */

  *p_total  = sum[length] - sum[-length];
  *p_curve  = curve;
  *p_sum    = sum;
  *p_length = length;

对我来说,曲线和总和是2个数组。曲线从让我们说-3到+3

和总和从0到6.换句话说,我有

curve[-3] = ... 
curve[0] = 255
curve[3] = ...

curve = curve + length确实做了什么? 同样的事情,sum = sum + length做了什么?

非常感谢你的帮助!

ps:我不是编码的天才:(

1 个答案:

答案 0 :(得分:3)

光滑的代码。看起来他们正在做指针运算。

我将从顶部开始,然后使用curve进行解释。我知道你只是询问曲线,但为了清晰起见,我也会解释其他的东西。

  

gint *curve;

这会创建一个指向内存地址的指针,该地址足以容纳一个整数(类型为gint)。目前尚未初始化,因此不太有用

  

curve = g_new (gint, n);

现在,创建了一个整数数组(gint),并为该新数组的起始地址指定了曲线。

  

length = n / 2;

这里他们正在计算过滤器的中点,其大小为n。过滤器的大小基于l,它基于先前的sigma参数和对数变换数学。这里,length指的是1D内核的 radius ,而不是数组长度的两倍。

  

curve += length; /* 'center' the curve[] */

你的问题:这里发生了什么?

这会更改变量curve,使其现在指向到先前已初始化的数组的中间位置,以便程序员可以更轻松地进行循环索引的后续操作考虑一下,编写,调试等等更清洁。

此处,由于未使用[]运算符,因此对curve的引用是其在内存中的地址。分配的内存仍然存在,并且不会四处移动(确保您可以将它从一个地方复制到另一个地方,但这不是我所说的)。指针curve可以四处移动。 curve本身的地址被设置,但是,作为变量,它包含的地址可以被调整和更改,以便它指向不同的东西,就像任何其他的一样,非常量变量的值可以更改。

首先,curve指向曲线[0]的地址。事实并非如此,但由于你说你是新手,所以让曲线[0]在内存地址00处。所以curve的值也是相等的地址00.调用curve += length可以解释为curve = curve + length,其内部将长度数据类型的大小(以字节为单位)添加到曲线的地址,然后更新曲线&# 39;带有结果的地址。举例来说,让我们说gint需要4个字节而length是5,而curve仍然是00.

因此呼叫变为

  1. curve += length
  2. curve = curve + length
  3. curve = curve + sizeof(length)
  4. curve =地址曲线指向+字节长度使用内存
  5. curve =地址00 + 4字节* 8位/字节
  6. curve = Address 32(地址32将以十六进制写为0x20)
  7. 同样,用g_new(gint, n)声明的内存仍然存在,它被声明(它不会移动),但现在,因为指针被更改,它(指针)可用于索引使用负索引进入该数组。也就是说,curve[0]实际上是数组中间的值,而curve[-n]是数组的第一个元素。

    在过滤器中,中点(curve[0])直接设置为最大值:

      

    curve[0] = 255;

    后续迭代从这里开始计算(+/- i)以填充内核。

    然而,您可以在下一个for循环中看到曲线值再次偏移到中心向上(即curve[i-length-1])。它现在有点令人困惑,因为看起来它们混合并匹配这两种方法(有时使用指针算法使索引更清晰,有时不使用)。但是嘿,他们对它进行了编程,并且可能有充分的理由以这种方式进行,基于其余代码的外观。谁知道,也许他们只是想为了变化而混合起来。

    <强>更新

    关于sum,首先设置数组中的值,然后将指针更改为指向此填充数组的中心。但是,该程序可能遵循之前用curve看到的相同模式,并且写成如下:

    sum += length; /* 'center' the sum[] */
    
    sum[-length] = 0;
    for (i = -length+1; i <= length; i++)
    {
       sum[i] = curve[i] + sum[i-1];
    }
    

    另外,通话*p_total = sum[length] - sum[-length];看起来只有p_total = sum[length];,因为sum[-length]始终设为0.也就是说,sum[0]=0后跟{sum += length 1}}表示调整后的sum[-length]与指针调整前的sum[0]相同。两个引用都是数组中的第一个值,即0。

    sum指针放在数组的中间与函数结束时设置为数组中间的curve一致。

    在&#39; sum&#39;但是,在使用值初始化数组之后进行调整,而在curve的情况下,首先进行调整,然后初始化值。这可能只是程序员喜欢混合的东西,可能更容易想到与从1到K的索引集成(可以这么说)。可能还有其他方法可以编写这个代码同样有效的方法,这就是它的美妙之处(或者有时候,诅咒)。

相关问题