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