VB.NET实现图像重着色并保留亮度的技术问询
VB.NET 保留亮度的图像重着色函数
问题分析
你提供的原始代码仅基于红色通道的强度缩放目标颜色,仅适用于纯红色调图像。对于非单色或偏色图像(比如(255,123,123)这类颜色),必须基于像素整体亮度调整目标颜色,才能保证重着色后亮度匹配。
解决方案思路
采用HSV颜色空间处理,核心逻辑:
- 提取原像素的亮度(Value)
- 提取目标颜色的色调(Hue)和饱和度(Saturation)
- 将目标颜色的亮度替换为原像素的亮度,再转换回RGB空间
- 保留原像素的Alpha通道
完整实现代码
先添加HSV与RGB互转的辅助函数,再实现重着色主函数:
' RGB转HSV辅助函数 Private Shared Function RgbToHsv(color As Color) As Tuple(Of Double, Double, Double) Dim r = color.R / 255.0 Dim g = color.G / 255.0 Dim b = color.B / 255.0 Dim max = Math.Max(r, Math.Max(g, b)) Dim min = Math.Min(r, Math.Min(g, b)) Dim h, s, v As Double v = max Dim delta = max - min If max = 0 Or delta = 0 Then s = 0 h = 0 Else s = delta / max If r = max Then h = (g - b) / delta ElseIf g = max Then h = 2 + (b - r) / delta Else h = 4 + (r - g) / delta End If h *= 60 If h < 0 Then h += 360 End If End If Return Tuple.Create(h, s, v) End Function ' HSV转RGB辅助函数 Private Shared Function HsvToRgb(h As Double, s As Double, v As Double) As Color Dim r, g, b As Double If s = 0 Then r = v g = v b = v Else h /= 60 Dim i = Math.Floor(h) Dim f = h - i Dim p = v * (1 - s) Dim q = v * (1 - s * f) Dim t = v * (1 - s * (1 - f)) Select Case i Case 0 r = v g = t b = p Case 1 r = q g = v b = p Case 2 r = p g = v b = t Case 3 r = p g = q b = v Case 4 r = t g = p b = v Case 5 r = v g = p b = q End Select End If Return Color.FromArgb(CInt(r * 255), CInt(g * 255), CInt(b * 255)) End Function ' 主重着色函数:保留原像素亮度,替换为指定颜色 Public Shared Function RecolorKeepingBrightness(image As Bitmap, newColor As Color) As Bitmap Dim resultImage As New Bitmap(image.Width, image.Height) ' 获取目标颜色的HSV参数(保留色调和饱和度) Dim targetHsv = RgbToHsv(newColor) Dim targetH = targetHsv.Item1 Dim targetS = targetHsv.Item2 For x As Integer = 0 To image.Width - 1 For y As Integer = 0 To image.Height - 1 Dim pixelColor = image.GetPixel(x, y) If pixelColor.A > 0 Then ' 获取原像素的HSV参数,提取亮度 Dim originalHsv = RgbToHsv(pixelColor) Dim originalV = originalHsv.Item3 ' 用目标颜色的H、S + 原像素的V,生成新颜色 Dim newRgb = HsvToRgb(targetH, targetS, originalV) ' 保留原Alpha通道 resultImage.SetPixel(x, y, Color.FromArgb(pixelColor.A, newRgb.R, newRgb.G, newRgb.B)) Else resultImage.SetPixel(x, y, pixelColor) End If Next Next Return resultImage End Function
额外说明
- 亮度逻辑:通过HSV的Value分量(RGB通道的最大值)获取亮度,符合人眼视觉感知
- 兼容性:支持所有RGB图像,包括非单色、带透明度的图像
- 性能优化:若处理大图像,建议用
LockBits替代GetPixel/SetPixel,可大幅提升处理速度(示例代码为保证可读性采用了简单的像素操作)
内容的提问来源于stack exchange,提问作者Michatom
相关产品推荐
相关产品推荐

