2010-06-16 5 views
0

Je voudrais, en code et à la demande, convertir un objet Image RGBA 32 bits (à l'origine un PNG 32 bits) en son équivalent en niveaux de gris 32 bits .Comment convertir l'image RGBA 32 bits en alpha dégradé

J'ai déjà read plusieurs questions other ici, ainsi que de nombreux articles en ligne. J'ai essayé d'utiliser ColorMatrix pour le faire, mais il ne semble pas très bien gérer l'alpha. Les pixels qui sont entièrement en niveaux de gris opaque parfaitement. Tout pixel qui est partiellement transparent ne semble pas bien se traduire car il y a encore des nuances de couleur dans ces pixels. Il suffit d'être perceptible.

Le ColorMatrix J'utilise est la suivante:

new System.Drawing.Imaging.ColorMatrix(new float[][]{ 
        new float[] {0.299f, 0.299f, 0.299f, 0, 0}, 
        new float[] {0.587f, 0.587f, 0.587f, 0, 0}, 
        new float[] {0.114f, 0.114f, 0.114f, 0, 0}, 
        new float[] {  0,  0,  0, 1, 0}, 
        new float[] {  0,  0,  0, 0, 1} 
        }); 

Ceci est, comme je l'ai lu, une matrice pondérée NTSC assez standard. Je l'utilise ensuite, avec Graphics.DrawImage, mais comme je l'ai dit, les pixels partiellement transparents sont toujours colorés. Je devrais signaler que c'est l'affichage de l'objet Image via un WinForms PictureBox sur un fond blanc. Serait-ce juste la façon dont PictureBox dessine ses images et manipule les parties transparentes? Les couleurs d'arrière-plan ne l'affectent pas (la teinte de la couleur provient certainement de l'image originale), mais peut-être que PictureBox ne redessine pas correctement les pixels transparents?

J'ai vu certaines méthodes qui utilisent un FormatConvertedBitmap avec un OpacityMask. Je ne l'ai pas essayé, principalement parce que je préfèrerais vraiment ne pas avoir à importer PresentationCore.dll (pour ne pas mentionner que cela ne fonctionnera pas dans les applications limitées .NET 2.0). Sûrement le matériel de base System.Drawing. * Peut faire cette procédure simple? Ou pas?

+0

Etes-vous sûr que la couleur n'est pas due à ce qui se cache derrière l'image? Tant que les valeurs RVB sont exactement égales, il ne devrait y avoir aucune nuance. Postez votre définition ColorMatrix. – ChrisF

+0

Je suis sûr que ce n'est pas le cas. L'image est présentée via un PictureBox. L'arrière-plan de PictureBox est, bien sûr, transparent, ce qui signifie simplement qu'il utilise la couleur de ses parents, qui est, dans ce cas, blanche. Les bords transparents de la nouvelle image en niveaux de gris sont cependant encore verts (l'image originale était principalement de couleur verte). –

Répondre

5

Êtes-vous en train de peindre l'image sur elle-même en utilisant une matrice de couleurs? Cela ne fonctionnera pas bien sûr (parce que si vous peignez quelque chose de semi-transparent-gris sur un pixel vert, un peu de vert brillera à travers). Vous devez le peindre sur un nouveau bitmap vide contenant uniquement des pixels transparents.

+0

Ah merde, vous avez probablement raison. Mec, j'espérais vraiment cette fois avoir trouvé un bug ou quelque chose comme ça! Mais, comme d'habitude, c'est juste que je suis stupide. –

0

Si vous convertissez l'image en TGA, un format imaeg non compressé, vous pouvez utiliser "RubyPixels" pour éditer les données de pixels directement, en faisant ce que vous voulez. Vous pouvez ensuite le convertir en PNG.

Je recommande de faire à la conversion avec ImageMagick, également de ruby.

+0

Peut-être que je n'étais pas clair, mais je ne suis pas vraiment préoccupé par le format original de l'image (GIF, PNG, JPG, etc.) ou de le convertir pour l'enregistrer ou quoi que ce soit. Je spécifiais simplement qu'un objet Image dans .NET a été créé à partir d'un fichier PNG. J'utilise directement cet objet Image dans un environnement WinForms et manipule sa couleur pour, dans ce cas, un aspect désactivé. Je n'ai pas l'intention de le sauvegarder. C'est juste pour "griser" à la volée. Néanmoins, pourriez-vous fournir des liens vers vos suggestions au cas où quelqu'un d'autre serait intéressé? –

+0

Désolé, ne peut pas vous aider dans ce cas ... = < – thomasfedb

3

Grâce à la curiosité oisive de danbystrom, j'étais en train de redessiner sur l'original. Pour ceux qui sont intéressés, voici la méthode corrigée que j'ai utilisée:

using System.Drawing; 
using System.Drawing.Imaging; 

public Image ConvertToGrayscale(Image image) 
{ 
    Image grayscaleImage = new Bitmap(image.Width, image.Height, image.PixelFormat); 

    // Create the ImageAttributes object and apply the ColorMatrix 
    ImageAttributes attributes = new System.Drawing.Imaging.ImageAttributes(); 
    grayscaleMatrix = new ColorMatrix(new float[][]{ 
     new float[] {0.299f, 0.299f, 0.299f, 0, 0}, 
     new float[] {0.587f, 0.587f, 0.587f, 0, 0}, 
     new float[] {0.114f, 0.114f, 0.114f, 0, 0}, 
     new float[] {  0,  0,  0, 1, 0}, 
     new float[] {  0,  0,  0, 0, 1} 
     }); 
    attributes.SetColorMatrix(grayscaleMatrix); 

    // Use a new Graphics object from the new image. 
    using (Graphics g = Graphics.FromImage(grayscaleImage)) 
    { 
     // Draw the original image using the ImageAttributes created above. 
     g.DrawImage(image, 
        new Rectangle(0, 0, grayscaleImage.Width, grayscaleImage.Height), 
        0, 0, grayscaleImage.Width, grayscaleImage.Height, 
        GraphicsUnit.Pixel, 
        attributes); 
    } 

    return grayscaleImage; 
} 
Questions connexes