我试图创建一个图像文件,如下所示:

uint8_t raw_r[pixel_width][pixel_height];
uint8_t raw_g[pixel_width][pixel_height];
uint8_t raw_b[pixel_width][pixel_height];
uint8_t blue(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x+y)%rand() : ((x*y%1024)%rand())%2 ? (x-y)%rand() : rand();
}
uint8_t green(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x-y)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}
uint8_t red(uint32_t x, uint32_t y)
{
    return (rand()%2)? (y-x)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}

for (y=0; y<pixel_height; ++y)
{
    for (x=0; x<pixel_width; ++x)
    {
        raw_b[x][y]=blue(x, y);
        raw_g[x][y]=green(x, y);
        raw_r[x][y]=red(x, y);
    }
}

我希望得到一些随机的东西(白噪音).但是,输出很有趣:

你知道原因吗?


Edit

现在,很明显,这与rand()无关.

还可以try 以下代码:

for (x=0; x<pixel_width; ++x)
    for (y=0; y<pixel_height; ++y)
    {
        r[x][y] = (x+y);
        g[x][y] = (y-x);
        /* b[x][y] = rand()%2? x : y; */
    }

推荐答案

起初,我会得到和其他人一样的答案,并将此归结为rand()个问题.然而,我想这样做更好,而是分析了您的数学计算实际产生的分布.

TL;DR:您看到的模式与底层的随机数生成器无关,而只是由于您的程序处理数字的方式所致.

我将继续使用你的蓝色函数,因为它们都是相似的.

uint8_t blue(uint32_t x, uint32_t y) {
    return (rand() % 2)                  ? (x + y) % rand() :
           ((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
                                           rand();
}

每个像素值从三个函数中 Select :(x + y) % rand()个、(x - y) % rand()个和rand()

让我们来看看每一张照片.

  • rand()

这就是你所期待的,只是噪音.将此称为"图像C"

enter image description here


  • (x + y) % rand()

这里你要把像素坐标加在一起,然后用一个随机数除以余数.如果图像为1024x1024,则总和在[0-2046]范围内.你所使用的随机数在[0,RAND_MAX]范围内,RAND_MAX至少是32k,在某些系统上是20亿.换言之,剩下的不只是(x + y)人,最多有16分之一的可能性.所以在大多数情况下,这个函数只会产生一个向+x+y方向增加蓝色的梯度.

然而,你只使用最低的8位,因为你返回uint8_t,所以你将有256像素宽的渐变条纹.

把这叫做"图像A"

enter image description here


  • (x - y) % rand()

在这里,您可以做一些类似的操作,但是使用了减法.只要x大于y,你就会得到类似于上图的东西.但在y较大的地方,结果是一个非常大的数字,因为xy是无符号的(负结果环绕到无符号类型范围的顶部),然后% rand()开始工作,实际上会得到噪声.

称之为"图像B"

enter image description here

最终图像中的每个像素都是使用函数rand() % 2((x * y % rand()4) % rand()) % 2从这三幅图像中的一幅中获取的.第一个可以理解为以50%的概率 Select (忽略rand()及其低阶位的问题)

这是rand() % 2为真(白色像素)的特写,因此 Select 了图像A.

enter image description here

第二个函数((x * y % (x * y % 1024)4) % rand()) % 2同样存在这样一个问题:rand()通常大于你要除以的(x * y % 1024),也就是最多(x * y % 1024)3.那么(x*y%1024)%2产生0和1的频率就不一样了.任何奇数乘以任何偶数都是偶数.任何偶数乘以任何偶数也是偶数.只有奇数乘以奇数才是奇数,因此,在四分之三时间为偶数的值上,%2将在四分之三时间内产生0.

这里是((x * y % 1024) % rand()) % 2为真的特写,这样就可以 Select 图像B.它精确地 Select 两个坐标都是奇数的位置.

enter image description here

下面是可以 Select 图像C的特写:

enter image description here

最后结合以下条件 Select 图像B:

enter image description here

Select 图像C时:

enter image description here

由此产生的组合可以理解为:

以50%的概率使用图像A中的像素.剩下的时间在图像B和图像C之间 Select ,其中两个坐标都是奇数,其中一个是偶数.

最后,因为你对三种不同的 colored颜色 做了相同的处理,但方向不同,所以每种 colored颜色 的图案方向不同,并产生你看到的交叉条或网格图案.

C++相关问答推荐

为什么这个select()会阻止?

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

使用GOTO从多个嵌套循环C继续

如何使fputs功能提示错误输入并要求用户重新输入.程序停止而不是请求新的输入

是否所有C编译器在将浮点数转换为整型数时都会隐式删除小数?

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

为什么GDB/MI进程的FIFO循环中有read()阻塞

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

实现简单字典时C语言中的段错误

如何有效地编写代码来判断两个元素数量相同的数组即使在不同的位置也具有相同的元素?

为什么指针运算会产生错误的结果?

如何仅使用软件重新初始化STM32微控制器中的USB枚举?

为什么realloc函数在此代码中修改变量?

这段代码用于在C中以相反的顺序打印数组,但它不起作用

用C++构建和使用DLL的困惑

使用C++中的字符串初始化 struct 时,从‘char*’初始化‘char’使指针变为整数,而不进行强制转换

生成的头文件不包括用户定义的文件

在C中打印指针本身

从文件到链表读取日期

当另一个指向 const 的指针观察到数据时,通过指针更改数据是否安全?