Изменение размера изображения в VB.NET

У меня есть следующий код в моем IHttpHandler:

            Dim MemoryStream1 As New System.IO.MemoryStream

            MemoryStream1.Write(SqlDataReader1("cover"), 0, SqlDataReader1("cover").Length - 1)

            Dim Bitmap1 As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(MemoryStream1)

            Dim Width1 As Integer = Bitmap1.Width
            Dim Height1 As Integer = Bitmap1.Height

            Dim Width2 As Integer = 90
            Dim Height2 As Integer = Height1 * Width1 / Width1

            Dim Bitmap2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(Width2, Height2)

            Dim Graphics1 As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(Bitmap2)

            Graphics1.DrawImage(Bitmap1, 0, 0, Width2, Height2)

            Dim MemoryStream2 As New System.IO.MemoryStream

            Bitmap2.Save(MemoryStream2, System.Drawing.Imaging.ImageFormat.Png)

            context.Response.BinaryWrite(MemoryStream2.ToArray)

Это работает, но я не уверен, что это правильный способ изменить размер изображения. Как упростить этот код?

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


person Vjacheslav Ravdin    schedule 08.12.2011    source источник
comment
Вот список проблем с ним: nathanaeljones.com/163/20-image-resizing -подводные камни Я бы посоветовал использовать мою библиотеку, это не то, что вы можете втиснуть в 1 или даже 10 страниц кода, не имея серьезных недостатков в системе.   -  person Lilith River    schedule 09.12.2011


Ответы (2)


В принципе код правильный, но есть некоторые проблемы с ним:

  • Вы пропускаете последний байт при записи в первый поток памяти. Последним свойством в вызове Write должна быть длина, а не длина минус один.
  • Ваш расчет Height2 неверен. Выражение Height1 * Width1 / Width1 всегда будет оцениваться как значение Height1. Вместо этого вы должны использовать Height1 * Width2 / Width1.
  • Вы не распоряжаетесь своими потоками памяти, растровыми изображениями или графическими объектами. Используйте блоки Using, чтобы убедиться, что объекты удалены.

Вы можете несколько упростить код, создав первый поток памяти из массива байтов вместо записи массива в поток:

Using MemoryStream1 As New System.IO.MemoryStream(SqlDataReader1("cover"))

  Using Bitmap1 As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(MemoryStream1)

    Dim Width1 As Integer = Bitmap1.Width
    Dim Height1 As Integer = Bitmap1.Height

    Dim Width2 As Integer = 90
    Dim Height2 As Integer = Height1 * Width2 / Width1

    Using Bitmap2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(Width2, Height2)

      Using Graphics1 As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(Bitmap2)

        Graphics1.DrawImage(Bitmap1, 0, 0, Width2, Height2)

      End Using

      Using MemoryStream2 As New System.IO.MemoryStream

        Bitmap2.Save(MemoryStream2, System.Drawing.Imaging.ImageFormat.Png)

        context.Response.BinaryWrite(MemoryStream2.ToArray)

      End Using

    End Using

  End Using

End Using
person Guffa    schedule 08.12.2011

Public Function ResizeImage(imgToResize As Image, size As Size) As Byte()
        Dim sourceWidth As Integer = imgToResize.Width
        Dim sourceHeight As Integer = imgToResize.Height

        Dim nPercent As Single = 0
        Dim nPercentW As Single = 0
        Dim nPercentH As Single = 0

        nPercentW = (CSng(size.Width) / CSng(sourceWidth))
        nPercentH = (CSng(size.Height) / CSng(sourceHeight))

        If nPercentH < nPercentW Then
            nPercent = nPercentH
        Else
            nPercent = nPercentW
        End If

        Dim destWidth As Integer = CInt(Math.Truncate(sourceWidth * nPercent))
        Dim destHeight As Integer = CInt(Math.Truncate(sourceHeight * nPercent))

        Dim b As New Bitmap(destWidth, destHeight)
        Dim g As Graphics = Graphics.FromImage(DirectCast(b, Image))
        g.InterpolationMode = InterpolationMode.HighQualityBicubic

        g.DrawImage(imgToResize, 0, 0, destWidth, destHeight)
        g.Dispose()

        Return b.ToByteArray()
    End Function

Эта функция изменит размер изображения до указанного размера, сохраняя его пропорции. Это было на С#, и я прогнал его через онлайн-конвертер, поэтому может быть не на 100% правильно.

ToByteArray() - это метод расширения, который я написал для хранения изображения в БД, я также могу дать вам это, если хотите.

person SimonGates    schedule 08.12.2011
comment
это уменьшит изображение, так что все изображение будет помещаться внутри размеров size (так что пустое пространство может появиться слева-справа или сверху-вниз, если отображается в контейнере измерения size, который имеет другое соотношение сторон, чем исходное изображение). Чтобы увеличить изображение, чтобы заполнить все размеры size, просто измените < на > в строке If nPercentH < nPercentW Then. (но на самом деле это вернет изображение размером больше size - тогда вам решать, какую часть изображения вы будете использовать и как, например, слева вверху или в центре, для отображения в контейнере с размерами size) - person Sharky; 17.09.2014