如何在图像缩放后保存具有原始位深度的图像?
问题
使用以下VB.NET代码对图像进行缩放保存时,原始文件位深度为8bit,但缩放后保存的图像位深度变为24bit,如何实现保存时保留原始位深度?
Dim strFolder = "E:\test\" Dim oFile = strFolder & "a.png" If oFile.ToString.ToLower.Contains(".png") Or oFile.ToString.ToLower.Contains(".jpg") Or oFile.ToString.ToLower.Contains(".jpeg") Then Dim strFileName = System.IO.Path.GetFileName(oFile) Try Dim original As Image = Image.FromFile(oFile) ' Calculate the scaled dimensions Dim w As Integer = CInt(original.Width * 0.9) Dim h As Integer = CInt(original.Height * 0.9) Dim encoderParams = New EncoderParameters(1) encoderParams.Param(0) = New EncoderParameter(Encoder.ColorDepth, 8L) Dim resized As Image = New Bitmap(original, New Size(w, h)) Dim memStream As MemoryStream = New MemoryStream() resized.Save(memStream, getCodec("image/jpeg"), encoderParams) Dim file As New FileStream(strFolder & "905_" & strFileName, FileMode.Create, FileAccess.Write) memStream.WriteTo(file) file.Close() memStream.Close() Catch ex As Exception End Try End If End Sub Public Function getCodec(getThis) As Drawing.Imaging.ImageCodecInfo Dim output As Drawing.Imaging.ImageCodecInfo Dim codecs As Imaging.ImageCodecInfo() = Imaging.ImageCodecInfo.GetImageEncoders For Each codec As Imaging.ImageCodecInfo In codecs If codec.MimeType = getThis Then output = codec End If Next codec Return output End Function
解决方案
问题原因
- 调用
New Bitmap(original, New Size(w, h))创建缩放图像时,默认会生成24位RGB格式的Bitmap,直接忽略原始图像的8位像素格式。 - 代码强制使用JPEG编码器,但JPEG格式仅支持8位灰度或24位彩色,不支持8位索引色;且编码器参数无法改变Bitmap本身已确定的像素格式。
修改步骤及代码
要保留原始位深度,需在创建缩放图像时指定与原始一致的像素格式,并根据图像类型匹配对应编码器:
Dim strFolder = "E:\test\" Dim oFile = strFolder & "a.png" Dim lowerFileName = oFile.ToLower() If lowerFileName.Contains(".png") Or lowerFileName.Contains(".jpg") Or lowerFileName.Contains(".jpeg") Then Dim strFileName = System.IO.Path.GetFileName(oFile) Try Dim original As Image = Image.FromFile(oFile) ' 获取原始图像的像素格式 Dim originalPixelFormat = original.PixelFormat ' 计算缩放尺寸 Dim w As Integer = CInt(original.Width * 0.9) Dim h As Integer = CInt(original.Height * 0.9) ' 创建与原始像素格式一致的缩放Bitmap Dim resized As New Bitmap(w, h, originalPixelFormat) ' 使用Graphics绘制缩放图像,避免自动格式转换 Using g As Graphics = Graphics.FromImage(resized) g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic g.DrawImage(original, New Rectangle(0, 0, w, h)) End Using Dim encoderParams As EncoderParameters = Nothing Dim codec As Drawing.Imaging.ImageCodecInfo = Nothing ' 根据图像类型选择编码器并设置对应参数 If lowerFileName.Contains(".png") Then codec = getCodec("image/png") ' 针对PNG的8位索引色设置颜色深度参数 encoderParams = New EncoderParameters(1) encoderParams.Param(0) = New EncoderParameter(Encoder.ColorDepth, 8L) Else codec = getCodec("image/jpeg") ' 针对8位灰度JPEG设置颜色深度与质量参数 encoderParams = New EncoderParameters(2) encoderParams.Param(0) = New EncoderParameter(Encoder.ColorDepth, 8L) encoderParams.Param(1) = New EncoderParameter(Encoder.Quality, 90L) End If ' 使用Using语句自动释放资源 Using memStream As New MemoryStream() resized.Save(memStream, codec, encoderParams) Using file As New FileStream(strFolder & "905_" & strFileName, FileMode.Create, FileAccess.Write) memStream.WriteTo(file) End Using End Using original.Dispose() resized.Dispose() Catch ex As Exception ' 可添加异常日志记录等处理逻辑 End Try End If End Sub Public Function getCodec(getThis As String) As Drawing.Imaging.ImageCodecInfo For Each codec As Imaging.ImageCodecInfo In Imaging.ImageCodecInfo.GetImageEncoders If codec.MimeType = getThis Then Return codec End If Next codec Return Nothing End Function
关键说明
- 创建Bitmap时指定
originalPixelFormat,确保缩放后图像的像素格式与原始一致。 - 用
Graphics.DrawImage完成缩放操作,避免Bitmap构造函数自动转换格式。 - 区分PNG与JPEG格式选择对应编码器:PNG支持8位索引色,JPEG仅支持8位灰度(若原始为8位灰度JPEG)。
- 使用
Using语句自动释放流与图像资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者D T
相关产品推荐
相关产品推荐

