2010-11-06 5 views
1
niveaux de gris

Actuellement quand je veux ajouter une couleur grise sur un Bitmap J'utilise les éléments suivantsL'utilisation de couleurs sur bitmap

Bitmap.SetPixel(x,y, new Color.FromArgb(100,100,100); 

Ma question est plus. Il utilise certaines mesures qui ne sont pas nécessaires à mon avis:

  1. Nous avons une couleur Niveaux de gris: 100
  2. je dois le convertir en une véritable couleur RVB (100100100)
  3. Ensuite, il calcule la couleur vient hors de lui, et il est un nouveau niveau de gris (100)

Requestion

y at-il quelque chose comme ça

Bitmap.SetPixel(x,y, new GreyColor(100)); 
+2

Quel type de "quelque chose"? Votre question est très vague. – Oded

+0

Eh bien, mon «problème» est. Est-ce en utilisant cette méthode, j'ai un niveau de gris, je le convertis en une couleur ('Color.FromArgb()'), puis laissez le programme le convertir à nouveau en niveaux de gris. –

+1

Je ne l'ai pas compris, que voulez-vous dire? –

Répondre

2

Non, il n'existe pas de GreyColor dans .NET. Un GreyColor est juste un cas particulier d'une couleur, de la même manière que le vert citron est un cas particulier d'une couleur. Il n'y a pas besoin de compliquer le modèle.

Il sont certains pre-defined colors que vous pouvez utiliser si vous pouvez trouver la couleur que vous cherchez. Ceux-ci renvoient simplement un objet Color qui a une valeur ARGB correspondant à la couleur prédéfinie, donc ils ne font rien de différent de ce que fait votre code ci-dessus. Ils sont simplement là pour la commodité du programmeur qui ne peut pas ou ne veut pas se souvenir du modèle de couleur RVB pas si intuitif.

Vous semblez être préoccupé par le coût potentiel ou la redondance de la création d'un objet Color, mais il y a plusieurs raisons pour lesquelles cela ne devrait pas être un problème. Vous pouvez considérer la méthode FromArgb comme un constructeur surchargé pour l'objet Color: c'est la manière dont vous créez une couleur autre que celles prédéfinies.Il crée simplement l'objet de couleur défini comme valeurs RVB que vous spécifiez. En fait, il n'y a vraiment aucun autre moyen de représenter une couleur (mis à part les modèles de couleurs alternatifs tels que HSV, mais même alors vous devez spécifier trois valeurs séparées: une teinte de 0, une saturation de 0 et une valeur de 39). Nous, humains, pouvons décrire les couleurs de manière beaucoup plus abstraite, mais un ordinateur ne comprend pas vraiment ces choses ou ne s'en soucie pas vraiment. Le documentation pour la structure de couleur elle-même explique qu'il ne représente que les valeurs RVB, avec la valeur alpha (transparence). C'est un très petit objet qui contient environ 4 valeurs d'octets. Et c'est exactement la façon dont la couleur à laquelle vous passez la couleur (Bitmap.SetPixel) va dessiner la couleur, en fonction de ces valeurs rouges, vertes et bleues.

Il est également intéressant de souligner que Color est une structure, qui est un type de valeur, plutôt qu'un type de référence. Cela signifie, among other things, qu'il vit en ligne, partout où votre variable est définie. Il ne pointe pas vers un autre objet, il vit localement sur la pile plutôt que sur le tas, et the stack is cheap. Cela en fait au moins un peu moins cher qu'un type de référence tel qu'une classe.

Enfin, je m'en voudrais de ne pas souligner que ce type de micro-optimisation va rarement faire une différence dans la performance de votre code.

En bref, non, il n'y a rien de tel, mais ce n'est pas un problème.

2

Rien ne permet de convertir une valeur de luminosité en couleur.

Pour obtenir la luminosité d'une couleur, utilisez la méthode GetBrightness. Il retourne une valeur comprise entre 0.0 et 1.0, donc vous devez escalader jusqu'à obtenir une valeur 0-255:

Color c = betPixel(x, y); 
int brightness = (int)Math.Round(c.GetBrightness() * 255.0); 

Vous pouvez faire des méthodes d'extension pour rendre le code plus simple:

public static ColorExtensions { 

    public static Color ToGrayscale(this int brightness) { 
    return Color.FromArgb(brightness, brightness, brightness); 
    } 

    public static int FromGrayscale(this Color color) { 
    return (int)Math.Round(color.GetBrightness() * 255.0); 
    } 

} 

Utilisation :

bitmap.SetPixel(x, y, 100.ToGrayscale()); 
int g = bitmap.GetPixel(x, y).FromGrayscale(); 
1

Vous pouvez créer des bitmaps indexés 8bpp et travailler avec eux:

var bmp = new Bitmap(width, height, 
    System.Drawing.Imaging.PixelFormat.Format8bppIndexed); 

Vous devez écrire vos propres get/set méthodes de pixels si, par exemple (non testé, mais devrait donner une idée générale comment le faire):

public static byte GetIndexedPixel(this Bitmap bitmap, int x, int y) 
{ 
    var bd = bitmap.LockBits(new Rectangle(x, y, 1, 1), 
     System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); 
    var color = System.Runtime.InteropServices.Marshal.ReadByte(bd.Scan0); 
    bitmap.UnlockBits(bd); 
    return color; 
} 

public static void SetIndexedPixel(this Bitmap bitmap, int x, int y, byte color) 
{ 
    var bd = bitmap.LockBits(new Rectangle(x, y, 1, 1), 
     System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); 
    System.Runtime.InteropServices.Marshal.WriteByte(bd.Scan0, color); 
    bitmap.UnlockBits(bd); 
} 

En général, je ne pense pas que vous devriez faire Si vous ne générez pas des tableaux d'octets en mémoire de pixels en niveaux de gris et que vous voulez les convertir en bitmap dans plusieurs appels CopyMemory. Cependant, si vous utilisez SetPixel/GetPixel, les performances risquent de ne pas poser problème.

Questions connexes