从数据库检索图片时画质变差且背景变黑的问题求助
问题解决方法
问题根源
- 背景变黑:你的原图是带透明通道的PNG格式,但保存时强制转成了JPEG——JPEG不支持透明,透明区域会被自动填充为黑色。
- 画质下降:直接调用
Image.Save保存JPEG时用了默认压缩参数,压缩率过高导致画质严重损失。 - 数据冗余异常:用
MemoryStream.GetBuffer()获取字节数组,它返回的是内存流的整个缓冲区(包含未使用的空字节),可能导致读取时解析异常。
修正方案
方案1:保留透明背景(存为PNG格式)
修改保存代码,以PNG格式存入数据库,完整保留透明通道:
Dim mstream As New System.IO.MemoryStream() Try ' 保存为PNG格式,保留透明属性 PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Png) Catch ex As Exception MessageBox.Show("图片保存失败:" & ex.Message) Return End Try ' 使用ToArray()获取实际有效字节数据,避免冗余空字节 Dim arrimage() As Byte = mstream.ToArray() mstream.Close() CMD = New SqlCommand("Update setting_TBL set Image_Value=@p1 Where Setting_name=@p2", sqlcon) CMD.Parameters.AddWithValue("@p1", arrimage) CMD.Parameters.AddWithValue("@p2", "Company_Logo") CMD.ExecuteNonQuery() ' 别忘了执行更新命令
方案2:必须用JPEG格式(处理透明+提高画质)
如果业务要求必须存JPEG,需要先替换透明背景为白色(或指定颜色),同时设置高质量压缩参数:
Dim mstream As New System.IO.MemoryStream() Try ' 创建带白色背景的画布,覆盖原图透明区域 Dim bmp As New Bitmap(PictureBox1.Image.Width, PictureBox1.Image.Height) Using g As Graphics = Graphics.FromImage(bmp) g.Clear(Color.White) g.DrawImage(PictureBox1.Image, 0, 0) End Using ' 设置JPEG高质量保存参数(质量值0-100,越高画质越好) Dim jpegParams As New System.Drawing.Imaging.EncoderParameters(1) jpegParams.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L) Dim jpegCodec As ImageCodecInfo = GetEncoder(ImageFormat.Jpeg) ' 保存高质量JPEG bmp.Save(mstream, jpegCodec, jpegParams) bmp.Dispose() Catch ex As Exception MessageBox.Show("图片保存失败:" & ex.Message) Return End Try Dim arrimage() As Byte = mstream.ToArray() mstream.Close() CMD = New SqlCommand("Update setting_TBL set Image_Value=@p1 Where Setting_name=@p2", sqlcon) CMD.Parameters.AddWithValue("@p1", arrimage) CMD.Parameters.AddWithValue("@p2", "Company_Logo") CMD.ExecuteNonQuery()
需要补充辅助函数获取JPEG编码器:
Private Function GetEncoder(format As ImageFormat) As ImageCodecInfo Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageDecoders() For Each codec As ImageCodecInfo In codecs If codec.FormatID = format.Guid Then Return codec End If Next Return Nothing End Function
检索代码优化
检索时不要提前关闭MemoryStream,Image.FromStream需要流保持打开状态:
Dim Da As New SqlDataAdapter Dim DT As New DataTable Da = New SqlDataAdapter("Select Image_Value From Setting_Tbl Where Setting_Name='Company_Logo'", sqlcon) Da.Fill(DT) If DT.Rows.Count > 0 Then Dim picbyte() As Byte = DT.Rows(0).Item("Image_Value") Dim pic As New System.IO.MemoryStream(picbyte) PictureBox1.Image = Image.FromStream(pic) PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage End If
内容的提问来源于stack exchange,提问作者Ahmed Saif
相关产品推荐
相关产品推荐

