VS2010(VB.Net)中JPG缩放保存后颜色变暗的解决方法咨询
解决JPG缩放后颜色暗淡的问题
这个问题我之前在VB.NET项目里也踩过坑!颜色变暗、饱和度降低的核心原因是System.Drawing.Graphics默认启用了颜色管理(ICM),会自动根据系统颜色配置文件调整图像颜色,再加上Bitmap创建和JPEG编码器的默认行为,最终导致原图的鲜亮色彩被削弱。咱们一步步修改代码来解决:
核心修改点
1. 禁用Graphics的自动颜色校正
创建绘图对象后,必须关闭颜色管理相关设置,避免它自动转换颜色。同时把插值模式换成更高质量的HighQualityBicubic,缩放后的细节和色彩会更接近原图:
objGraphics = Graphics.FromImage(imgJPEG_New) With objGraphics .SmoothingMode = Drawing2D.SmoothingMode.HighQuality .InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic ' 替换原High模式 .PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality .CompositingQuality = Drawing2D.CompositingQuality.HighQuality .CompositingMode = Drawing2D.CompositingMode.SourceCopy ' 避免颜色混合失真 .ImageRenderingFormat = Imaging.PixelFormat.Format24bppRgb ' 强制使用RGB格式 .DrawImage(imgJPEG_Current, 0, 0, imgJPEG_New.Width, imgJPEG_New.Height) .Dispose() End With
2. 显式指定Bitmap的像素格式
不要直接复用原图像的像素格式(有些JPG可能带有特殊标记),显式指定Format24bppRgb可以确保色彩空间一致:
imgJPEG_New = New Bitmap( CInt(imgJPEG_Current.Width * dblRatio), CInt(imgJPEG_Current.Height * dblRatio), Imaging.PixelFormat.Format24bppRgb ' 显式指定24位RGB )
3. 加载图片时跳过颜色配置文件
Image.FromFile默认会加载图像嵌入的颜色配置文件,导致后续绘图时自动校正颜色。改用Bitmap.FromStream并禁用颜色管理:
' 替换原Image.FromFile代码 Using fs As New FileStream(strFilePhysicalPath_Original, FileMode.Open, FileAccess.Read) imgJPEG_Current = Bitmap.FromStream(fs, False, False) ' 最后一个False禁用颜色管理 End Using
4. 优化编码器参数
你的现有参数已经设置了高质量,但可以补充Encoder.ColorTransform参数来确保颜色空间不被转换:
' 先调整编码器参数数量为4 Dim arrEncoderParameters = New Imaging.EncoderParameters(4) With arrEncoderParameters .Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, 100L) .Param(1) = New Imaging.EncoderParameter(Imaging.Encoder.ColorDepth, 24) .Param(2) = New Imaging.EncoderParameter(Imaging.Encoder.Compression, Imaging.EncoderValue.CompressionNone) .Param(3) = New Imaging.EncoderParameter(Imaging.Encoder.ColorTransform, Imaging.EncoderValue.ColorTransformNone) End With
修改后的完整代码片段
'*************************************** ' Constants '*************************************** Const DECREASE_RATIO As Double = 10.0 '*************************************** ' Initialize Variables '*************************************** Dim dblRatio As Double = (100 - DECREASE_RATIO) * 0.01 Dim objGraphics As System.Drawing.Graphics Dim imgJPEG_Current As System.Drawing.Image = Nothing Dim imgJPEG_New As System.Drawing.Bitmap = Nothing Dim objJPGCodec As Imaging.ImageCodecInfo = Nothing ' 调整编码器参数数量为4 Dim arrEncoderParameters = New Imaging.EncoderParameters(4) '*************************************** ' Default Values '*************************************** With arrEncoderParameters .Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, 100L) .Param(1) = New Imaging.EncoderParameter(Imaging.Encoder.ColorDepth, 24) .Param(2) = New Imaging.EncoderParameter(Imaging.Encoder.Compression, Imaging.EncoderValue.CompressionNone) .Param(3) = New Imaging.EncoderParameter(Imaging.Encoder.ColorTransform, Imaging.EncoderValue.ColorTransformNone) End With '*************************************** ' Get JPEG Codec '*************************************** For Each objCodec As Imaging.ImageCodecInfo In Imaging.ImageCodecInfo.GetImageDecoders() If (objCodec.FormatID = Imaging.ImageFormat.Jpeg.Guid) Then objJPGCodec = objCodec Exit For End If Next '*************************************** ' Load Current Image To Process (禁用颜色管理) '*************************************** Using fs As New FileStream(strFilePhysicalPath_Original, FileMode.Open, FileAccess.Read) imgJPEG_Current = Bitmap.FromStream(fs, False, False) End Using '*************************************** ' Create Clone Of Current Image Resized Using New Size Ratio '*************************************** imgJPEG_New = New Bitmap( CInt(imgJPEG_Current.Width * dblRatio), CInt(imgJPEG_Current.Height * dblRatio), Imaging.PixelFormat.Format24bppRgb ) objGraphics = Graphics.FromImage(imgJPEG_New) With objGraphics .SmoothingMode = Drawing2D.SmoothingMode.HighQuality .InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic .PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality .CompositingQuality = Drawing2D.CompositingQuality.HighQuality .CompositingMode = Drawing2D.CompositingMode.SourceCopy .ImageRenderingFormat = Imaging.PixelFormat.Format24bppRgb .DrawImage(imgJPEG_Current, 0, 0, imgJPEG_New.Width, imgJPEG_New.Height) .Dispose() End With '*************************************** ' Save New JPG File To Disk '*************************************** imgJPEG_New.Save(strFilePhysicalPath_Delta, objJPGCodec, arrEncoderParameters) ' 记得释放资源! imgJPEG_Current.Dispose() imgJPEG_New.Dispose()
额外提醒
别忘了在代码最后手动释放imgJPEG_Current和imgJPEG_New的资源,避免内存泄漏。这样修改后,缩放后的JPG颜色应该和原图几乎一致,同时保持小尺寸。
内容的提问来源于stack exchange,提问作者TekkGuy
相关产品推荐
相关产品推荐

