Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Windows.Forms

Namespace ImageProcessor
    Public Class ImageProcessor
        Public Shared Function GetBitmapImage(path As String) As Image
            Using fileStream As New FileStream(path, FileMode.Open, FileAccess.Read)
                Dim byteLength As Integer = CInt(fileStream.Length)
                Dim fileBytes(byteLength - 1) As Byte
                fileStream.Read(fileBytes, 0, byteLength)
                fileStream.Close()
                Return Image.FromStream(New MemoryStream(fileBytes))
            End Using
        End Function

        Public Shared Function ImagePathToBytes(path As String) As Byte()
            Using fileStream As New FileStream(path, FileMode.Open, FileAccess.Read)
                Dim byteLength As Integer = CInt(fileStream.Length)
                Dim fileBytes(byteLength - 1) As Byte
                fileStream.Read(fileBytes, 0, byteLength)
                fileStream.Close()
                Return fileBytes
            End Using
        End Function

        ''' <summary>
        ''' 将图像格式转换为二进制数组,以jpeg的格式
        ''' </summary>
        ''' <param name="img"></param>
        ''' <returns></returns>
        Public Shared Function ImageToBytes(img As Image) As Byte()
            Dim ms As New MemoryStream()
            If img Is Nothing Then Return New Byte() {}
            img.Save(ms, ImageFormat.Jpeg)
            Return ms.GetBuffer()
        End Function

        ''' <summary>
        ''' 将图像格式转换为二进制数组
        ''' </summary>
        ''' <param name="img">图像</param>
        ''' <param name="format">图像格式</param>
        ''' <returns></returns>
        Public Shared Function ImageToBytes(img As Image, format As ImageFormat) As Byte()
            Dim ms As New MemoryStream()
            If img Is Nothing Then Return New Byte() {}
            img.Save(ms, format)
            Return ms.GetBuffer()
        End Function

        ''' <summary>
        ''' 将二进制数组转换为图像格式
        ''' </summary>
        ''' <param name="bytes"></param>
        ''' <returns></returns>
        Public Shared Function BytesToImage(bytes() As Byte) As Image
            Dim ms As New MemoryStream(bytes)
            Dim img As Image = Nothing
            Try
                img = Image.FromStream(ms)
            Catch ex As Exception
                Console.WriteLine($"BytesToImage Error:{ex.Message}")
            End Try
            Return img
        End Function


        ''' <summary>
        ''' 将图片变更为String格式,默认PNG格式保存
        ''' </summary>
        ''' <param name="img"></param>
        ''' <returns></returns>
        Public Shared Function ImageToString(img As Image) As String
            If img Is Nothing Then Return String.Empty
            Using ms As New MemoryStream()
                img.Save(ms, ImageFormat.Png) 'png格式支持存储文件中并还原,其他格式存在问题
                Dim buffer6() As Byte = ms.GetBuffer

                Return Convert.ToBase64String(buffer6)
            End Using
        End Function

        ''' <summary>
        ''' 将图片变更为String格式
        ''' </summary>
        ''' <param name="img"></param>
        ''' <param name="format">保存格式</param>
        ''' <returns></returns>
        Public Shared Function ImageToString(img As Image, format As Imaging.ImageFormat) As String
            If img Is Nothing Then Return String.Empty
            Using ms As New MemoryStream()
                img.Save(ms, format)
                Dim buffer() As Byte = ms.GetBuffer
                Return Convert.ToBase64String(buffer)
            End Using
        End Function




        ''' <summary>
        ''' 将图片string还原为图片格式
        ''' </summary>
        ''' <param name="imgString"></param>
        ''' <returns></returns>
        Public Shared Function StringToImage(imgString As String) As Image
            If String.IsNullOrEmpty(imgString) Then Return Nothing
            Using ms As New MemoryStream(Convert.FromBase64String(imgString))
                Return Image.FromStream(ms, True)
            End Using
        End Function

        ''' <summary>
        ''' 压缩图像到指定的高度与宽度
        ''' </summary>
        ''' <param name="bitmap">图像</param>
        ''' <param name="maxWidth">指定的宽度</param>
        ''' <param name="maxHeight">指定的高度</param>
        ''' <returns></returns>
        Public Shared Function CompressImageWithSize(bitmap As Image, Optional maxWidth As Integer = 120, Optional maxHeight As Integer = 90) As System.Drawing.Bitmap
            If bitmap Is Nothing Then Return Nothing

            Dim actualWidth As Integer = CInt(IIf(bitmap.Width < maxWidth, bitmap.Width, maxWidth))
            Dim actualHeight As Integer = CInt(IIf(bitmap.Height < maxHeight, bitmap.Height, maxHeight))
            Dim actualBitmap As New System.Drawing.Bitmap(actualWidth, actualHeight)

            Using g As Graphics = System.Drawing.Graphics.FromImage(actualBitmap)
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default
                g.DrawImage(bitmap, New System.Drawing.Rectangle(0, 0, actualWidth, actualHeight), New System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.GraphicsUnit.Pixel)
            End Using

            Return actualBitmap
        End Function

        ''' <summary>
        ''' 压缩图像,根据宽度比
        ''' </summary>
        ''' <param name="bitmap">图像</param>
        ''' <param name="maxWidth">指定的宽度</param>
        ''' <returns></returns>
        Public Shared Function CompressImageWithWidth(bitmap As Bitmap, Optional maxWidth As Integer = 600) As System.Drawing.Bitmap
            If bitmap Is Nothing Then Return Nothing
            If bitmap.Width = maxWidth Then Return bitmap

            Dim actualWidth As Integer = CInt(IIf(bitmap.Width < maxWidth, bitmap.Width, maxWidth))
            Dim actualHeight As Integer = CInt(Math.Round(bitmap.Height * (actualWidth / bitmap.Width)))

            Dim actualBitmap As New System.Drawing.Bitmap(actualWidth, actualHeight)

            Using g As Graphics = System.Drawing.Graphics.FromImage(actualBitmap)
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default
                g.DrawImage(bitmap, New System.Drawing.Rectangle(0, 0, actualWidth, actualHeight), New System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.GraphicsUnit.Pixel)
            End Using
            Return actualBitmap
        End Function


        ''' <summary>
        ''' 压缩图像,根据高度比
        ''' </summary>
        ''' <param name="bitmap">图像</param>
        ''' <param name="maxHeight">指定的高度</param>
        ''' <returns></returns>
        Public Shared Function CompressImageWithHeight(bitmap As Bitmap, Optional maxHeight As Integer = 450) As System.Drawing.Bitmap
            If bitmap Is Nothing Then Return Nothing
            If bitmap.Height < maxHeight Then Return bitmap

            Dim actualHeight As Integer = CInt(IIf(bitmap.Height < maxHeight, bitmap.Height, maxHeight))
            Dim actualWidth As Integer = CInt(Math.Round(bitmap.Width * (actualHeight / bitmap.Height)))

            Dim actualBitmap As New System.Drawing.Bitmap(actualWidth, actualHeight)

            Using g As Graphics = System.Drawing.Graphics.FromImage(actualBitmap)
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default
                g.DrawImage(bitmap, New System.Drawing.Rectangle(0, 0, actualWidth, actualHeight), New System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.GraphicsUnit.Pixel)
            End Using
            Return actualBitmap
        End Function


        ''' <summary>
        ''' 按指定比例有损的压缩图像
        ''' </summary>
        ''' <param name="bitmap"></param>
        ''' <param name="encoding"></param>
        ''' <param name="quality"></param>
        ''' <returns></returns>
        Public Shared Function CompressImageWithQuality(bitmap As Bitmap, encoding As Imaging.ImageCodecInfo, Optional quality As Integer = 20) As Bitmap
            If bitmap Is Nothing Then Return Nothing
            Dim ps As New System.Drawing.Imaging.EncoderParameters(1)
            ps.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality)

            Dim ms As New MemoryStream
            bitmap.Save(ms, encoding, ps)

            Dim compressedBitmap As New System.Drawing.Bitmap(ms)

            Return compressedBitmap
        End Function

        ''' <summary>
        ''' 获取图片的代码器信息
        ''' </summary>
        ''' <returns></returns>
        Public Shared Function GetImageEncoders() As Dictionary(Of String, System.Drawing.Imaging.ImageCodecInfo)
            Dim result As New Dictionary(Of String, System.Drawing.Imaging.ImageCodecInfo)
            Dim encoders As List(Of ImageCodecInfo) = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders().ToList()

            For Each encode As ImageCodecInfo In encoders
                result.Add(encode.MimeType, encode)
            Next
            Return result
        End Function

        ''' <summary>
        ''' 截取整个电脑屏幕
        ''' </summary>
        ''' <returns></returns>
        Public Shared Function CaptureScreen() As Image
            Dim startPoint As New Point(0, 0)
            Dim regionSize As New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
            Dim pic As New Bitmap(regionSize.Width, regionSize.Height)

            Using g As Graphics = Graphics.FromImage(pic)
                g.CopyFromScreen(startPoint, startPoint, regionSize)
            End Using

            Return pic
        End Function

        ''' <summary>
        ''' 截取整个电脑屏幕,并指定文件路径下生成jpg格式文件。
        ''' </summary>
        Public Shared Sub SaveScreenCapture(path As String)
            Dim startPoint As New Point(0, 0)
            Dim regionSize As New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
            Dim pic As New Bitmap(regionSize.Width, regionSize.Height)

            Using g As Graphics = Graphics.FromImage(pic)
                g.CopyFromScreen(startPoint, startPoint, regionSize)
                pic.Save(path, ImageFormat.Jpeg)
            End Using

        End Sub
    End Class
End Namespace