先說概念:
HSL是一種描述顏色的方式,其他顏色描述方式還有大家熟悉的RGB值。HSL三個字母分別表示圖像的Hue色相、Saturation飽和度、Lightness明亮度。
需求:
制作一個面板,包含三個滑動條,拖動滑動條可以修改目標圖片的HSL值。即模仿PS中類似的功能,如下圖:

方案一:遍歷所有像素點,修改每個點的HSL值。
參考:https://stackoverflow.com/questions/10332363/getting-hue-from-every-pixel-in-an-image
for (int j = 0; j < bitmap.Height; j++) { for (int i = 0; i < bitmap.Width; i++) { System.Drawing.Color color = bitmap.GetPixel(i, j);
// todo something } }
方案二:使用三方庫MagickImage.Net
眾所周知MagickImage是一個及其強大又多功能的圖像處理庫,而且有多個平台下對應的版本(如Java、PHP)。
步驟:
1、 在Visual Studio的NuGet中搜索、下載、安裝MagickImage。選最上面最高下載量這個。

2、隨便打開一個類,輸入ImageMagick.MagickImage並導包后,按下F12查看該類有哪些方法能實現我們的需求。在該類中按Ctrl + F搜索hue,即可看到該類的確提供了修改圖像HSL的方法!
(文件很長,中間省略。。。)

3、觀察上圖這個Modelate()方法的傳參,是結構體ImageMagick.Percentage,該結構體的描述跟圖片像素無關。看下圖,該Percentage構造函數中傳參的是一個數字,可知該Modelate()方法修改的HSL值是原圖的HSL值的一個百分比!

4、再觀察被操作的圖像ImageMagick.MagickImage這個類,該類提供了toBitmap()和toBitmapSource()方法,前者Bitmap是通用的圖像類型,后者BitmapSource是WPF使用的圖像類型,說明該類連圖像類型轉換的功能都准備好了,前置條件一切OK!
5、了解所需函數的使用方法后,開始做Demo。界面如下,一個Image控件顯示圖片,三個Slider滑動條分別調節Hue色相、Saturation飽和度、Lightness明亮度。
<DockPanel Width="400" Height="150" VerticalAlignment="Top" Margin="0,20,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Label Content="色相" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" />
<Slider x:Name="slider0" Value="{Binding SliderValue0}" Minimum="0" Maximum="200" VerticalAlignment="Center" Grid.Row="0" Grid.Column="1"/>
<Label Content="飽和度" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" />
<Slider x:Name="slider1" Value="{Binding SliderValue1}" Minimum="0" Maximum="200" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
<Label Content="明度" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" />
<Slider x:Name="slider2" Value="{Binding SliderValue2}" Minimum="0" Maximum="200" VerticalAlignment="Center" Grid.Row="2" Grid.Column="1"/>
</Grid>
</DockPanel>
界面如下圖:

注意,因為Modelate()方法的傳參要求是百分比,所以Slider滑動條的兩頭的值為0,200(表示0%和200%),默認位置在中間100(表示100%,即HSL未修改的狀態)。
Controller層給這三個Slider滑動條添加滑動事件,下面只以修改Hue色相為例:
private ImageMagick.MagickImage originalMagickImage; // 圖層圖像修改前的狀態
// 先執行該方法!
private void Init()
{
// 滑動條的修改是在原圖的基礎上修改!
Bitmap bitmap = ImageSourceToBitmap(img.Source); // img是前台Image控件
originalMagickImage = new ImageMagick.MagickImage(bitmap);
}
/// <summary>
/// 調節色相。在原圖的基礎上增加/減少百分比
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Hue_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// 只調整圖像的Hue色相值
ImageMagick.Percentage brightness = new ImageMagick.Percentage(100); // 100%表示不改變該屬性
ImageMagick.Percentage saturation = new ImageMagick.Percentage(100);
ImageMagick.Percentage hue = new ImageMagick.Percentage(e.NewValue); // 滑動條范圍值0%~200%
ImageMagick.MagickImage newImage = new ImageMagick.MagickImage(originalMagickImage); // 相當於深復制
newImage.Modulate(brightness, saturation, hue);
// 重新給Image控件賦值新圖像
BitmapSource bitmapImage = newImage.ToBitmapSource();
img.Source = imageSource;
}
// 工具方法:ImageSource --> Bitmap
public System.Drawing.Bitmap ImageSourceToBitmap(ImageSource imageSource)
{
BitmapSource m = (BitmapSource)imageSource;
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(m.PixelWidth, m.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
System.Drawing.Imaging.BitmapData data = bmp.LockBits(
new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
m.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); bmp.UnlockBits(data);
return bmp;
}
經測試,該方法效率很高!拖拽滑動條立馬能看到HSL修改后的效果!顯著比兩個For循環遍歷所有像素點高效很多!
2017.7.17更新:
項目有了新的需求,還要做調節圖像的對比度(Contrast),就順便把之前落下的GIF補上。同時因為做對比度時沒有再使用這個ImageMagick插件,所以打算新開一篇博文 http://www.cnblogs.com/guxin/p/csharp-wpf-adjust-image-contrast.html
調節色相(Hue)的動圖:

調節飽和度(Saturation)的動圖:

調節明度(Lightness)的動圖:

另外,關於調節圖像的對比度(Contrast),可參考在下的另一篇博文:
