Рейтинг@Mail.ru

WPF: Как сохранить элемент управления FrameworkElement() в виде изображения

Print Friendly, PDF & Email

Нужно сохранить какой-то элемент управления окна WPF в изображение. Допустим, сохранить как картинку динамически сгенерированный график или таблицу. Можно сделать это, например, так.

Сначала сгенерируем изображение с помощью класса RenderTargetBitmap(), запишем его в поток в памяти, прочитаем и сохраним в объект типа String():

''' <summary>
''' Генерирует строку, представляющую поток изображения, из FrameworkElement.
''' </summary>
''' <param name="elem">Элемент, который будет преобразован в изображение.</param>
Private Function GetElementAsString(ByVal elem As FrameworkElement) As String    
    Dim w As Integer = CInt(elem.ActualWidth)
    Dim h As Integer = CInt(elem.ActualHeight)
    Dim renderBitmap As New RenderTargetBitmap(w, h, 96, 96, PixelFormats.Default)
    renderBitmap.Render(elem)

    Dim pngEncoder As New PngBitmapEncoder()
    Dim bmFrame As BitmapFrame = BitmapFrame.Create(renderBitmap)
    pngEncoder.Frames.Add(bmFrame)

    Dim pngStr As String = String.Empty
    Using ms As New IO.MemoryStream()
        pngEncoder.Save(ms)
        ms.Seek(0, IO.SeekOrigin.Begin)
        Using sr As New IO.StreamReader(ms, Text.Encoding.Default)
            pngStr = sr.ReadToEnd
        End Using
    End Using
    Return pngStr
End Function

Напишем метод для сохранения изображения в файл:

''' <summary>
''' Сохраняет строку с данными изображения в файл PNG с указанным именем.
''' </summary>
''' <param name="fileName">Имя файла с расширением PNG, под которым будет сохранено изображение.</param>
''' <param name="imgStr">Строка, представляющая изображение.</param>
Private Sub SaveElementAsImage(ByVal fileName As String, ByVal imgStr As String)
    Using fs As New IO.FileStream(fileName, IO.FileMode.Create)
        Using sw As New IO.StreamWriter(fs, Text.Encoding.Default)
            sw.Write(imgStr)
        End Using
    End Using
End Sub

Теперь мы можем сохранить изображение в файл, используя предыдущие два метода:

Dim pngStr As String = GetElementAsString(MyControlToSave)
SaveElementAsImage("1.png", "Рисунок 1")

Кстати, интересно было бы иметь возможность менять размер сгенерированного изображения. Это пригодится, если нам нужно увеличить или уменьшить изображение элемента управления, или изменить его пропорции. Сделать это можно, например, вот таким образом:

''' <summary>
''' Изменяет размер переданного изображения.
''' </summary>
''' <param name="src">Исходное изображение.</param>
''' <param name="width">Ширина выходного изображения.</param>
''' <param name="height">Высота выходного изображения.</param>
Private Function GetResizedBitmapFrame(ByVal src As ImageSource, ByVal width As Double, ByVal height As Double) As BitmapFrame

    Dim rect As New Rect(0, 0, width, height)
    Dim group As New DrawingGroup
 
    RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality)
    group.Children.Add(New ImageDrawing(src, rect))
 
    Dim drwVisual As New DrawingVisual
    Using drwContext = drwVisual.RenderOpen()
        drwContext.DrawDrawing(group)
    End Using
 
    Dim resizedBitmap As New RenderTargetBitmap(CInt(width), CInt(height), 96, 96, PixelFormats.Default)
    resizedBitmap.Render(drwVisual)
    Return BitmapFrame.Create(resizedBitmap)

End Function

Теперь, чтобы использовать метод изменения размера изображения, нужно немного изменить наш метод GetElementAsString(), а именно, вместо

pngEncoder.Frames.Add(bmFrame)

добавить вот такой код:

Dim resizedFrame As BitmapFrame = GetResizedBitmapFrame(bmFrame, newWidth, newHeight)
pngEncoder.Frames.Add(resizedFrame)

Последнее изменениеСреда, 20 Декабрь 2017 19:20 Прочитано 8690 раз

Поблагодарить автора:

Поделиться

Print Friendly, PDF & Email

Оставить комментарий