MyBitmap.vb 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. '一个万能的自动图片类型转换工具类
  2. Imports System.Drawing.Imaging
  3. Public Class MyBitmap
  4. ''' <summary>
  5. ''' 位图缓存。
  6. ''' </summary>
  7. Public Shared BitmapCache As New Dictionary(Of String, MyBitmap)
  8. ''' <summary>
  9. ''' 存储的图片
  10. ''' </summary>
  11. Public Pic As System.Drawing.Bitmap
  12. '自动类型转换
  13. '支持的类:Image,ImageSource,Bitmap,ImageBrush,BitmapSource
  14. Public Shared Widening Operator CType(Image As System.Drawing.Image) As MyBitmap
  15. Return New MyBitmap(Image)
  16. End Operator
  17. Public Shared Widening Operator CType(Image As MyBitmap) As System.Drawing.Image
  18. Return Image.Pic
  19. End Operator
  20. Public Shared Widening Operator CType(Image As ImageSource) As MyBitmap
  21. Return New MyBitmap(Image)
  22. End Operator
  23. Public Shared Widening Operator CType(Image As MyBitmap) As ImageSource
  24. Dim Bitmap = Image.Pic
  25. Dim rect = New System.Drawing.Rectangle(0, 0, Bitmap.Width, Bitmap.Height)
  26. Dim bitmapData = Bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
  27. Try
  28. Dim size = rect.Width * rect.Height * 4
  29. Return BitmapSource.Create(Bitmap.Width, Bitmap.Height, Bitmap.HorizontalResolution, Bitmap.VerticalResolution, PixelFormats.Bgra32, Nothing, bitmapData.Scan0, size, bitmapData.Stride)
  30. Finally
  31. Bitmap.UnlockBits(bitmapData)
  32. End Try
  33. End Operator
  34. Public Shared Widening Operator CType(Image As System.Drawing.Bitmap) As MyBitmap
  35. Return New MyBitmap(Image)
  36. End Operator
  37. Public Shared Widening Operator CType(Image As MyBitmap) As System.Drawing.Bitmap
  38. Return Image.Pic
  39. End Operator
  40. Public Shared Widening Operator CType(Image As ImageBrush) As MyBitmap
  41. Return New MyBitmap(Image)
  42. End Operator
  43. Public Shared Widening Operator CType(Image As MyBitmap) As ImageBrush
  44. Return New ImageBrush(New MyBitmap(Image.Pic))
  45. End Operator
  46. '构造函数
  47. Public Sub New()
  48. End Sub
  49. Public Sub New(FilePathOrResourceName As String)
  50. Try
  51. FilePathOrResourceName = FilePathOrResourceName.Replace("pack://application:,,,/images/", PathImage)
  52. If FilePathOrResourceName.StartsWithF(PathImage) Then
  53. '使用缓存
  54. If BitmapCache.ContainsKey(FilePathOrResourceName) Then
  55. Pic = BitmapCache(FilePathOrResourceName).Pic
  56. Else
  57. Pic = New MyBitmap(CType((New ImageSourceConverter).ConvertFromString(FilePathOrResourceName), ImageSource))
  58. BitmapCache.Add(FilePathOrResourceName, Pic)
  59. End If
  60. Else
  61. If FilePathOrResourceName.StartsWithF("http") Then '在线图片(这里判断 https:\\ 或 http:\\ 会出问题)
  62. Dim tempFile = PathTemp & "Cache\MyImage\" & GetHash(FilePathOrResourceName)
  63. NetDownload(FilePathOrResourceName, tempFile, True)
  64. FilePathOrResourceName = tempFile
  65. ElseIf FilePathOrResourceName.StartsWithF("data:image/png;base64,") Then 'base64 图片
  66. Dim base64Data = FilePathOrResourceName.Split(",")(1)
  67. Dim imageData = Convert.FromBase64String(base64Data)
  68. Using ms = New MemoryStream(imageData)
  69. Pic = New System.Drawing.Bitmap(ms)
  70. End Using
  71. Return
  72. End If
  73. '使用这种自己接管 FileStream 的方法加载才能解除文件占用
  74. Using InputStream As New FileStream(FilePathOrResourceName, FileMode.Open)
  75. '判断是否为 WebP 文件头
  76. Dim Header(1) As Byte
  77. InputStream.Read(Header, 0, 2)
  78. InputStream.Seek(0, SeekOrigin.Begin)
  79. If Header(0) = 82 AndAlso Header(1) = 73 Then
  80. '读取 WebP
  81. If Is32BitSystem Then Throw New Exception("不支持在 32 位系统下加载 WebP 图片。")
  82. Dim FileBytes(InputStream.Length - 1) As Byte
  83. InputStream.Read(FileBytes, 0, FileBytes.Length)
  84. Dim Decoder As New Imazen.WebP.SimpleDecoder()
  85. Pic = Decoder.DecodeFromBytes(FileBytes, FileBytes.Length)
  86. Else
  87. Pic = New System.Drawing.Bitmap(InputStream)
  88. End If
  89. End Using
  90. End If
  91. Catch ex As Exception
  92. Pic = My.Application.TryFindResource(FilePathOrResourceName)
  93. If Pic Is Nothing Then
  94. Pic = New System.Drawing.Bitmap(1, 1)
  95. Log(ex, $"加载位图失败({FilePathOrResourceName})")
  96. Throw
  97. Else
  98. Log(ex, $"指定类型有误的位图加载({FilePathOrResourceName})", LogLevel.Developer)
  99. Exit Try
  100. End If
  101. End Try
  102. End Sub
  103. Public Sub New(Image As ImageSource)
  104. Using MS = New MemoryStream()
  105. Dim Encoder = New PngBitmapEncoder()
  106. Encoder.Frames.Add(BitmapFrame.Create(Image))
  107. Encoder.Save(MS)
  108. Pic = New System.Drawing.Bitmap(MS)
  109. End Using
  110. End Sub
  111. Public Sub New(Image As System.Drawing.Image)
  112. Pic = Image
  113. End Sub
  114. Public Sub New(Image As System.Drawing.Bitmap)
  115. Pic = Image
  116. End Sub
  117. Public Sub New(Image As ImageBrush)
  118. Using MS = New MemoryStream()
  119. Dim Encoder = New BmpBitmapEncoder()
  120. Encoder.Frames.Add(BitmapFrame.Create(Image.ImageSource))
  121. Encoder.Save(MS)
  122. Pic = New System.Drawing.Bitmap(MS)
  123. End Using
  124. End Sub
  125. ''' <summary>
  126. ''' 获取裁切的图片,这个方法不会导致原对象改变且会返回一个新的对象。
  127. ''' </summary>
  128. Public Function Clip(X As Integer, Y As Integer, Width As Integer, Height As Integer) As MyBitmap
  129. Dim bmp As New System.Drawing.Bitmap(Width, Height, Pic.PixelFormat)
  130. bmp.SetResolution(Pic.HorizontalResolution, Pic.VerticalResolution)
  131. Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp)
  132. g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
  133. g.TranslateTransform(-X, -Y)
  134. g.DrawImage(Pic, New System.Drawing.Rectangle(0, 0, Pic.Width, Pic.Height))
  135. End Using
  136. Return bmp
  137. End Function
  138. ''' <summary>
  139. ''' 获取旋转或翻转后的图片,这个方法不会导致原对象改变且会返回一个新的对象。
  140. ''' </summary>
  141. Public Function RotateFlip(Type As System.Drawing.RotateFlipType) As MyBitmap
  142. Dim bmp As New System.Drawing.Bitmap(Pic)
  143. bmp.SetResolution(Pic.HorizontalResolution, Pic.VerticalResolution)
  144. bmp.RotateFlip(Type)
  145. Return bmp
  146. End Function
  147. ''' <summary>
  148. ''' 将图像保存到文件。
  149. ''' </summary>
  150. Public Sub Save(FilePath As String)
  151. Dim encoder As BitmapEncoder = New PngBitmapEncoder()
  152. encoder.Frames.Add(BitmapFrame.Create(Me))
  153. Using fileStream As New FileStream(FilePath, FileMode.Create)
  154. encoder.Save(fileStream)
  155. End Using
  156. End Sub
  157. End Class