Graphics.DrawImage создает градиент альфа-канала в C# WinForms 2.0

Я столкнулся с действительно сложной проблемой ..

У меня есть проект .Net 2.0 С# WinForms. Я пытаюсь растянуть растровое изображение на область рисования, но по какой-то причине оно не растягивается должным образом - я получаю градиент альфа-канала на правом и нижнем полях области рисования.

Мне потребовалось довольно много времени, чтобы изолировать эту проблему. Я создаю несколько строк кода, которые воспроизводят проблему (см. фрагмент кода и снимок экрана ниже).

Кто-нибудь может пролить свет на этот вопрос?

Заранее спасибо.

--

private void Form1_Paint( object sender, PaintEventArgs e )
{
    // Create a black bitmap resource sized 10x10
    Image resourceImg = new Bitmap( 10, 10 );
    Graphics g = Graphics.FromImage( resourceImg );
    g.FillRectangle( Brushes.Black, 0, 0, resourceImg.Width, resourceImg.Height );

    Rectangle drawingArea = new Rectangle( 0, 0, 200, 200 ); // Set the size of the drawing area
    e.Graphics.FillRectangle( Brushes.Aqua, drawingArea );   // Fill an aqua colored rectangle
    e.Graphics.DrawImage( resourceImg, drawingArea );        // Stretch the resource image

    // Expected result: The resource image should completely cover the aqua rectangle.
    // Actual Result:   The right and bottom edges become gradiently transparent (revealing the aqua rectangle under it)
}

Проблема рисования изображения


person AVIDeveloper    schedule 27.11.2011    source источник


Ответы (1)


Поведение связано с тем, как GDI+ обрабатывает края. В этом случае вы масштабируете очень маленькое изображение на большой площади и не указали GDI+, как обрабатывать края. Если вы используете класс ImageAttributes и правильно устанавливаете WrapMode, вы можете обойти эту проблему.

Например:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    using (var resourceImg = new Bitmap(10, 10))
    {
        using (var g = Graphics.FromImage(resourceImg))
        {
            g.FillRectangle(Brushes.Black, 0, 0, 
                resourceImg.Width, resourceImg.Height);
        }

        var drawingArea = new Rectangle(0, 0, 200, 200);
        e.Graphics.FillRectangle(Brushes.Aqua, drawingArea);

        using (var attribs = new ImageAttributes())
        {
            attribs.SetWrapMode(WrapMode.TileFlipXY);
            e.Graphics.DrawImage(resourceImg, drawingArea, 
                    0, 0, resourceImg.Width, resourceImg.Height, 
                    GraphicsUnit.Pixel, attribs);
        }
    }    
}

Приведенный выше код должен создавать полностью черное изображение. Если вы закомментируете оператор attribs.SetWrapMode(WrapMode.TileFlipXY);, вы должны увидеть синий градиент. С установленным режимом переноса вы указываете GDI+ переворачивать изображение по краям, чтобы он улавливал больше черного и не затухал по краям при масштабировании изображения.

person rsbarro    schedule 27.11.2011
comment
Теперь я понимаю, что неправильно ведет себя WrapMode.Clamp (я ожидал, что он умножит пиксели, но, очевидно, он выполняет какой-то другой алгоритм постепенного сдвига цвета). Спасибо за содержательный ответ, поправляйтесь! - person AVIDeveloper; 28.11.2011