Création d’un dégradé linéaire dans un tableau 2D

J’ai un tableau de type bitmap 2D de 500 * 500 valeurs, par exemple. J’essaie de créer un dégradé linéaire sur le tableau afin que le bitmap résultant ressemble à ceci (en niveaux de gris): Exemple de dégradé http://soffr.miximages.com/algorithm/gradient_12.jpg

L’entrée serait le tableau à remplir, deux points (comme le sharepoint départ et d’arrivée de l’outil Dégradé de Photoshop / GIMP) et la plage de valeurs à utiliser.

Mon meilleur résultat actuel est le suivant:

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

… qui est loin de ce que je voudrais réaliser. Cela ressemble plus à un dégradé radial.

Quel est le moyen le plus simple de créer un tel dégradé? Je vais l’implémenter en C ++, mais j’aimerais un algorithme général.

Dans votre exemple, il semble que vous ayez un dégradé radial. Voici mon explication mathématique impromptue pour les étapes dont vous aurez besoin. Désolé pour le calcul, les autres réponses sont meilleures en termes de mise en œuvre.

  1. Définissez une fonction linéaire (comme y = x + 1) avec le domaine (c’est-à-dire x) allant de la couleur avec laquelle vous voulez commencer à la couleur avec laquelle vous voulez terminer. Vous pouvez penser à cela en termes de plage comprise entre Ox0 et OxFFFFFF (pour la couleur 24 bits). Si vous voulez gérer des choses comme la luminosité, vous devrez faire quelques astuces avec la plage (c’est-à-dire la valeur y).
  2. Ensuite, vous devez mapper un vecteur sur la masortingce que vous avez, car cela définit la direction dans laquelle les couleurs vont changer. En outre, les valeurs de couleur définies par votre fonction linéaire seront atsortingbuées à chaque point du vecteur. Les points de début et de fin du vecteur définissent également les min et max du domaine en 1. Vous pouvez considérer le vecteur comme une ligne de votre dégradé.
  3. Pour chaque cellule de la masortingce, il est possible d’atsortingbuer aux couleurs une valeur du vecteur où une ligne perpendiculaire de la cellule coupe le vecteur. Voir le diagramme ci-dessous où c est la position de la cellule et. est le point d’intersection. Si vous prétendez que la couleur à. est rouge, alors c’est ce que vous assignerez à la cellule.
              |
              c
              |
              |
     Vect: ____.______________
              |
              |

C’est vraiment une question de maths, donc on peut se demander si elle «appartient» vraiment à Stack Overflow, mais vous devez quand même projeter les coordonnées de chaque sharepoint l’image sur l’axe de votre dégradé et utiliser cette Couleur.

Mathématiquement, ce que je veux dire, c’est:

  1. Disons que votre sharepoint départ est (x1, y1) et votre point final est (x2, y2)
  2. Calculer A = (x2 - x1) et B = (y2 - y1)
  3. Calculer C1 = A * x1 + B * y1 pour le sharepoint départ et C2 = A * x2 + B * y2 pour le point final ( C2 doit être supérieur à C1 )
  4. Pour chaque sharepoint l’image, calcule C = A * x + B * y
  5. Si C <= C1 , utilisez la couleur de départ; si C >= C2 , utilisez la couleur de fin; sinon, utilisez une moyenne pondérée:

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

J'ai fait quelques tests rapides pour vérifier que cela fonctionnait fondamentalement.

Je vais juste poster ma solution.

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

Pour les accélérations, mettez en cache les valeurs de "direction" dérivées (indice: prémultiplier par le mag).

Ce problème comporte deux parties.

  1. Étant donné deux couleurs A et B et un certain pourcentage p, déterminez quelle couleur se trouve p ‘pour cent du chemin’ de A à B.

  2. À partir d’un point d’un plan, trouvez la projection orthogonale de ce point sur une ligne donnée.

La ligne donnée dans la partie 2 est votre ligne de dégradé. Pour tout point P, projetez-le sur la ligne de dégradé. Supposons que sa projection est R. Ensuite, déterminez la distance entre R et le sharepoint départ de votre segment de dégradé, sous forme de pourcentage de la longueur du segment de dégradé. Utilisez ce pourcentage dans votre fonction à partir de la partie 1 ci-dessus. C’est la couleur que P devrait être.

Notez que, contrairement à ce que d’autres personnes ont dit, vous ne pouvez pas simplement voir vos couleurs comme des nombres normaux dans votre fonction à partir de la partie 1. Cela ne fera presque certainement pas ce que vous voulez. Ce que vous faites dépend de l’espace colorimésortingque que vous utilisez. Si vous souhaitez un dégradé RVB, vous devez examiner séparément les composants de couleur rouge, vert et bleu.

Par exemple, si vous voulez une couleur “à mi-chemin entre” le rouge et le bleu purs, alors vous utilisez la notation hexadécimale.

ff 00 00

et

00 00 ff

Probablement la couleur que vous voulez est quelque chose comme

80 00 80

qui est une belle couleur pourpre. Vous devez établir une moyenne pour chaque composante de couleur séparément. Si vous essayez juste de faire la moyenne des nombres hexadécimaux 0xff0000 et 0x0000ff directement, vous obtenez 0x7F807F, qui est un gris moyen. Je suppose que cela explique au moins une partie du problème de votre photo ci-dessus.

Si vous êtes dans l’espace colorimésortingque HSV, vous pouvez également ajuster le composant de teinte uniquement et laisser les autres tels quels.