Обработка изображений
От: GePo  
Дата: 19.03.06 15:19
Оценка:
Пусть я, например, хочу свести изображение к градациям серого.
Пишу такую фукнцию

void Filters::ToGray(System::Drawing::Bitmap* bmp)
{
    int w = bmp->Width;
    int h = bmp->Height;
    int x, y;

    BitmapData* bmpData;

    bmpData = bmp->LockBits (System::Drawing::Rectangle(0, 0, w, h),
                                           ImageLockMode::ReadWrite,
                                        PixelFormat::Format24bppRgb);

    char* p = (char*)bmpData->Scan0.ToPointer();
    char gray;
    int nOffset = bmpData->Stride - 3*w;

    for(y = 0; y < h; ++y, p += nOffset)
    {
        for(x = 0; x < w; ++x, p += 3)
        {
            char r = p[2];
            char g = p[1];
            char b = p[0];
            gray = char(0.3*r + 0.59*g + 0.11*b);

            p[0] = p[1] = p[2] = gray;
        }
    }
    bmp->UnlockBits(bmpData);
}


в неё передается Bitmap, который хранится в памяти. В обработчике формы OnPaint стоит
e->Graphics->DrawImage(m_Bitmap, 0, 0, m_Bitmap->Width, m_Bitmap->Height);


На выходе получаю картинку плохого качества.Т.е., это явно не gray-scale, там палитра серго явно меньше.
Отсюда вопрос, что я неправильно сделал?
Re: Обработка изображений
От: Closer  
Дата: 19.03.06 15:49
Оценка:
Здравствуйте, GePo, Вы писали:

GP>Пусть я, например, хочу свести изображение к градациям серого.


Попробуй использовать класс System.Drawing.Drawing2D.LinearGradientBrush

using (LinearGradientBrush brush1 = new LinearGradientBrush(rectangle2, color3, color4, 90f))
{
    g.FillRectangle(brush1, rectangle2);
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Мы были здесь. Но пора идти дальше. (с) Дуглас Коупленд, Рабы "Микрософт"
Re[2]: Обработка изображений
От: GePo  
Дата: 19.03.06 15:55
Оценка:
Здравствуйте, Closer, Вы писали:

C>Здравствуйте, GePo, Вы писали:


GP>>Пусть я, например, хочу свести изображение к градациям серого.


C>Попробуй использовать класс System.Drawing.Drawing2D.LinearGradientBrush


C>
C>using (LinearGradientBrush brush1 = new LinearGradientBrush(rectangle2, color3, color4, 90f))
C>{
C>    g.FillRectangle(brush1, rectangle2);
C>}
C>


Если я правильно понял, то это вы предлагаете по другому свести к градациям. Мне такой вариант не подходит, потому что мне надо будет реализовывать различные фильтры. Если я не правильно понял, то можете по конкретнее пример написать, т.к. я еще плохо дружу с .NET
Re[3]: Обработка изображений
От: Closer  
Дата: 19.03.06 16:24
Оценка:
Здравствуйте, GePo, Вы писали:

GP>Если я правильно понял, то это вы предлагаете по другому свести к градациям. Мне такой вариант не подходит, потому что мне надо будет реализовывать различные фильтры. Если я не правильно понял, то можете по конкретнее пример написать, т.к. я еще плохо дружу с .NET


Сори, не внимательно прочитал вопрос. Посмотри как сделано здесь http://www.bobpowell.net/grayscale.htm
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Мы были здесь. Но пора идти дальше. (с) Дуглас Коупленд, Рабы "Микрософт"
Re[4]: Обработка изображений
От: GePo  
Дата: 19.03.06 16:40
Оценка:
C>Сори, не внимательно прочитал вопрос. Посмотри как сделано здесь http://www.bobpowell.net/grayscale.htm

Да, вроде у проблема в цветах, т.к. используя GetPixel/SetPixel все фильтры работают правильно — но медленно. Хотелось бы быстро, как я делал, только вот как правильно работать с цветами — непонятно.
Re[5]: Обработка изображений
От: Closer  
Дата: 19.03.06 16:50
Оценка:
Здравствуйте, GePo, Вы писали:


C>>Сори, не внимательно прочитал вопрос. Посмотри как сделано здесь http://www.bobpowell.net/grayscale.htm


GP>Да, вроде у проблема в цветах, т.к. используя GetPixel/SetPixel все фильтры работают правильно — но медленно. Хотелось бы быстро, как я делал, только вот как правильно работать с цветами — непонятно.


А второй алгоритм который там описан чем тебе не устраивает? Вроде написано что он быстро работает.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Мы были здесь. Но пора идти дальше. (с) Дуглас Коупленд, Рабы "Микрософт"
Re[5]: Обработка изображений
От: Powerz Россия https://zagosk.in
Дата: 19.03.06 17:13
Оценка:
Здравствуйте, GePo, Вы писали:


C>>Сори, не внимательно прочитал вопрос. Посмотри как сделано здесь http://www.bobpowell.net/grayscale.htm


GP>Да, вроде у проблема в цветах, т.к. используя GetPixel/SetPixel все фильтры работают правильно — но медленно. Хотелось бы быстро, как я делал, только вот как правильно работать с цветами — непонятно.



public static Bitmap RGBToGrey(Bitmap picture, ProcessingType type)
        {
            Bitmap pic = (Bitmap)picture.Clone();
            int pictureWidth = pic.Width;
            switch (type)
            {
                case ProcessingType.Matrix:
                    Graphics g = Graphics.FromImage(pic);
                    float[][] greyArray = 
                    { 
                        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,      1, 1}
                    };
                    ColorMatrix greyMatrix = new ColorMatrix(greyArray);
                    ImageAttributes greyAttributes = new ImageAttributes(); 
            
                    greyAttributes.SetColorMatrix(greyMatrix, ColorMatrixFlag.Default, ColorAdjustType.Default);
                    Rectangle picRectangle = new Rectangle(0, 0, pic.Width, pic.Height);
                    g.DrawImage(pic, picRectangle, 0, 0, pic.Width, pic.Height, GraphicsUnit.Pixel, greyAttributes);
                    break;

                case ProcessingType.PerPixel:
                    Color pixelColor;
                    byte byteGrey = 0;
                    int intGrey = 0;
                    
                    for (int y = 0; y < pic.Height; y++)
                    {
                        for (int x = 0; x < pictureWidth; x++)
                        {
                            pixelColor = pic.GetPixel(x, y);
                            intGrey = (int)(0.299 * pixelColor.R + 0.587 * pixelColor.G + 0.144 * pixelColor.B);
                            if (intGrey > 255)
                                byteGrey = 255;
                            else
                                byteGrey = (byte)intGrey;
                            pic.SetPixel(x, y, Color.FromArgb(byteGrey, byteGrey, byteGrey));
                        }
                    }
                    break;

                case ProcessingType.PerPixelUnsafe:
                    BitmapData bmData = pic.LockBits(new Rectangle(0, 0, pic.Width, pic.Height), 
                        ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 
                    IntPtr scan = bmData.Scan0; 
                    
                    unsafe 
                    { 
                        byte* p = (byte*)scan;
                        byte red;
                        byte green;
                        byte blue;

                        for (int y = 0; y < pic.Height; y++)
                        {
                            for (int x = 0; x < pictureWidth; x++)
                            {
                                blue  = p[0];
                                green = p[1];
                                red   = p[2];
                                p[0]  = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
                                p += 3;
                            }
                        }
                    }
                    pic.UnlockBits(bmData);
                    break;
            }
            return pic;
        }
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
https://zagosk.in
Re[6]: Обработка изображений
От: GePo  
Дата: 19.03.06 17:57
Оценка:
Здравствуйте, Powerz, Вы писали:

P>
            case ProcessingType.PerPixelUnsafe:
P>                    BitmapData bmData = pic.LockBits(new Rectangle(0, 0, pic.Width, pic.Height), 
P>                        ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 
P>                    IntPtr scan = bmData.Scan0; 
                    
P>                    unsafe 
P>                    { 
P>                        byte* p = (byte*)scan;
P>                        byte red;
P>                        byte green;
P>                        byte blue;

P>                        for (int y = 0; y < pic.Height; y++)
P>                        {
P>                            for (int x = 0; x < pictureWidth; x++)
P>                            {
P>                                blue  = p[0];
P>                                green = p[1];
P>                                red   = p[2];
P>                                p[0]  = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
P>                                p += 3;
P>                            }
P>                        }
P>                    }
P>                    pic.UnlockBits(bmData);
P>                    break;
P>            }
P>            return pic;
P>        }
P>


именно вот в этом случае у меня проблема с цветами. Может там какие-нибудь дополнительные параметры для битмапа задавать надо?
Re[6]: Обработка изображений
От: GePo  
Дата: 19.03.06 17:59
Оценка:
Совсем забыл сказать. Аналогичный пример в C# у меня работает. Тоже, но на С++ — нет. Нужно на С++
Re[7]: Обработка изображений
От: GePo  
Дата: 19.03.06 19:49
Оценка:
Все проблему решил. К буферу картинки надо обращатся не как к char*, а как к unsigned char*. Это если кому понадобится
Re[7]: Обработка изображений
От: Аноним  
Дата: 19.03.06 20:12
Оценка:
код некорректен
надо вместо pic.windth использовать pic.stride
SLoW


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.