Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > GDI/GDI+: наложение маски на изображение


Автор: tab 10.12.2008, 14:28
Задачка такая: допустим есть Bitmap. С ним необходимо провести кучу действий сводящихся в основном к наложению на него различных масок. В данный момент использую массив пикселов получаемый с помощью bitmapData.Scan0 и дальше маска - как комбинация соответствующих пикселов. Может быть есть в GDI/GDI+ набор функций отвечающий за наложение масок непосредственно?

Автор: Unlocker 28.1.2009, 11:58
Сабж остается неизменным.
Кратко сформулирую задачу: есть пара Bitmap'ов, которые имеют одинаковые размеры и PixelFormat. Необходимо получить изображение, полученное наложением маски на целевой Bitmap. Если пиксель окрашен на маске в белый цвет, то соответствующий пиксель изображения переносится из целевой картинки, а если в черный, то окрашивается каким-то заранее установленным цветом.
Код

public Bitmap DrawMaskedImage()
        {
            Bitmap bmp = new Bitmap(mMainImage.Width, mMainImage.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(mMainImage, 0, 0);
            g.Dispose();
            for(int i=0; i<mMainImage.Width; i++)
            {
                for(int j=0; j<mMainImage.Height; j++)
                {
                    if(mShadowImage.GetPixel(i, j) == Color.Black)
                        bmp.SetPixel(i, j, mBackColor);
                }
            }
            return bmp;
        }

сначала рисуем базовое изображение, потом окрашиваем пикселы, соответствующие черным на маске, установленным цветом mBackColor. Только этот код оказывается неработоспособным. Буду признателен за комментарии.

Автор: Unlocker 30.1.2009, 11:38
Ларчик просто открывался. Вместо этого
Код

if(mShadowImage.GetPixel(i, j) == Color.Black)
                        bmp.SetPixel(i, j, mBackColor);

Надо было написать
Код

if(mShadowImage.GetPixel(i, j).ToArgb() == Color.Black.ToArgb())
                        bmp.SetPixel(i, j, mBackColor);

Еще улучшил попиксельную обработку в плане скорости. Класс декоратора нашел Google, а код я приложил к посту.
Код

public Bitmap DrawMaskedImage()
        {
            Bitmap bmp = new Bitmap(mMainImage.Width, mMainImage.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(mMainImage, 0, 0);
            g.Dispose();
            using(BitmapDecorator deco1 = new BitmapDecorator(bmp))
            {
                using(BitmapDecorator deco2 = new BitmapDecorator(mShadowImage))
                {
                    for(int i=0; i<mMainImage.Width; i++)
                    {
                        for(int j=0; j<mMainImage.Height; j++)
                        {
                            if(deco2.GetPixel(i, j).ToArgb() == Color.Black.ToArgb())
                                deco1.SetPixel(i, j, mBackColor);
                        }
                    }
                }
            }
            return bmp;
        }

Смысл его использования зафиксировать Bitmap методом LockBits(), провести все попиксельные операции, уничтожить декораторы вызовом Dispose(), в котором прописан UnlockBits(). Реально ускоряет попиксельную обработку достаточно больших растров.
Проблему, на мой взгляд, можно считать решенной.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)