2010-06-16 176 views
0

我希望在代码中并根据需要将32位RGBA图像对象(最初是32位PNG)转换为其32位灰度对象。如何将32位RGBA图像转换为保存灰度图的alpha

我已经在这里read几个other问题,以及在线许多文章。我尝试过使用ColorMatrix来做到这一点,但它似乎并没有很好地处理Alpha。像素完全不透明的灰度。任何部分透明的像素似乎都不能很好地平移,因为这些像素中仍有色彩。足以引人注目。我用

嘉洛斯如下:

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

这是,因为我读过,一个非常标准的NTSC加权矩阵。然后我使用它,连同Graphics.DrawImage,但正如我所说,部分透明的像素仍然是彩色的。我应该指出这是通过在白色背景上的WinForms PictureBox显示Image对象。它可能只是PictureBox绘制图像和处理透明部分的方式吗?背景颜色不会影响它(颜色的颜色肯定来自原始图像),但PictureBox可能不会正确重绘透明像素?

我见过一些使用FormatConvertedBitmap和OpacityMask的方法。我还没有尝试过,主要是因为我真的不想导入PresentationCore.dll(更不用说这意味着它不能在.NET 2.0有限的应用程序中工作)。当然基本的System.Drawing。*的东西可以做到这一简单的过程?或不?

+0

你确定颜色的色调不是由于背后的图像?只要RGB值完全相等,就不会有任何色差。发布您的ColorMatrix定义。 – ChrisF 2010-06-16 14:03:47

+0

我确定它不是。该图像通过PictureBox呈现。当然,PictureBox的背景是透明的,这实际上意味着它使用父级的颜色,在这种情况下,它是白色的。但是,新灰度图像的透明边缘仍然呈绿色(原始图像大部分为绿色)。 – 2010-06-16 14:17:18

回答

5

您是否有机会使用ColorMatrix将图像绘制到自身上?这当然不会起作用(因为如果你在绿色像素上绘制半透明灰色的东西,一些绿色会发光)。您需要将其绘制到仅包含透明像素的新空白位图上。

+0

啊,废话,你可能是对的。男人,我真的希望这次能找到一个bug或者什么的!但是,像往常一样,这只是我的愚蠢。 – 2010-06-16 14:30:43

0

如果您将图像转换为TGA格式,您可以使用“RubyPixels”直接编辑像素数据,根据您的需要进行无压缩的图像格式。然后您可以将其转换回PNG。

我推荐使用ImageMagick进行转换,也可以从ruby转换。

+0

也许我并不清楚,但我并不关心图像的原始格式(GIF,PNG,JPG等)或将其转换为保存它或任何东西。我只是指定.NET中的Image对象最初是从PNG创建的。我直接在WinForms环境中使用这个Image对象,并操纵它的颜色,在这种情况下,禁用外观。我无意挽救它。它只是用于即时“变灰”。即便如此,如果其他人感兴趣,你能否提供一些链接给你的建议? – 2010-06-16 14:19:49

+0

对不起,在这种情况下不能帮你... = < – thomasfedb 2010-06-16 16:05:09

3

感谢danbystrom的好奇心,我的确在重绘原版。对于任何感兴趣的人,这里是我使用的更正方法:

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