los imprime impresora g3100 colores canon bien c image random

g3100 - impresora canon no imprime



¿Por qué obtengo este patrón de color en particular cuando uso rand()? (2)

Inicialmente iba a tener la misma respuesta que todos los demás y lo atribuía a los problemas con rand() . Sin embargo, pensé mejor en hacerlo y en su lugar analicé la distribución que tus matemáticas están produciendo.

TL; DR: El patrón que ves no tiene nada que ver con el generador de números aleatorios subyacente, sino que se debe simplemente a la forma en que tu programa está manipulando los números.

Me atendré a tu función azul ya que todas son similares.

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

Cada valor de píxel se selecciona de una de las tres funciones: (x + y) % rand() , (x - y) % rand() y rand() ;

Echemos un vistazo a las imágenes producidas por cada uno de estos solo.

  • rand()

Esto es lo que esperarías, solo ruido. Llama a esto "Imagen C"

  • (x + y) % rand()

Aquí está agregando las coordenadas de los píxeles y eliminando el resto de la división por un número aleatorio. Si la imagen es 1024x1024, la suma está en el rango [0-2046]. El número aleatorio por el que se está buceando está en el rango [0, RAND_MAX], donde RAND_MAX es de al menos 32k y en algunos sistemas es de 2 mil millones. En otras palabras, en el mejor de los casos, existe una probabilidad de 1 en 16 de que el resto no sea solo (x + y) . Así que, en su mayor parte, esta función solo producirá un gradiente de azul creciente hacia la dirección + x + y.

Sin embargo, solo está utilizando los 8 bits más bajos, porque devuelve un uint8_t , por lo que tendrá franjas de degradados de 256 píxeles de ancho.

Llama a esto "Imagen A"

  • (x - y) % rand()

Aquí haces algo parecido, pero con la resta. Siempre que x sea mayor que y tendrás algo similar a la imagen anterior. Pero donde y es mayor, el resultado es un número muy grande porque y están sin signo (los resultados negativos se ajustan a la parte superior del rango del tipo sin signo), y luego el % rand() activa y en realidad se escucha ruido.

Llama a esto "Imagen B"

Cada píxel de su imagen final se toma de una de estas tres imágenes usando las funciones rand() % 2 y ((x * y % 1024) % rand()) % 2 . El primero de estos se puede leer como elegir con un 50% de probabilidad (ignorando los problemas con rand() y sus bits de orden inferior).

Aquí hay un primer plano de donde rand() % 2 es verdadero (píxeles blancos), por lo que la Imagen A está seleccionada.

La segunda función ((x * y % 1024) % rand()) % 2 nuevamente tiene el problema de que rand() suele ser mayor que lo que estás dividiendo, (x * y % 1024) , que es como máximo 1023 . Entonces (x*y%1024)%2 no produce 0 y 1 con la misma frecuencia. Cualquier número impar multiplicado por cualquier número par es par. Cualquier número par multiplicado por cualquier número par también es par. Sólo un número impar multiplicado por un número impar es impar, por lo que %2 en valores que son incluso tres cuartos del tiempo producirá 0 tres cuartos del tiempo.

Aquí hay un primer plano de donde ((x * y % 1024) % rand()) % 2 es verdadero para que la Imagen B pueda ser seleccionada. Se está seleccionando exactamente donde ambas coordenadas son impares.

Y aquí hay un primer plano de donde se puede seleccionar la Imagen C:

Finalmente combinando las condiciones aquí es donde se selecciona la Imagen B:

Y donde se selecciona la Imagen C:

La combinación resultante se puede leer como:

Con un 50% de probabilidad, use el píxel de la Imagen A. El resto de la selección de tiempo entre la Imagen B y la Imagen C, B donde ambas coordenadas son impares, C donde cualquiera de las dos es par.

Finalmente, ya que estás haciendo lo mismo con tres colores diferentes, pero con diferentes orientaciones, los patrones están orientados de manera diferente en cada color y producen las tiras cruzadas o el patrón de cuadrícula que estás viendo.

Intenté crear un archivo de imagen, como este:

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); } }

Esperaba conseguir algo al azar (ruido blanco). Sin embargo, la salida es interesante:

¿Sabes por qué?

Editar

Ahora, está claro que no tiene nada que ver con rand() .

Prueba también este código:

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; */ }


Muchos de los cálculos que estás haciendo en tu código no llevarán a valores verdaderamente aleatorios. Esas líneas nítidas que estás viendo corresponden a lugares donde los valores relativos de tus coordenadas x e y se intercambian entre sí, y cuando eso sucede, estás utilizando fórmulas fundamentalmente diferentes. Por ejemplo, computar (x + y) % rand() generalmente le devolverá el valor x + y , ya que rand() (generalmente) devolverá un número mucho más grande que x + y dado que RAND_MAX es generalmente bastante gran número. En ese sentido, no debe esperar recuperar el ruido blanco, ya que el algoritmo que está utilizando para generar cosas está desviado de generar ruido blanco. Si desea ruido blanco, simplemente configure cada píxel en rand() . Si deseas un buen patrón como el que tienes arriba, pero con un poco de aleatoriedad lanzada aquí y allá, sigue usando el código que has escrito.

Además, como @ pm100 ha notado en los comentarios, la función rand no devuelve números verdaderamente aleatorios, y en su lugar utiliza una función pseudoaleatoria para producir sus valores. La implementación predeterminada de rand en muchos sistemas utiliza un tipo de generador de números pseudoaleatorios denominado generador lineal congruente que produce números que, en ráfagas cortas, pueden parecer aleatorios, pero que en la práctica son decididamente no aleatorios. Por ejemplo, aquí hay una animación de Wikipedia que muestra cómo los puntos aleatorios en el espacio elegido con un generador lineal congruente terminan cayendo en un número fijo de hiperplanos:

Si reemplaza las coordenadas x, y y z con las coordenadas R, G y B, esto se ve muy similar a la salida producida por su programa. Sospecho que este no es probablemente el problema central aquí, ya que el otro aspecto mencionado anteriormente probablemente será mucho más pronunciado.

Si está buscando números aleatorios de mayor calidad, necesitará usar una fuente aleatoria de mayor calidad. En C, podría considerar leer bytes de /dev/urandom/ (en un sistema similar a Linux), lo que da valores aleatorios bastante uniformes. C ++ ahora tiene una serie de buenas primitivas de generación de números aleatorios en sus bibliotecas estándar, si está disponible para usted.