如何调整大小和图像并另存为字节数组
How to resize and image and save as byte array
我试图让用户 select 一个图像文件,然后根据需要将图像调整为几个不同的大小,然后将调整后的图像保存到字节数组中,这些字节数组将保存到数据库中。将图像转换为字节数组时,我不断收到错误消息(但前提是图像已调整大小)。希望有人能告诉我我做错了什么。
仅供参考,我不是专业程序员,当我 post 我的代码时通常会受到严厉批评。我绝对乐于接受您的任何反馈或建议,所以请保持友好..lol
我通常在 Image.Save(mStream, TheImage.RawFormat) 行的 SaveImage() 函数中遇到此错误
System.ArgumentNullException: 'Value cannot be null. Parameter name: encoder'
有时我会遇到框架错误,但无法真正判断错误发生在何处。
编辑:我最终扩展了图像 class,到目前为止它似乎工作得很好。
Imports System.Drawing.Imaging
Imports System.IO
Module Extentions
<Runtime.CompilerServices.Extension()>
Public Function GetBytes(ByRef bc As Image, Optional Format As ImageFormat = Nothing) As Byte()
'Converts Image to Byte Array
If Format Is Nothing Then Format = ImageFormat.Jpeg
Using mStream As New MemoryStream()
bc.Save(mStream, Format)
Return mStream.ToArray()
End Using
End Function
<Runtime.CompilerServices.Extension()>
Public Function ReSize(ByRef bc As Image, MaxWidth As Integer, MaxHeight As Integer) As Image
'Resize image to fit within MaxWidth & MaxHeight while keeping aspect ratio
If MaxWidth < bc.Width Or MaxHeight < bc.Height Then
Dim Scale As Double = Math.Min(MaxWidth / bc.Width, MaxHeight / bc.Height)
Dim NewWidth As Integer = CInt(Math.Round(bc.Width * Scale))
Dim NewHeight As Integer = CInt(Math.Round(bc.Height * Scale))
Return New Bitmap(bc, New Size(NewWidth, NewHeight))
Else
Return bc
End If
End Function
End Module
现在,我以前处理的表单中的代码简单多了..
Private Sub SelectImage_Click(sender As Object, e As EventArgs) Handles SelectImage.Click
Dim Popup As New OpenFileDialog
With Popup
.Filter = "Images|*.gif;*.png;*.jpg;*.bmp"
.Title = "Select Image"
.FileName = ""
.FilterIndex = 1
.Multiselect = False
.RestoreDirectory = True
End With
If Popup.ShowDialog = vbOK Then
'Load Image from disk
OriginalImage = Image.FromFile(Popup.FileName)
'Resize and display image on form
Picture.Image = OriginalImage.ReSize(200, 150)
'Save Large Image
FullImage = OriginalImage.ReSize(400, 300).GetBytes
'Save Small Image
SmallImage = OriginalImage.ReSize(100, 75).GetBytes
ImageSelected = True
End If
End Sub
这是我的原始代码...
Private OriginalImage As Image
Private FullImage As Byte()
Private SmallImage As Byte()
Private ImageSelected As Boolean
Private Sub SelectImage_Click(sender As Object, e As EventArgs) Handles SelectImage.Click
Dim Popup As New OpenFileDialog
With Popup
.Filter = "Images|*.gif;*.png;*.jpg;*.bmp"
.Title = "Select Image"
.FileName = ""
.FilterIndex = 1
.Multiselect = False
.RestoreDirectory = True
End With
If Popup.ShowDialog = vbOK Then
'Load Image from disk
OriginalImage = Image.FromFile(Popup.FileName)
'Resize and display image on form
Picture.Image = ResizeImage(OriginalImage, 200, 150)
'Save Large Image
Dim ResizedImage As Image = ResizeImage(OriginalImage, 400, 300)
FullImage = SaveImage(ResizedImage)
'Save Small Image
ResizedImage = ResizeImage(OriginalImage, 100, 75)
SmallImage = SaveImage(ResizedImage)
ImageSelected = True
End If
End Sub
Private Function ResizeImage(ByRef InputImage As Image, MaxWidth As Integer, MaxHeight As Integer) As Image
'ReSize the Image if needed to save space in the database
If MaxWidth < InputImage.Width Or MaxHeight < InputImage.Height Then
'ReSize Image
Dim Scale As Double = Math.Min(MaxWidth / InputImage.Width, MaxHeight / InputImage.Height)
Return New Bitmap(InputImage, New Size(Math.Round(InputImage.Width * Scale), Math.Round(InputImage.Height * Scale)))
Else
'Image size was OK
Return InputImage
End If
End Function
Private Function GetImage(ImageData As Byte()) As Image
'Converts Byte Array to Image
Using mStream As New MemoryStream(ImageData)
Return Image.FromStream(mStream)
End Using
End Function
Private Function SaveImage(TheImage As Image) As Byte()
'Converts Image to Byte Array
Using mStream As New MemoryStream()
TheImage.Save(mStream, TheImage.RawFormat)
Return mStream.ToArray()
End Using
End Function
'These are functions I was playing around with because I was getting
'System.ArgumentNullException: 'Value cannot be null. Parameter name: encoder'
'in the SaveImage() function on TheImage.Save(mStream, TheImage.RawFormat)
'and I wasn't using the encoder parameter. I couldn't get these to help me though.
Private Function SaveImage2(TheImage As Image) As Byte()
'Converts Image to Byte Array
Dim CodecInfo As Imaging.ImageCodecInfo = GetEncoderInfo("image/jpeg")
Dim Parameters As New Imaging.EncoderParameters(1)
Parameters.Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, 75L)
Using mStream As New MemoryStream()
TheImage.Save(mStream, CodecInfo, Parameters)
Return mStream.ToArray()
End Using
End Function
Private Function GetEncoderInfo(MimeType As String) As Imaging.ImageCodecInfo
Dim encoders As Imaging.ImageCodecInfo()
encoders = Imaging.ImageCodecInfo.GetImageEncoders()
For j As Integer = 0 To encoders.Length - 1
If encoders(j).MimeType = MimeType Then Return encoders(j)
Next
Return Nothing
End Function
当您使用此构造函数创建新位图时:
new Bitmap([OriginalImage], [Width], [Height])
您可能认为考虑了 [OriginalImage]
格式。不是。将创建具有指定大小的新原始位图,并在新容器内绘制 [OriginalImage]
。
在内存中创建了新的Bitmap对象,其ImageFormat为ImageFormat.MemoryBmp
.
这个 ImageFormat
没有 Encoder/Decoder。
当您使用传递新位图对象 RawFormat
的 Image.Save(Stream, Format) 方法重载保存图像时,您传递的是 ImageFormat.MemoryBmp
.
图像 class 然后尝试从指定的 ImageFormat
获取编码器(使用内部 FindEncoder() 方法),这当然是 returns null
,导致异常:
System.ArgumentNullException: 'Value cannot be null. Parameter name:
encoder'
你可以自己测试一下,尝试从OriginalImage
和ResizedImage
对象中获取Encoder/Decoder(使用ImageCodecInfo.GetImageDecoders() or ImageCodecInfo.GetImageEncoders()):
Dim originalCodec As ImageCodecInfo = ImageCodecInfo.GetImageDecoders().
FirstOrDefault(Function(cc) cc.FormatID.Equals(ResizedImage.RawFormat.Guid))
您会看到,当您尝试获取 ResizedImage
格式的 Encoder/Decoder 时,originalCodec
将为空 (nothing
),而它会return OriginalImage
格式的 Encoder/Decoder。
由于预定义的 ImageFormat
是 ImageFormat.Png
,您可以更改将图像保存到 MemoryStream
时设置此格式的方法:
Using mStream As New MemoryStream()
TheImage.Save(mStream, ImageFormat.Png)
Return mStream.ToArray()
End Using
某件事在内部也不止一次做过。
例如:Image.Save(MemoryStream stream)
我试图让用户 select 一个图像文件,然后根据需要将图像调整为几个不同的大小,然后将调整后的图像保存到字节数组中,这些字节数组将保存到数据库中。将图像转换为字节数组时,我不断收到错误消息(但前提是图像已调整大小)。希望有人能告诉我我做错了什么。
仅供参考,我不是专业程序员,当我 post 我的代码时通常会受到严厉批评。我绝对乐于接受您的任何反馈或建议,所以请保持友好..lol
我通常在 Image.Save(mStream, TheImage.RawFormat) 行的 SaveImage() 函数中遇到此错误 System.ArgumentNullException: 'Value cannot be null. Parameter name: encoder'
有时我会遇到框架错误,但无法真正判断错误发生在何处。
编辑:我最终扩展了图像 class,到目前为止它似乎工作得很好。
Imports System.Drawing.Imaging
Imports System.IO
Module Extentions
<Runtime.CompilerServices.Extension()>
Public Function GetBytes(ByRef bc As Image, Optional Format As ImageFormat = Nothing) As Byte()
'Converts Image to Byte Array
If Format Is Nothing Then Format = ImageFormat.Jpeg
Using mStream As New MemoryStream()
bc.Save(mStream, Format)
Return mStream.ToArray()
End Using
End Function
<Runtime.CompilerServices.Extension()>
Public Function ReSize(ByRef bc As Image, MaxWidth As Integer, MaxHeight As Integer) As Image
'Resize image to fit within MaxWidth & MaxHeight while keeping aspect ratio
If MaxWidth < bc.Width Or MaxHeight < bc.Height Then
Dim Scale As Double = Math.Min(MaxWidth / bc.Width, MaxHeight / bc.Height)
Dim NewWidth As Integer = CInt(Math.Round(bc.Width * Scale))
Dim NewHeight As Integer = CInt(Math.Round(bc.Height * Scale))
Return New Bitmap(bc, New Size(NewWidth, NewHeight))
Else
Return bc
End If
End Function
End Module
现在,我以前处理的表单中的代码简单多了..
Private Sub SelectImage_Click(sender As Object, e As EventArgs) Handles SelectImage.Click
Dim Popup As New OpenFileDialog
With Popup
.Filter = "Images|*.gif;*.png;*.jpg;*.bmp"
.Title = "Select Image"
.FileName = ""
.FilterIndex = 1
.Multiselect = False
.RestoreDirectory = True
End With
If Popup.ShowDialog = vbOK Then
'Load Image from disk
OriginalImage = Image.FromFile(Popup.FileName)
'Resize and display image on form
Picture.Image = OriginalImage.ReSize(200, 150)
'Save Large Image
FullImage = OriginalImage.ReSize(400, 300).GetBytes
'Save Small Image
SmallImage = OriginalImage.ReSize(100, 75).GetBytes
ImageSelected = True
End If
End Sub
这是我的原始代码...
Private OriginalImage As Image
Private FullImage As Byte()
Private SmallImage As Byte()
Private ImageSelected As Boolean
Private Sub SelectImage_Click(sender As Object, e As EventArgs) Handles SelectImage.Click
Dim Popup As New OpenFileDialog
With Popup
.Filter = "Images|*.gif;*.png;*.jpg;*.bmp"
.Title = "Select Image"
.FileName = ""
.FilterIndex = 1
.Multiselect = False
.RestoreDirectory = True
End With
If Popup.ShowDialog = vbOK Then
'Load Image from disk
OriginalImage = Image.FromFile(Popup.FileName)
'Resize and display image on form
Picture.Image = ResizeImage(OriginalImage, 200, 150)
'Save Large Image
Dim ResizedImage As Image = ResizeImage(OriginalImage, 400, 300)
FullImage = SaveImage(ResizedImage)
'Save Small Image
ResizedImage = ResizeImage(OriginalImage, 100, 75)
SmallImage = SaveImage(ResizedImage)
ImageSelected = True
End If
End Sub
Private Function ResizeImage(ByRef InputImage As Image, MaxWidth As Integer, MaxHeight As Integer) As Image
'ReSize the Image if needed to save space in the database
If MaxWidth < InputImage.Width Or MaxHeight < InputImage.Height Then
'ReSize Image
Dim Scale As Double = Math.Min(MaxWidth / InputImage.Width, MaxHeight / InputImage.Height)
Return New Bitmap(InputImage, New Size(Math.Round(InputImage.Width * Scale), Math.Round(InputImage.Height * Scale)))
Else
'Image size was OK
Return InputImage
End If
End Function
Private Function GetImage(ImageData As Byte()) As Image
'Converts Byte Array to Image
Using mStream As New MemoryStream(ImageData)
Return Image.FromStream(mStream)
End Using
End Function
Private Function SaveImage(TheImage As Image) As Byte()
'Converts Image to Byte Array
Using mStream As New MemoryStream()
TheImage.Save(mStream, TheImage.RawFormat)
Return mStream.ToArray()
End Using
End Function
'These are functions I was playing around with because I was getting
'System.ArgumentNullException: 'Value cannot be null. Parameter name: encoder'
'in the SaveImage() function on TheImage.Save(mStream, TheImage.RawFormat)
'and I wasn't using the encoder parameter. I couldn't get these to help me though.
Private Function SaveImage2(TheImage As Image) As Byte()
'Converts Image to Byte Array
Dim CodecInfo As Imaging.ImageCodecInfo = GetEncoderInfo("image/jpeg")
Dim Parameters As New Imaging.EncoderParameters(1)
Parameters.Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, 75L)
Using mStream As New MemoryStream()
TheImage.Save(mStream, CodecInfo, Parameters)
Return mStream.ToArray()
End Using
End Function
Private Function GetEncoderInfo(MimeType As String) As Imaging.ImageCodecInfo
Dim encoders As Imaging.ImageCodecInfo()
encoders = Imaging.ImageCodecInfo.GetImageEncoders()
For j As Integer = 0 To encoders.Length - 1
If encoders(j).MimeType = MimeType Then Return encoders(j)
Next
Return Nothing
End Function
当您使用此构造函数创建新位图时:
new Bitmap([OriginalImage], [Width], [Height])
您可能认为考虑了 [OriginalImage]
格式。不是。将创建具有指定大小的新原始位图,并在新容器内绘制 [OriginalImage]
。
在内存中创建了新的Bitmap对象,其ImageFormat为ImageFormat.MemoryBmp
.
这个 ImageFormat
没有 Encoder/Decoder。
当您使用传递新位图对象 RawFormat
的 Image.Save(Stream, Format) 方法重载保存图像时,您传递的是 ImageFormat.MemoryBmp
.
图像 class 然后尝试从指定的 ImageFormat
获取编码器(使用内部 FindEncoder() 方法),这当然是 returns null
,导致异常:
System.ArgumentNullException: 'Value cannot be null. Parameter name: encoder'
你可以自己测试一下,尝试从OriginalImage
和ResizedImage
对象中获取Encoder/Decoder(使用ImageCodecInfo.GetImageDecoders() or ImageCodecInfo.GetImageEncoders()):
Dim originalCodec As ImageCodecInfo = ImageCodecInfo.GetImageDecoders().
FirstOrDefault(Function(cc) cc.FormatID.Equals(ResizedImage.RawFormat.Guid))
您会看到,当您尝试获取 ResizedImage
格式的 Encoder/Decoder 时,originalCodec
将为空 (nothing
),而它会return OriginalImage
格式的 Encoder/Decoder。
由于预定义的 ImageFormat
是 ImageFormat.Png
,您可以更改将图像保存到 MemoryStream
时设置此格式的方法:
Using mStream As New MemoryStream()
TheImage.Save(mStream, ImageFormat.Png)
Return mStream.ToArray()
End Using
某件事在内部也不止一次做过。
例如:Image.Save(MemoryStream stream)