Я изменил ваш исходный класс, добавив некоторые недостающие функции:
- Выбранный формат файла, возвращаемый
SaveFileDialog()
- Выбором фильтров в
SaveFileDialog()
сокращено до форматов, которые Image.Save () фактически поддерживает IDisposable
, используется для удаления растрового изображения, загруженного в данный момент - Некоторые другиеподробности вы можете найти в примечаниях и в коде класса
Теперь это автономный класс, который можно использовать в других контекстах (нет ссылок на конкретные элементы управления или методы:
Пример использования :
Инициализация класса ImageConversion
(в конструкторе формы или там, где вы считаете нужным):
Public Partial Class Form1
Public imgConversion As ImageConversion = New ImageConversion()
'(...)
End Class
Ваши обработчики могут быть изменены следующим образом:
Private Sub OpenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenToolStripMenuItem.Click
If PictureBox1.Image IsNot Nothing Then PictureBox1.Image.Dispose()
Dim NewBitmapFile = imgConversion.OpenFile()
If NewBitmapFile.OpenedBitmap IsNot Nothing Then
PictureBox1.Image = NewBitmapFile.OpenedBitmap
Me.Text = NewBitmapFile.FileName
End If
End Sub
Private Sub BitmapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BitmapToolStripMenuItem.Click
Dim SavedFile = imgConversion.SaveFileFormat()
If SavedFile.ErrorMessage <> String.Empty Then
MessageBox.Show("Failed to save image to Bitmap.", "Error" & SavedFile.ErrorMessage, MessageBoxButtons.OK, MessageBoxIcon.Error)
ElseIf SavedFile.FileName <> String.Empty Then
MessageBox.Show("Image File saved to: " + SavedFile.FileName, "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
Удалять класс ImageConversion
при закрытии формы, это освободит последний использованный объект Image:
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
imgConversion.Dispose()
End Sub
К сведению :
Так как выСпойте метод, который возвращает объект Bitmap
, и этот объект затем присваивается свойству PictureBox.Image
, вам необходимо избавиться от предыдущего изображения, если оно есть, перед назначением нового.В противном случае этот потерянный объект будет задерживаться на большее, чем хотелось бы, и это будет препятствовать вашему приложению.
Фильтры в SaveFileDialog
имеютbeed уменьшен до ImageFormats
, которые фактически поддерживаются GDI + при создании нового растрового изображения.
Icon
, WMF
, EMF
и Exif
не поддерживаются, и в результате получается изображение PNG
формат файла, формат GDI + по умолчанию.
Первые три могут быть созданы с помощью других средств, но это широкий вопрос и не может быть решен здесь.
Несколько методов возвращают ValueTuple в форме ValueTuple(Of T1, T2)
.
Я не уверен, что ваша версия VB.Net поддерживает этот тип и форму возврата.
Если нет, методможет быть изменен, чтобы возвращать ByRef
результаты или специализированный публичный объект (подкласс ImageConversion
), который содержит необходимую информацию (вероятно, предпочтительнее).
Public Function OpenFile() As (OpenedBitmap As Image, FileName As String)
'(...)
Dim result = OpenFile()
Dim img As Bitmap = result.OpenedBitmap
Dim fName As String = result.FileName
Класс ImageConversion
:
Imports System.Drawing.Imaging
Imports System.Globalization
Imports System.IO
Public Class ImageConversion
Implements IDisposable
Private IsDisposed As Boolean = False
Private CurrentFile As String
Private CurrentBitmap As Image
Private Enum FilterType
OpenFile
SaveFile
End Enum
Public Function OpenFile() As (OpenedBitmap As Image, FileName As String)
Using OFD As OpenFileDialog = New OpenFileDialog()
With OFD
.CheckFileExists = True
.CheckPathExists = True
.RestoreDirectory = True
.Title = "Open Image File"
.Filter = GetFileFilters(FilterType.OpenFile)
.FilterIndex = 4
.FileName = ""
End With
If OFD.ShowDialog() = DialogResult.Cancel Then Return Nothing
CurrentFile = OFD.FileName
If CurrentBitmap IsNot Nothing Then CurrentBitmap.Dispose()
CurrentBitmap = CType(Image.FromFile(CurrentFile).Clone(), Bitmap)
End Using
Return (CurrentBitmap, CurrentFile)
End Function
Public Function SaveFileFormat() As (FileName As String, ErrorMessage As String)
Dim NewFileName As String = Path.GetFileNameWithoutExtension(CurrentFile)
Dim ErrorMessage As String = String.Empty
Using SFD As SaveFileDialog = New SaveFileDialog()
With SFD
.AddExtension = True
.ValidateNames = True
.CheckPathExists = True
.RestoreDirectory = True
.Title = "Save Image File"
.Filter = GetFileFilters(FilterType.SaveFile)
.FileName = NewFileName
End With
If SFD.ShowDialog() = DialogResult.Cancel Then Return (String.Empty, String.Empty)
Try
NewFileName = SFD.FileName
Dim imgFormat As ImageFormat = GetImageFormat(NewFileName)
CurrentBitmap.Save(NewFileName, imgFormat)
Catch ex As IOException
NewFileName = String.Empty
End Try
End Using
Return (NewFileName, ErrorMessage)
End Function
Private Function GetImageFormat(FileName As String) As ImageFormat
Dim fileType As String = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Path.GetExtension(FileName).Remove(0, 1).ToLower())
If fileType = "Tif" Then fileType = "Tiff"
If fileType = "Jpg" Then fileType = "Jpeg"
Dim imgFormat As ImageFormat = New ImageFormat(New Guid())
Return DirectCast(imgFormat.GetType().GetProperty(fileType).GetValue(imgFormat), ImageFormat)
End Function
Private Function GetFileFilters(Filter As FilterType) As String
Dim Filters As String() = {
"BMP Files|*.bmp", "|GIF Files|*.gif", "|JPEG Files|*.jpg",
"|PNG Files|*.png", "|TIFF Files|*.tif", "|Enhanced Windows MetaFile|*.emf",
"|Exchangeable Image File|*.exif", "|Icons|*.ico", "|Windows MetaFile|*.wmf"
}
Select Case Filter
Case FilterType.OpenFile
Return String.Join("", Filters)
Case FilterType.SaveFile
Return String.Join("", Filters.Take(5))
Case Else
Return String.Empty
End Select
End Function
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
If IsDisposed Then Return
If disposing Then
If CurrentBitmap IsNot Nothing Then
CurrentBitmap.Dispose()
End If
End If
IsDisposed = True
End Sub
End Class