色相饱和度亮度滤镜






4.87/5 (11投票s)
一个 VB.NET 类,用于实现图像的色相/饱和度/亮度调整。
引言
这个 Visual Basic .NET 类实现了一个图像滤镜,可以改变图像的色相、饱和度和/或亮度。提供了一个小型演示项目。
背景
我一直在研究 "一个 C# 图像增强滤镜库" 这篇文章中描述的图像滤镜,并将代码从 C 转换为 VB.NET。 然后,我使用 "使用 C# 和 GDI+ 的傻瓜图像处理第 1 部分 - 逐像素滤镜" 中描述的滤镜扩展了我的库。 由于以上文章都没有描述色相/饱和度/亮度 (HSL) 滤镜,所以我决定编写自己的类。
滤镜类基础
所有滤镜共享相同的接口 IFilter
,定义一个接受图像作为输入并在退出时返回经过滤的图像的函数。
Public Interface IFilter
Function ExecuteFilter( _
ByVal inputImage As System.Drawing.Image) As System.Drawing.Image
End Interface
类 BasicFilter
实现了 IFilter
接口,并用作所有滤镜的基类。
Public MustInherit Class BasicFilter _
Implements IFilter
''' <summary />
''' Background color. Default is a transparent background.
''' </summary />
Private _bgColor As Color = Color.FromArgb(0, 0, 0, 0)
''' <summary />
''' Interpolation mode. Default is highest quality.
''' </summary />
Private _interpolation As InterpolationMode = _
InterpolationMode.HighQualityBicubic
''' <summary />
''' Get or set background color.
''' </summary />
Public Property BackgroundColor() As Color
Get
Return _bgColor
End Get
Set(ByVal value As Color)
_bgColor = value
End Set
End Property
''' <summary />
''' Get or set resize interpolation mode.
''' </summary />
Public Property Interpolation() As InterpolationMode
Get
Return _interpolation
End Get
Set(ByVal value As InterpolationMode)
_interpolation = value
End Set
End Property
''' <summary />
''' Execute filter function and return new filtered image.
''' </summary />
''' Image to be filtered.
''' <returns />New filtered image.</returns />
Public MustOverride Function ExecuteFilter( _
ByVal img As System.Drawing.Image) _
As System.Drawing.Image Implements IFilter.ExecuteFilter
End Class
大多数滤镜都具有相同的 ExecuteFilter
函数,该函数目前仅处理某些图像格式。
Public Overrides Function ExecuteFilter( _
ByVal img As System.Drawing.Image) _
As System.Drawing.Image
Select Case img.PixelFormat
Case PixelFormat.Format16bppGrayScale
Return img
Case PixelFormat.Format24bppRgb, _
PixelFormat.Format32bppArgb, PixelFormat.Format32bppRgb
Return ExecuteRgb8(img)
Case PixelFormat.Format48bppRgb
Return img
Case Else
Return img
End Select
End Function
由于我喜欢掌控一切并了解发生了什么,因此我不使用颜色矩阵来转换图像,而是读取/修改/写入像素,这证明与使用颜色矩阵一样快。 我在我的滤镜中使用类似的框架来访问像素。
Private Function ExecuteXXX(ByVal img As System.Drawing.Image) As System.Drawing.Image
'Create new image for result.
Dim result As Bitmap = New Bitmap(img)
result.SetResolution(img.HorizontalResolution, img.VerticalResolution)
Dim bmpData As BitmapData = result.LockBits( _
New Rectangle(0, 0, result.Width, result.Height), _
ImageLockMode.ReadWrite, img.PixelFormat)
Dim pixelBytes As Integer = _
System.Drawing.Image.GetPixelFormatSize(img.PixelFormat) \ 8
'Get the address of the first line.
Dim ptr As IntPtr = bmpData.Scan0
Dim size As Integer = bmpData.Stride * result.Height
Dim pixels(size - 1) As Byte
Dim index As Integer
'Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, size)
'Main loop.
For row As Integer = 0 To result.Height - 1
For col As Integer = 0 To result.Width - 1
index = (row * bmpData.Stride) + (col * pixelBytes)
R = pixels(index + 2)
G = pixels(index + 1)
B = pixels(index + 0)
'Do filtering.
'...
Next
Next
'Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, size)
'Unlock the bits.
result.UnlockBits(bmpData)
Return result
End Function
实现 HSL 滤镜
基本思路是将 RGB 值转换为 HSL 值,根据用户设置更改 HSL 值,然后将 HSL 值转换回 RGB 值。 HSL 颜色空间在 Wikipedia 中有详细描述,您还可以在 EasyRGB 找到 C 代码的转换链接。 将 C 代码转换为 VB.NET 非常简单,并且滤镜运行良好。
为了测试滤镜,我使用了一个 256 像素的正方形 JPEG 图像,并且我从控制台应用程序运行滤镜,同时测量过滤时间。 执行时间比其他滤镜稍长,但不是很关键。 直到在 2288x1712 像素的图像上使用滤镜。 执行时间超过 16 秒。
通过纸、笔和一些基本的数学运算,我发现 EasyRGB 代码中的许多计算是不必要的。 使用 HSL 的完整范围而不是范围 [0..1] 也节省了一些时间。 通过将单独函数中的代码放入主循环中,实现了最大的时间节省。 有趣的是,当我尝试使用整数算术进行部分计算时,执行时间反而增加了。 看来类型转换花费了相当多的时间。
最终执行时间约为 1.5 秒,仅为原始执行时间的 10%。
使用代码
代码非常简单。 滤镜接受的参数如下:
Hue
是一个介于 0 和 360 之间的值; 实际上,任何值都将被接受,然后转换为适当的范围。Saturation
和Lightness
允许的值介于 -100 和 +100 之间(以百分比表示)。BackgroundColor
和Interpolation
参数在此滤镜中没有意义。
'Define compression for saved image.
Dim myEncoderParameters As EncoderParameters = New EncoderParameters(1)
myEncoderParameters.Param(0) = _
New EncoderParameter(Encoder.Quality, CType(90L, Int32))
'Load image.
Dim imgOriginal As Image = _
Image.FromFile("C:\Documents and Settings\Test.jpg")
'Define filter and parameters.
Dim imgFilter As HSLFilter = New HSLFilter()
imgFilter.Hue = 50
imgFilter.Saturation = 0
imgFilter.Lightness = 0
'Execute filter.
Dim imgFiltered As Image = imgFilter.ExecuteFilter(imgOriginal)
'Save filtered image as jpeg.
imgFiltered.Save("C:\Documents and Settings\Test_HSL.jpg", _
Library.Image.Functions.GetEncoderInfo(ImageFormat.Jpeg), _
myEncoderParameters)
关注点
实现此滤镜是优化代码以提高速度的一个很好的例子。 我学到了很多关于颜色和访问图像数据的知识。
历史
- 2007-06-08:饱和度和亮度比例已更改。 添加了演示项目。
- 2007-06-05:1.00 版。