Как преобразовать 32-битное изображение RGBA в альфа-код, сохраняющий оттенки серого - PullRequest
0 голосов
/ 16 июня 2010

Я хотел бы в коде и по требованию преобразовать 32-разрядный объект RGBA Image (первоначально 32-разрядный PNG) в его 32-разрядный аналог оттенков серого.

Я уже прочитайте несколько других вопросов здесь, а также много статей в Интернете.Я пытался использовать ColorMatrix, но, похоже, он не очень хорошо справляется с альфой.Пиксели, которые полностью непрозрачны в оттенках серого отлично.Кажется, что любой частично прозрачный пиксель не очень хорошо переводится, поскольку в этих пикселях все еще присутствуют оттенки цвета.Достаточно быть заметным.

Я использую ColorMatrix следующим образом:

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, но, как я уже сказал, частично прозрачные пиксели все еще окрашены.Я должен отметить, что это отображение объекта Image через WinForms PictureBox на белом фоне.Может быть, именно так PictureBox рисует свои изображения и обрабатывает прозрачные части?Цвета фона не влияют на него (оттенок цвета от исходного изображения наверняка), но, возможно, PictureBox неправильно перерисовывает прозрачные пиксели?

Я видел некоторые методы, которые используют FormatConvertedBitmap вдольс непрозрачностью маски.Я не пробовал, главным образом потому, что я действительно предпочел бы не импортировать PresentationCore.dll (не говоря уже о том, что он не будет работать в приложениях с ограничением .NET 2.0).Наверняка основные вещи System.Drawing. * Могут сделать эту простую процедуру?Или нет?

Ответы [ 3 ]

5 голосов
/ 16 июня 2010

Вы случайно рисуете изображение на себя, используя ColorMatrix?Это, конечно, не сработает (потому что если вы нарисуете что-то полупрозрачно-серое над зеленым пикселем, зеленый будет просвечивать).Вам нужно нарисовать его на новом пустом растровом изображении, содержащем только прозрачные пиксели.

4 голосов
/ 16 июня 2010

Благодаря праздному любопытству 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();
    ColorMatrix 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;
}
0 голосов
/ 16 июня 2010

Если вы преобразуете изображение в TGA, в несжатый формат imaeg, вы можете использовать RubyPixels для непосредственного редактирования данных пикселей, делая все, что вам угодно. Затем вы можете преобразовать его обратно в PNG.

Я рекомендую делать преобразование с ImageMagick, также из ruby.

...