Silverlight : Remplissage de formes dans une image bitmap

Par Patrick Bélanger, vendredi 31 juillet 2009 22:18
Catégorie : Intégration / design  |  Programmation

Silverlight 3 nous permet maintenant de contrôler une image bitmap pixel par pixel.

 

Ainsi, nous avons cherché à écrire un algorithme de colorisation de région par remplissage (flood fill algorithm). Nos premières approches qui empruntaient à d’autres algorithmes du domaine de l’infographie n’ont pas été concluante. Bien que l’algorithme était rapide et précis, dans certains cas nous dépassions la pile d’appel (call stack) et des exceptions survenais.

 

Mais lorsque nous avons tenté d’implémenter par la technique de la queue, nous avons trouvé la solution !

 

La méthode principale à utiliser est celle-ci :

private void ColorizeRegion(WriteableBitmap bmp, int originalX, int originalY, Color newColor, bool antiAliasing, int threshold)
{
  Color oldColor = GetColorFromPixel(bmp, originalX, originalY);
  int rgb = GetRgbFromColor(newColor);
 
  int width = bmp.PixelWidth;
  int height = bmp.PixelHeight;
 
  // Set Q to the empty queue.
  Queue<PointI> q = new Queue<PointI>(2048);
 
  // Add starting node to Q.
  q.Enqueue(new PointI(originalX, originalY));
 
  // For each element n of Q:
  while (q.Count > 0)
  {
    PointI n = q.Dequeue();
 
    // If the color of n is equal to target-color
    if (IsSimilarColor(GetColorFromPixel(bmp, n.X, n.Y), oldColor, threshold))
    {
      // Set startX and endX equal to n
      int startX = n.X;
      int endX = n.X;
 
      // Move startX to the left until the color of the node to the left of startX no longer matches the old color.
      while (startX > 0 && IsSimilarColor(GetColorFromRgb(GetRgbFromPixel(bmp, startX - 1, n.Y)), oldColor, threshold))
      {
        --startX;
      }
 
      // Move endX to the right until the color of the node to the right of endX no longer matches the old color.
      while (endX < width - 1 && IsSimilarColor(GetColorFromRgb(GetRgbFromPixel(bmp, endX + 1, n.Y)), oldColor, threshold))
      {
        ++endX;
      }
 
      if (antiAliasing)
      {
        // Anti-aliasing is performed on the edges (left, right) of the current line
        if (startX - 1 >= 0)
        {
          Blend(bmp, startX - 1, n.Y, newColor);
        }
        if (endX + 1 < width)
        {
          Blend(bmp, endX + 1, n.Y, newColor);
        }
      }
 
      // For each node between startX and endX
      for (int x = startX; x <= endX; ++x)
      {
        // Set the color of nodes between w and e to replacement-color
        SetPixelRgb(bmp, x, n.Y, rgb);
 
        // If the color of the upper node of n is an old color, add that node to Q
        if (n.Y > 0 && IsSimilarColor(GetColorFromRgb(GetRgbFromPixel(bmp, x, n.Y - 1)), oldColor, threshold))
        {
          q.Enqueue(new PointI(x, n.Y - 1));
        }
        else
        {
          if (antiAliasing && n.Y - 1 >= 0)
          {
            // Anti-aliasing is performed on the line up of the current one if we are on a frontier one
            Blend(bmp, x, n.Y - 1, newColor);
          }
        }
 
        // If the color of the lower node of n is an old color, add that node to Q
        if (n.Y < height - 1 && IsSimilarColor(GetColorFromRgb(GetRgbFromPixel(bmp, x, n.Y + 1)), oldColor, threshold))
        {
          q.Enqueue(new PointI(x, n.Y + 1));
        }
        else
        {
          if (antiAliasing && n.Y + 1 < height)
          {
            // Anti-aliasing is performed on the line down of the current one if we are on a frontier one
            Blend(bmp, x, n.Y + 1, newColor);
          }
        }
      }
    }
  }
}

 

Et le résultat ressemble à ceci (cliquer dans la section de droit).

Impressionnant ce que Silverlight nous donne comme liberté. Et nous avons déjà trouvé plusieurs applications à cette petite librairie !

 

Alors pour votre plaisir, voici les sources :

Commentaires

mercredi 14 octobre 2009 06:24

Bueno!

 
 

Ajouter un commentaire

no avatar
Entrez votre nom, alias ou adresse de courriel.
Nous vous incarnerons à partir des services ici-bas.
 

(Affichera votre icône Gravatar)

  Country flag

biuquote
Loading