Графика неправильная интерполяция изображения в .Net - PullRequest
3 голосов
/ 04 октября 2011

У меня есть простой тест.Когда это решено, моя проблема тоже решена.При работе с небольшими изображениями графическая интерполяция плохо работает.

Пожалуйста, проверьте, если вы знаете, как решить проблему, что изображение результата в следующем коде игнорирует вторую половину изображения для рисования.Нарисуйте что-нибудь на изображении, используя loadimage из JPG или что вы хотите.

    Dim GrayImage as system.drawing.Bitmap(640,480)    
    Dim bmTmp As New System.Drawing.Bitmap(GrayImage.Width, 1)
    Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmTmp)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear
         gr.DrawImage(GrayImage, New System.Drawing.Rectangle(0, 0, bmTmp.Width, bmTmp.Height), New System.Drawing.Rectangle(0, 0, GrayImage.Width - 0, GrayImage.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

     GrayImage = New System.Drawing.Bitmap(GrayImage.Width, GrayImage.Height, GrayImage.PixelFormat)
     Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(GrayImage)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
         gr.DrawImage(bmTmp, New System.Drawing.Rectangle(0, 0, GrayImage.Width, GrayImage.Height ), New System.Drawing.Rectangle(0, 0, bmTmp.Width - 0, bmTmp.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

Source stretched to let you view it Скачать исходный код здесь: http://www.goldengel.ch/temp/Source01%20one%20Pixel.jpg (одно изображение высоты в пикселях)

Destination image without fully drawing in half Вторая половина вертикали не рисуется с помощью метода DrawImage.Я хочу получить изображение в результате, как вы видите на первом изображении.Растянутое изображение с источником на весь контент.

* СКАЧАТЬ * Загрузить здесь полностью работающий демонстрационный проект VS2010 VB.Net:

VS2010 Масштабный проект с описанием - TimoБёме

Ответы [ 4 ]

2 голосов
/ 14 октября 2011

Пожалуйста, попробуйте добавить:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

до вашего последнего предложения. GDI магия, я думаю, :) 1004 *

Надеюсь, это поможет!

2 голосов
/ 07 октября 2011

У меня была похожая проблема, которую я решил, изменив размер исходного изображения. Я предполагаю, что это ожидаемое поведение, а не ошибка (обычное объяснение MS, но для этого случая это может быть правильным :)). Некоторые алгоритмы интерполяции требуют более одной строки пикселя (относится к обеим осям) для правильной работы. Если второй строки нет, они могут интерполироваться в пустую строку, что вызывает вышеуказанную проблему. Вы можете изменить ширину / высоту изображения до 2 пикселей минимум или использовать надлежащие методы интерполяции для однострочных изображений.

1 голос
/ 14 октября 2011

Как сказал @EmirAkaydin в своем ответе, ваша проблема заключается в интерполяции.Я подозреваю, что его ответ о том, что он имеет высоту всего в один пиксель, противоречит алгоритму изменения размера Microsoft, является правильным.

У меня есть для вас двухэтапное решение.Если вы не хотите писать свой собственный код изменения размера (я не хотел), который изменяет размеры точно так, как вы хотите, вы все равно можете использовать функцию Graphics.DrawImage, чтобы хотя бы изменить размер width вашего изображения, нотолько ширина.Затем вы можете напрямую манипулировать данными пикселей и копировать каждую эту первую действительную строку для всей высоты изображения.

Вы можете заменить свой код DoDemo следующим (я не использую VB, поэтомуЯ не уверен насчет стиля кодирования, он работает, однако):

    Call CreateSampleImage()

    'scale the image to only one single row
    Dim bm As New Bitmap(450, 1)
    Using gr As Graphics = Graphics.FromImage(bm)
        Dim RDst As New Rectangle(0, 0, bm.Width, bm.Height)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox1.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using
    Me.PictureBox2.Image = bm

    'stretch now the single row image back to original width
    Dim bm2 As New Bitmap(Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)
    Using gr As Graphics = Graphics.FromImage(bm2)
        Dim RDst As New Rectangle(0, 0, bm2.Width, 1)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox2.Image.Width, Me.PictureBox2.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox2.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using

    ' use our own custom height stretch code
    Dim rrc As New Rectangle(0, 0, bm2.Width, bm2.Height)
    Dim bmd As BitmapData

    bmd = bm2.LockBits(rrc, ImageLockMode.ReadWrite, bm2.PixelFormat)

    ' stride is the width of the image in pixels
    Dim ba(bmd.Stride - 1) As Byte
    Marshal.Copy(bmd.Scan0, ba, 0, bmd.Stride)

    ' copy pixel data to each line
    For y = 1 To bmd.Height - 1
        Marshal.Copy(ba, 0, bmd.Scan0 + (y * bmd.Stride), ba.Length)
    Next

    bm2.UnlockBits(bmd)

    Me.PictureBox3.Image = bm2

РЕДАКТИРОВАТЬ:

Интересно, что опубликованный код @FredrikJohansson также будет работать:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

прямо перед тем, как нарисовать изображение.Я оставлю этот код и отвечу здесь, на случай, если кто-нибудь захочет его увидеть, но, похоже, он ответил на ваш вопрос проще:)

0 голосов
/ 11 октября 2011

Вы пробовали интерполяцию NearestNebor?

...