2017-08-04 107 views
2

我想了解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:我不是在编码天才:(

回答

3

油滑的代码看起来,他们在做指针运算

我会在顶部开始向下运行使用curve的。解释。我知道你只是问曲线,但我会解释其他的东西太多了清晰度。

gint *curve;

这会创建一个指向内存地址的指针,该地址足够容纳一个整数(类型为gint)。目前,它没有初始化,所以不是非常有帮助

curve = g_new (gint, n);

现在,创建一个整数数组(GINT)和曲线都被分配开始这个新的数组的地址。

length = n/2;

在这里它们被计算滤波器是大小n的中点。过滤器的大小基于l,它基于早先的西格玛参数和对数变换数学。这里,length指的是1D内核的半径,而不是数组长度的两倍。

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

你的问题:这到底是怎么回事?

这改变了可变curve,以便它现在到先前初始化,以便在后续的for循环索引是程序员考虑一下可能更容易在阵列的中间,有点吸尘器写入,调试等。

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

首先,curve指向曲线[0]的地址。事实并非如此,但是由于您说您是新手,因此我们假设曲线[0]位于内存地址00处。因此curve的值也等于地址00.呼叫curve += length可解释为curve = curve + length,其内部为添加将长度数据类型的大小(以字节为单位)写入曲线地址,然后更新曲线地址,结果为。例如起见,让我们说,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将被写入十六进制为0×20)

再次,用g_new(gint, n)声明的存储器仍然存在,其中它是声明(它不会移动),但现在,因为指针已更改,它(指针)可用于使用负指数索引到该数组中。也就是说,curve[0]实际上是数组中间的值,而curve[-n]是数组的第一个元素。

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

curve[0] = 255;

上迭代的后续从这里计算出(+/- i)至填在内核中。

然而,您可以在下一个循环中看到曲线值再次偏移到中心位置(即curve[i-length-1])。现在有点混乱,因为它看起来像是混合并匹配两种方法(有时使用指针算术使索引变得更清晰,然后有时不使用)。但是,嘿,他们编程它,并可能有这样做的一个很好的理由基于其他代码看起来如何。谁知道呢,也许他们只是想把各种东西混为一谈。

UPDATE

关于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];看起来像它可以仅仅是因为sum[-length]p_total = sum[length];总是被设置为0。是,sum[0]=0后面跟着sum += length表示sum[-length]之后的调整与sum[0]之前的指针调整相同。这两个参考都是数组中的第一个值,即0。

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

然而,在'sum'的情况下,调整是在数组初始化后进行的,而在curve的情况下,首先进行调整,然后初始化值。这可能只是程序员偏好混合的东西,可能更容易想到将从1到K的索引集成起来(可以这么说)。有可能还有其他的方法来编写这个代码,这是它的全部美好(或者,有时也许是诅咒)。

+0

你好informaton, 非常感谢您的详细解答。我得到了与曲线 点,但我不明白与“总和”。 “曲线”居中之前,则设置值(curve [i] = curve [-i] = temp)。 – kalonkadour

+0

“sum”在定义值后居中。那么,我想以sum [-1]为例得到什么呢? (让我们假设总和[1] = 4) 请您澄清一下吗?非常感谢你 ! – kalonkadour

+0

没错。我会更新我的答案,因为添加评论太长。 – informaton