Ответ 1
Первоначально у меня был такой же ответ, как и у всех остальных, и помешал ему проблемы с 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();
}
Каждое значение пикселя выбирается из одной из трех функций: (x + y) % rand()
, (x - y) % rand()
и rand()
;
Посмотрите на изображения, созданные каждым из них.
-
rand()
Это то, чего вы ожидаете, просто шум. Назовите это "Image C"
-
(x + y) % rand()
Здесь вы добавляете координаты пикселя вместе и отделяете остаток от случайного числа. Если изображение равно 1024x1024, тогда сумма находится в диапазоне [0-2046]. Случайное число, которое вы ныряете, находится в диапазоне [0, RAND_MAX], где RAND_MAX составляет не менее 32 тыс., А на некоторых системах - 2 млрд. Другими словами, в лучшем случае вероятность 1 из 16 заключается в том, что остаток не просто (x + y)
. Таким образом, по большей части эта функция будет генерировать только градиент синего цвета в направлении +x + y.
Однако вы используете только самые младшие 8 бит, потому что вы возвращаете uint8_t
, поэтому у вас будут полосы градиентов шириной 256 пикселей.
Назовите это "Изображение A"
-
(x - y) % rand()
Здесь вы делаете что-то подобное, но с вычитанием. Пока x больше y, вы будете иметь что-то похожее на предыдущее изображение. Но где y больше, результат - очень большое число, потому что x
и y
без знака (отрицательные результаты округляются до вершины диапазона без знака), а затем появляется % rand()
и вы действительно получаете шум.
Назовите это "Изображение B"
Каждый пиксель в конечном изображении берется из одного из этих трех изображений, используя функции rand() % 2
и ((x * y % 1024) % rand()) % 2
. Первый из них можно считать выбором с вероятностью 50% (игнорируя проблемы с rand()
и битами младшего порядка).
Здесь крупным планом, где rand() % 2
истинно (белые пиксели), так что выбрано изображение A.
Вторая функция ((x * y % 1024) % rand()) % 2
снова имеет проблему, где rand()
обычно больше, чем вещь, которую вы делите, (x * y % 1024)
, которая не более 1023. Тогда (x*y%1024)%2
не производит 0 и 1 одинаково часто. Любое нечетное число, умноженное на любое четное число, является четным. Любое четное число, умноженное на любое четное число, также четное. Только нечетное число, умноженное на нечетное число, является нечетным, поэтому %2
при значениях, составляющих даже три четверти времени, будет производить 0 три четверти времени.
Здесь крупным планом, где ((x * y % 1024) % rand()) % 2
истинно, чтобы можно было выбрать изображение B. Он выбирает именно там, где обе координаты нечетны.
И здесь крупным планом, где можно выбрать Image C:
Наконец, комбинируя условия здесь, где выбрано изображение B:
И где выбрано изображение C:
Получившаяся комбинация может быть прочитана как:
При 50% вероятности используйте пиксель из изображения A. Остальное время выбирается между изображением B и изображением C, B, где обе координаты нечетны, C, где один из них четный.
Наконец, поскольку вы делаете то же самое для трех разных цветов, но с разными ориентациями, шаблоны ориентируются по-разному в каждом цвете и создают пересекающиеся полосы или сетку, которые вы видите.