2009-02-06 19 views
5

Tengo una matriz bidimensional similar a un mapa de bits, digamos 500 * 500 valores. Estoy intentando crear un gradiente lineal en la matriz, por lo que el mapa de bits resultante sería algo como esto (en escala de grises): Example gradient http://showandtell-graphics.com/images/gradient/gradient_12.jpgCrear un degradado lineal en matriz 2D

La entrada sería la matriz de llenar, dos puntos (como el inicio y fin punto para la herramienta Degradado en Photoshop/GIMP) y el rango de valores que se usarían.

Mi mejor resultado actual es la siguiente:

alt text http://img222.imageshack.us/img222/1733/gradientfe3.png

... lo cual está muy lejos de lo que me gustaría lograr. Se parece más a un gradiente radial.

¿Cuál es la forma más sencilla de crear dicho degradado? Voy a implementarlo en C++, pero me gustaría algún algoritmo general.

Respuesta

3

En su imagen de ejemplo, parece que tiene un degradado radial. Aquí está mi explicación matemática imprompt para los pasos que necesitarás. Perdón por las matemáticas, las otras respuestas son mejores en términos de implementación.

  1. Defina una función lineal (como y = x + 1) con el dominio (es decir, x) del color con el que desea comenzar al color que desea finalizar. Puedes pensar en esto en términos de un rango dentro de Ox0 a OxFFFFFF (para color de 24 bits). Si desea manejar cosas como el brillo, tendrá que hacer algunos trucos con el rango (es decir, el valor y).
  2. A continuación, debe asignar un vector en la matriz que tiene, ya que esto define la dirección en la que cambiarán los colores. Además, los valores de color definidos por su función lineal se asignarán en cada punto a lo largo del vector. El punto inicial y final del vector también define el mínimo y el máximo del dominio en 1. Puedes pensar en el vector como una línea de tu gradiente.
  3. Para cada celda de la matriz, a los colores se les puede asignar un valor del vector donde una línea perpendicular de la celda interseca el vector. Vea el diagrama a continuación donde c es la posición de la celda y. es el punto de intersección. Si finges que el color en. es rojo, entonces eso es lo que asignarás a la celda.
 
      | 
      c 
      | 
      | 
    Vect:____.______________ 
      | 
      | 

+0

Estaba pensando en algo parecido, pero esperaba encontrar alguna solución más simple. Me llevó una hora y media derivar la fórmula correcta para calcular el punto correcto en la línea A-> B :) –

+0

Lo bueno, si tienes la oportunidad, publícalo en tu pregunta. Estoy seguro de que alguien lo encontrará útil. –

14

Esto es realmente una cuestión matemática, por lo que podría ser discutible si realmente "pertenece" en Stack Overflow, pero de todos modos: debe proyectar las coordenadas de cada punto en la imagen en el eje de su gradiente y usar coordinar para determinar el color.

Matemáticamente, lo que quiero decir es:

  1. Digamos que su punto de partida es (x1, y1) y el punto final es (x2, y2)
  2. Calcular A = (x2 - x1) y B = (y2 - y1)
  3. Calcular C1 = A * x1 + B * y1 de el punto de partida y C2 = A * x2 + B * y2 para el punto final (C2 debe ser mayor que C1)
  4. Para cada punto en la imagen, calcule C = A * x + B * y
  5. Si C <= C1, utilice el color inicial; si es C >= C2, use el color final; de lo contrario, utilizar una media ponderada:

    (start_color * (C2 - C) + end_color * (C - C1))/(C2 - C1)

Hice algunas pruebas rápidas para comprobar que esto básicamente trabajó.

+3

+1, ¿qué es la programación si no se aplica la matemática? =) – Crashworks

+0

Tal vez soy estúpido, pero no pude hacer que funcione. Funcionó para gradientes horizontales y verticales, pero no hubo suerte para los angulados. +1 de todos modos. –

+0

Simplemente comprobé dos veces y en Mathematica funcionó perfectamente para todos los ángulos que probé, así que estoy bastante seguro de que la fórmula en sí es válida. ¿Qué problema tenías? –

1

Voy a publicar mi solución.

int ColourAt(int x, int y) 
{ 
    float imageX = (float)x/(float)BUFFER_WIDTH; 
    float imageY = (float)y/(float)BUFFER_WIDTH; 

    float xS = xStart/(float)BUFFER_WIDTH; 
    float yS = yStart/(float)BUFFER_WIDTH; 
    float xE = xEnd/(float)BUFFER_WIDTH; 
    float yE = yEnd/(float)BUFFER_WIDTH; 
    float xD = xE - xS; 
    float yD = yE - yS; 

    float mod = 1.0f/(xD * xD + yD * yD); 

    float gradPos = ((imageX - xS) * xD + (imageY - yS) * yD) * mod; 

    float mag = gradPos > 0 ? gradPos < 1.0f ? gradPos : 1.0f : 0.0f; 

    int colour = (int)(255 * mag); 
    colour |= (colour << 16) + (colour << 8); 
    return colour; 
} 

para UPS de velocidad, caché los valores derivados "dirección" (pista: premultiplicar por el MAG).

0

Este problema tiene dos partes.

  1. Dados dos colores A y B y un porcentaje p, determinar de qué color se encuentra p 'por ciento del camino' de A a B.

  2. Dado un punto en un plano, encontrar la proyección ortogonal de ese punto en una línea dada.

La línea dada en la parte 2 es su línea de degradado. Dado cualquier punto P, proyectarlo en la línea de gradiente. Digamos que su proyección es R. Luego, determine qué tan lejos está R desde el punto de partida de su segmento de gradiente, como un porcentaje de la longitud del segmento de gradiente. Use este porcentaje en su función de la parte 1 anterior. Ese es el color P debería ser.

Tenga en cuenta que, al contrario de lo que otras personas han dicho, no puede simplemente ver sus colores como números regulares en su función de la parte 1. Eso seguramente no hará lo que quiera. Lo que haga depende del espacio de color que esté usando. Si quieres un degradado RGB, entonces tienes que mirar los componentes de color rojo, verde y azul por separado.

Por ejemplo, si desea un color "a medio camino entre" puro rojo y azul, a continuación, en notación hexadecimal que se trata de

ff 00 00

y

00 00 ff

Probablemente el color que desea es algo así como

que es un bonito color morado. Debe promediar cada componente de color por separado. Si intenta promediar los números hexadecimales 0xff0000 y 0x0000ff directamente, obtendrá 0x7F807F, que es un gris medio. Supongo que esto explica al menos parte del problema con su imagen de arriba.

Alternativamente, si se encuentra en el espacio de color HSV, quizás desee ajustar el componente de matiz solamente, y dejar los otros como están.

+0

Estoy trabajando solo en escala de grises, lo que simplifica significativamente la combinación de colores. –

Cuestiones relacionadas