2010-07-13 20 views
0

J'ai une petite fonction qui va recolorer les pixels dans un bitmap d'une couleur donnée à une nouvelle couleur donnée.Remplacer le dégradé de couleurs dans l'image transparente

Les problèmes que j'ai avec le code sont les suivantes:

1) La fonction donne des résultats qui sont REMAPPAGE pixels blancs qui ne devrait pas être concidered depuis que je suis un seuil ... (à moins d'avoir défini cette mauvais calcul)

2) Lorsque certaines couleurs sont données par exemple LIMEGREEN résultats de wierd sont vus dans l'image renvoyée par la fonction (je beleive cela est dû à un débordement du type d'octet dans le cas d'addition ou soustraction)

L'image de base que je me sers se trouve ici:

http://www.freeimagehosting.net/uploads/c8745a9de1.png

Résultats J'ai obtenu peuvent être trouvés ici:

freeimagehosting.net/uploads/fa48e5a0eb.png (appelé avec Color.Magenta comme remapColor, Color.Red comme newColor, on dirait que les pixels blancs sont effectués et la la fin du dégradé n'est pas colorée correctement)

freeimagehosting.net/uploads/8faec6a569.png (appelé avec Color.Magenta comme remapColor, Color.Yellow comme newColor, apparaît comme les pixels blancs sont effectués et la fin du gradient ne sont pas correctement colorés)

freeimagehosting. net/uploads/2efd4c04aa.png (appelé avec Color.Magenta comme remapColor, Color.Blue comme newColor, semble gradient colorés correctement)

freeimagehosting.net/uploads/defdf04e16.png (appelé avec Color.Magenta comme remapColor , Color.Teal comme newColor, Apparaît que les pixels blancs sont appliqués et que le dégradé n'est pas calculé correctement)

La fonction que j'ai pour ce code est ci-dessous: par suggestions À JOUR

public unsafe static Bitmap RecolorImage(Bitmap original, Color remapColor, Color newColor) 
    { 
     Bitmap result = new Bitmap(original.Width, original.Height); 

     //lock the original bitmap in memory 
     BitmapData originalData = original.LockBits(
      new Rectangle(0, 0, original.Width, original.Height), 
      ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

     //lock the new bitmap in memory 
     BitmapData newData = result.LockBits(
      new Rectangle(0, 0, original.Width, original.Height), 
      ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 

     //set the number of bytes per pixel 
     int pixelSize = 4; 

     int rthreshold = 128; 
     int gthreshold = 128; 
     int bthreshold = 128; 

     for (int y = 0; y < original.Height; y++) 
     { 
      //get the data from the original image 
      byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride); 

      //get the data from the new image 
      byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride); 

      for (int x = 0; x < original.Width; x++) 
      { 
       //examine the rgb values 
       byte r = (byte)((oRow[x * pixelSize])); 
       byte g = (byte)((oRow[x * pixelSize + 1])); 
       byte b = (byte)((oRow[x * pixelSize + 2])); 
       byte a = (byte)((oRow[x * pixelSize + 3])); 

       if (a > 0 && 
        Math.Abs(remapColor.R - r) <= rthreshold && 
        Math.Abs(remapColor.B - b) <= bthreshold && 
        Math.Abs(remapColor.G - g) <= gthreshold 
        ) 
       { 
        if (newColor.R == 0) 
        { 
         r = 0; 
        } 
        else 
        { 
         if (newColor.R > remapColor.R) 
          r = (byte)(r - newColor.R); 
         else 
          r = (byte)(r + newColor.R); 
        } 

        if (newColor.G == 0) 
        { 
         g = 0; 
        } 
        else 
        { 
         if (newColor.G > remapColor.G) 
          g = (byte)(g - newColor.G); 
         else 
          g = (byte)(g + newColor.G); 
        } 

        if (newColor.B == 0) 
        { 
         b = 0; 
        } 
        else 
        { 
         if (newColor.B > remapColor.B) 
          b = (byte)(b - newColor.B); 
         else 
          b = (byte)(b + newColor.B); 
        } 
       } 


       //set the new image's pixel remaped pixel color 
       nRow[x * pixelSize] = b; //B 
       nRow[x * pixelSize + 1] = g; //G 
       nRow[x * pixelSize + 2] = r; //R 
       nRow[x * pixelSize + 3] = a; //A 
      } 
     } 

     original.UnlockBits(originalData); 
     result.UnlockBits(newData); 


     return result; 
    }   

Ce qui donne ....

Est-ce que je suis en train de faire possible?

Est-ce fiable?

Y a-t-il un bogue dans mon code? Y a-t-il une meilleure façon de réaliser cette "technique re-mapable" sur les bitmaps utilisant des gradients?

Nous vous remercions de votre temps.

Répondre

0

J'ai décidé que cela serait possible si j'étudiais les différents matériaux concernant les espaces colorimétriques et leurs théories de support. Il semble que cela prendra un peu plus que quelques calculs de seuil rapide et normalisation à la RemapColor.

Je vais proposer au lieu d'effectuer ce type de modification sur une image bitmap raster que les graphiques soient modifiés dans leur forme vectorielle.

Le processus devrait être quelque chose comme ceci:.

Les graphiques sont créés dans tout le concepteur imagerie la suite travaille dans

Ils sont enregistrés dans un format vectoriel par exemple SVG ceci permettra aux chemins personnalisables d'être nommés, traversés et modifiés par programmation (et pour plus que la couleur si nécessaire) avec le moteur de rendu SVG (http://svg.codeplex.com/)

Avec cette solution, nous pouvons soit envoyer le SVG directement au navigateur si supporté et effectuez les modifications directement sur le client ou utilisez le serveur et affichez le fichier au format PNG si nécessaire. Je pense que cet arrangement nous donnera plus de flexibilité et une solution plus robuste que ce que j'allais initialement hacker ensemble.

Merci les gars pour votre temps!

+0

J'aurais pu aussi modifier un ensemble de couleurs connues dans la palette Bitmap qui aurait affecté l'image globale et serait plus rapide que de définir chaque pixel dans le bitmap! Et nous avons finalement fini par utiliser du XAML ordinaire. Illustrator peut exporter XAML avec un plugin et ainsi nous pourrions éditer les graphiques après avoir été sauvé avec le plugin à la volée! – Jay

0

Il semble que votre test de seuil soit incorrect. Prenez la ligne:

remapColor.R - r <= rthreshold 

Si le pixel courant est blanc, alors r seront 255, et le test sera toujours vrai, peu importe ce que remapColor.R et rthreshold sont. Je pense que Math.Abs(remapColor.R - r) pourrait fonctionner.

Et vous avez probablement raison à propos de vos valeurs d'octets étant hors limites. La fixation du test de seuil pourrait empêcher cela. Sinon, essayez de placer des limites pour voir où cela se passe.

+0

Hey, Merci pour les conseils mais il semble que cela n'a pas fonctionné comme prévu. Voici la sortie du code après avoir apporté les modifications suggérées. http://www.freeimagehosting.net/uploads/d5ea228622.png Appelée avec Color.Magenta comme remapColor et Color.Red comme newColor Vais-je sur ce dans le mauvais sens? – Jay