【WPF】ImageMagick調節圖片的顏色

需求:打開一張圖片後,自由調節圖片的顏色(色調)。php

思路:讀取顯示一張圖片後,用ColorPicker取色器選擇一種顏色,以後將圖片的色調調節爲該顏色。shell

工具:express

一、圖像工具 ImageMagick(.Net版)http://www.imagemagick.org/script/develop.php#dot-net 。或者在VS裏Nuget搜Magick.NET-Q8-AnyCPU。windows

二、WPF的取色器插件 https://www.cyotek.com/blog/colorpicker-controls-for-windows-forms。或者在VS裏Nuget搜Cyotek.Windows.Forms.ColorPicker。這是設計給Form用的,可是WPF中也能用代碼調用來使用。ide

新建一個WPF項目,顯示一張本地圖片。注意圖片是背景透明的,用該圖表示一個圖層。工具

<Window x:Class="TestMagickImage.Presentation.Views.ShellWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:vm="clr-namespace:TestMagickImage.Applications.ViewModels"
        mc:Ignorable="d" Title="{Binding Title}" Icon="{StaticResource ApplicationIcon}" Width="380" Height="400">

    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="調色" Command="{Binding ShowPalletCommand}"/>
            </MenuItem>
        </Menu>

        <Grid>
            <Image x:Name="img" Source="/TestMagickImage;component/Presentation/Resources/Images/test.png" />
        </Grid>
    </DockPanel>
</Window>

這裏顯示的是一張捕魚遊戲的小魚圖片素材。lua

在菜單項MenuItem中準備了一個按鈕,按鈕點擊事件彈出取色器。取色器中拾取一種顏色後點擊肯定後,將圖片調整到該色調。下面演示調整偏紅色的狀況。spa

private void ShowPallet()
{
    // 建立取色器(調色板)控件
    ColorPickerDialog colorPickerDialog = new ColorPickerDialog();
    colorPickerDialog.Width = 500;
    colorPickerDialog.Height = 300;
    colorPickerDialog.ShowDialog();
    
    // 查看剛纔獲取的顏色Color對象屬性
    //MessageBox.Show(colorPickerDialog.Color.ToString());
    
    using (MagickImage image = new MagickImage(ConvertImageSourceToBitmap(shellWindow.img.Source)))
    {
        // byte --> float
        float r = colorPickerDialog.Color.R;
        
        // 僅設置Red通道
        image.Evaluate(Channels.Red, EvaluateOperator.Set, r);

        // 從新給Image控件賦值新圖像
        shellWindow.img.Source = image.ToBitmapSource();
    }
}


/// <summary>
/// ImageSource --> Bitmap
/// </summary>
/// <param name="imageSource"></param>
/// <returns></returns>
public Bitmap ConvertImageSourceToBitmap(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;
}

調色後的效果,小魚總體色調偏紅色。由於上面的代碼僅設置了圖片的Red通道,因此不管顏色盤選中哪一個位置,都只會取其R值使用,G值、B值未被使用上。插件

可是,若是同時開放調整RGB三個通道,就會把整個圖片變成單一色塊!把上面代碼稍微改動一下。設計

using (MagickImage image = new MagickImage(ConvertImageSourceToBitmap(shellWindow.img.Source)))
{
    // byte --> float
    float r = colorPickerDialog.Color.R;
    float g = colorPickerDialog.Color.G;
    float b = colorPickerDialog.Color.B;
    
    // 設置三個通道
    image.Evaluate(Channels.Red, EvaluateOperator.Set, r);
    image.Evaluate(Channels.Green, EvaluateOperator.Set, g);
    image.Evaluate(Channels.Blue, EvaluateOperator.Set, b);

    // 從新給Image控件賦值新圖像
    shellWindow.img.Source = image.ToBitmapSource();
}

運行後的效果是一整個色塊。也許有人會碰到有這種需求的狀況??

相關文章
相關標籤/搜索