WPF 修改图片颜色

原文:WPF 修改图片颜色

本文告诉大家如何修改图片的颜色,如去掉图片的蓝色

在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件。

在阅读本文,我假设大家是熟悉 WPF 的,至少了解 C# ,也知道图片的格式。

在 WPF 可以使用 ARBG 数组表示图片,本文修改图片颜色的方法就是使用 ARBG 数组的方法修改,修改里面的元素的值。

如我需要去掉图片的蓝色,就可以通过修改 ARBG 数组的元素,设置所有蓝色为 0 ,去掉蓝色。

读取图片

首先找到一张好看的图片,放在解决方案

读取解决方案的图片

            var stream = Application.GetResourceStream(new Uri("pack://application:,,,/1.jpg")).Stream;

如果找不到图片,就是没有设置图片生成是 Resource

解析文件

创建 WriteableBitmap 需要使用 ImageSource 所以需要先解析

// 其他忽略代码
            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();

使用 BitmapImage 解析文件

创建图片

在读取图片之后就可以创建图片

            var writeableBitmap = new WriteableBitmap(bitmapImage);

转换图片格式

如果读取到的图片不是 BGRA 的格式,就需要转换图片格式

            var formatConvertedBitmap = new FormatConvertedBitmap();

            formatConvertedBitmap.BeginInit();

            formatConvertedBitmap.Source = bitmapImage;

            formatConvertedBitmap.DestinationFormat = PixelFormats.Bgra32;

            formatConvertedBitmap.EndInit();

使用这个代码可以把格式转为PixelFormats.Bgra32,需要重新创建图片

            var stream = Application.GetResourceStream(new Uri("pack://application:,,,/1.jpg")).Stream;

            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();

            var formatConvertedBitmap = new FormatConvertedBitmap();

            formatConvertedBitmap.BeginInit();

            formatConvertedBitmap.Source = bitmapImage;

            formatConvertedBitmap.DestinationFormat = PixelFormats.Bgra32;

            formatConvertedBitmap.EndInit();

            var writeableBitmap = new WriteableBitmap(formatConvertedBitmap);

尝试显示图片,可以看到图片还是很好看

读取数组

在图片可以看到图片是使用 BGRA 的格式数组,所以只需要读取图片数组就可以修改图片

读取图片需要使用不安全代码,需要右击项目属性,点击生成,允许不安全代码。

在修改图片之前需要使用 Lock 函数,读取图片的数组长度可以使用这个代码

            var length = writeableBitmap.PixelWidth * writeableBitmap.PixelHeight *
                         writeableBitmap.Format.BitsPerPixel / 8;

这里知道使用的是 BGRA 也就是一个像素使用 4 个 byte ,一个图片的像素就是writeableBitmap.PixelWidth * writeableBitmap.PixelHeight 。这里 writeableBitmap.Format.BitsPerPixel 就是拿到一个像素的 bit 数。

转换数组

            var backBuffer = (byte*) writeableBitmap.BackBuffer;

读取颜色就是从数组拿到值

            for (int i = 0; i + 4 < length; i = i + 4)
            {
                var blue = backBuffer[i];
                var green = backBuffer[i + 1];
                var red = backBuffer[i + 2];
                var alpha = backBuffer[i + 3];
            }

修改颜色就是修改对应的值然后设置数组,如设置蓝色是 0 去掉蓝色

            for (int i = 0; i + 4 < length; i = i + 4)
            {
                var blue = backBuffer[i];
                var green = backBuffer[i + 1];
                var red = backBuffer[i + 2];
                var alpha = backBuffer[i + 3];

                blue = 0;

                backBuffer[i] = blue;
                backBuffer[i + 1] = green;
                backBuffer[i + 2] = red;
                backBuffer[i + 3] = alpha;
            }

设置之后需要设置图片显示


            writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight));
            writeableBitmap.Unlock();

所以去掉图片的蓝色可以使用 RemoveBlue 函数,设置蓝色为 0 的方法就是读取蓝色然后修改数组

        private unsafe void RemoveBlue(WriteableBitmap writeableBitmap)
        {
            writeableBitmap.Lock();

            var length = writeableBitmap.PixelWidth * writeableBitmap.PixelHeight *
                         writeableBitmap.Format.BitsPerPixel / 8;

            var backBuffer = (byte*) writeableBitmap.BackBuffer;

            for (int i = 0; i + 4 < length; i = i + 4)
            {
                var blue = backBuffer[i];
                var green = backBuffer[i + 1];
                var red = backBuffer[i + 2];
                var alpha = backBuffer[i + 3];

                blue = 0;

                backBuffer[i] = blue;
                backBuffer[i + 1] = green;
                backBuffer[i + 2] = red;
                backBuffer[i + 3] = alpha;
            }

            writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight));
            writeableBitmap.Unlock();
        }

去掉蓝色的图片

代码:WPF 修改图片颜色 1.2-CSDN下载

现在的程序看起来还不能使用,尝试添加几个依赖属性,用来修改图片的颜色

可以点击这里下载程序

WPF 修改图片

首先在 xaml 添加几个控件

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="485*" />
            <ColumnDefinition Width="308*" />
        </Grid.ColumnDefinitions>
        <Image x:Name="Image" />
        <Grid Grid.Column="1">
            <Grid VerticalAlignment="Center">
                <FrameworkElement.Resources>
                    <Style TargetType="Slider">
                        <Setter Property="Width" Value="100" />
                        <Setter Property="HorizontalAlignment" Value="Center" />
                        <Setter Property="Margin" Value="10,10,10,10" />
                        <Setter Property="Minimum" Value="-255" />
                        <Setter Property="Maximum" Value="255" />
                    </Style>

                    <Style TargetType="TextBlock">
                        <Setter Property="Margin" Value="10,10,10,10" />
                        <Setter Property="HorizontalAlignment" Value="Center" />
                    </Style>

                    <local:DoubleConvert x:Key="DoubleConvert" />
                </FrameworkElement.Resources>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <TextBlock>蓝色</TextBlock>
                <TextBlock Grid.Row="1" Grid.Column="0">绿色</TextBlock>
                <TextBlock Grid.Row="2" Grid.Column="0">红色</TextBlock>
                <TextBlock Grid.Row="3" Grid.Column="0">透明度</TextBlock>

                <!-- 蓝色 -->
                <Slider Grid.Row="0" Grid.Column="1" Value="{Binding Path=Blue,Mode=TwoWay}" />
                <!-- 绿色 -->
                <Slider Grid.Row="1" Grid.Column="1" Value="{Binding Path=Green,Mode=TwoWay}" />
                <!-- 红色 -->
                <Slider Grid.Row="2" Grid.Column="1" Value="{Binding Path=Red,Mode=TwoWay}" />
                <!-- 透明度 -->
                <Slider Grid.Row="3" Grid.Column="1" Value="{Binding Path=Alpha,Mode=TwoWay}" />

                <!-- 蓝色 -->
                <TextBlock Grid.Row="0" Grid.Column="2"
                           Text="{Binding Path=Blue,Mode=OneWay,Converter={StaticResource DoubleConvert}}" />
                <!-- 绿色 -->
                <TextBlock Grid.Row="1" Grid.Column="2"
                           Text="{Binding Path=Green,Mode=OneWay,Converter={StaticResource DoubleConvert}}" />
                <!-- 红色 -->
                <TextBlock Grid.Row="2" Grid.Column="2"
                           Text="{Binding Path=Red,Mode=OneWay,Converter={StaticResource DoubleConvert}}" />
                <!-- 透明度 -->
                <TextBlock Grid.Row="3" Grid.Column="2"
                           Text="{Binding Path=Alpha,Mode=OneWay,Converter={StaticResource DoubleConvert}}" />
            </Grid>
            <Grid VerticalAlignment="Bottom">
                <Button Margin="10,10,10,10" Content="替换图片" Click="Button_OnClick" />
            </Grid>
        </Grid>
    </Grid>

注意在页面设置数据

DataContext="{Binding RelativeSource={RelativeSource Self}}"

然后打开 cs 添加代码

      private WriteableBitmap _writeableBitmap;

        public MainWindow()
        {
            InitializeComponent();

            Image.Margin = new Thickness(10, 10, 10, 10);

            var stream = Application.GetResourceStream(new Uri("pack://application:,,,/1.jpg")).Stream;

            ChangeImage(stream);

            DataContext = this;
        }

        public static readonly DependencyProperty BlueProperty = DependencyProperty.Register(
            "Blue", typeof(double), typeof(MainWindow),
            new PropertyMetadata(default(double), (s, e) => ((MainWindow) s).ChangeArray()));

        public double Blue
        {
            get { return (double) GetValue(BlueProperty); }
            set { SetValue(BlueProperty, value); }
        }

        public static readonly DependencyProperty GreenProperty = DependencyProperty.Register(
            "Green", typeof(double), typeof(MainWindow),
            new PropertyMetadata(default(double), (s, e) => ((MainWindow) s).ChangeArray()));

        public double Green
        {
            get { return (double) GetValue(GreenProperty); }
            set { SetValue(GreenProperty, value); }
        }

        public static readonly DependencyProperty RedProperty = DependencyProperty.Register(
            "Red", typeof(double), typeof(MainWindow),
            new PropertyMetadata(default(double), (s, e) => ((MainWindow) s).ChangeArray()));

        public double Red
        {
            get { return (double) GetValue(RedProperty); }
            set { SetValue(RedProperty, value); }
        }

        public static readonly DependencyProperty AlphaProperty = DependencyProperty.Register(
            "Alpha", typeof(double), typeof(MainWindow),
            new PropertyMetadata(default(double), (s, e) => ((MainWindow) s).ChangeArray()));

        public double Alpha
        {
            get { return (double) GetValue(AlphaProperty); }
            set { SetValue(AlphaProperty, value); }
        }

        private void ChangeImage(Stream stream)
        {
            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();

            var formatConvertedBitmap = new FormatConvertedBitmap();

            formatConvertedBitmap.BeginInit();

            formatConvertedBitmap.Source = bitmapImage;

            formatConvertedBitmap.DestinationFormat = PixelFormats.Bgra32;

            formatConvertedBitmap.EndInit();

            _writeableBitmap = new WriteableBitmap(formatConvertedBitmap);

            ChangeArray();
        }

        private unsafe void ChangeArray()
        {
            var writeableBitmap = _writeableBitmap;

            if (writeableBitmap == null)
            {
                return;
            }

            writeableBitmap.Lock();

            var length = writeableBitmap.PixelWidth * writeableBitmap.PixelHeight *
                         writeableBitmap.Format.BitsPerPixel / 8;

            var backBuffer = (byte*) writeableBitmap.BackBuffer;

            var byteList = new byte[length];

            for (int i = 0; i + 4 < length; i = i + 4)
            {
                var blue = backBuffer[i];
                var green = backBuffer[i + 1];
                var red = backBuffer[i + 2];
                var alpha = backBuffer[i + 3];

                blue += (byte) Blue;
                green += (byte) Green;
                red += (byte) Red;
                alpha += (byte) Alpha;

                byteList[i] = blue;
                byteList[i + 1] = green;
                byteList[i + 2] = red;
                byteList[i + 3] = alpha;
            }

            writeableBitmap.Unlock();

            writeableBitmap = new WriteableBitmap(writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, 96, 96,
                writeableBitmap.Format, writeableBitmap.Palette);

            writeableBitmap.Lock();

            writeableBitmap.WritePixels(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight),
                byteList, writeableBitmap.BackBufferStride, 0);

            writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight));
            writeableBitmap.Unlock();

            Image.Source = writeableBitmap;
        }

        private void Button_OnClick(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "jpg(*.jpg)|*.jpg";

            if (openFileDialog.ShowDialog() == true)
            {
                var stream = openFileDialog.OpenFile();
                ChangeImage(stream);
            }
        }

    public class DoubleConvert : IValueConverter
    {
        /// <inheritdoc />
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is double n)
            {
                return n.ToString("0.00");
            }

            return DependencyProperty.UnsetValue;
        }

        /// <inheritdoc />
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

代码:WPF 修改图片颜色 2.5-CSDN下载

参见:

How to: Convert a BitmapSource to a Different PixelFormat



本文会经常更新,请阅读原文:
https://lindexi.gitee.io/lindexi/post/WPF-%E4%BF%AE%E6%94%B9%E5%9B%BE%E7%89%87%E9%A2%9C%E8%89%B2.html
,以避免陈旧错误知识的误导,同时有更好的阅读体验。


本作品采用
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:
https://lindexi.gitee.io
),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请
与我联系

原文地址:https://www.cnblogs.com/lonelyxmas/p/10218041.html

时间: 2024-10-09 21:13:20

WPF 修改图片颜色的相关文章

Beyond Compare比较图片怎么修改背景颜色

Beyond Compare作为一款专业的文件夹以及文本比较工具,它拥有强大的比较功能,并将文件差异以不同的颜色标注,方便查阅.为了体现人性化的设计理念,Beyond Compare也支持多种个性化设置,今天就和大家分享一下,Beyond Compare比较图片怎么修改背景颜色,以符合每个用户的使用习惯. 具体的操作步骤如下: 步骤一:打开Beyond Compare软件,选择图片比较会话操作,打开操作界面. 单击“打开文件”按钮,选择需要比较的图片.  Beyond Compare图片比较会话

ExtJS4.1.1 设置表格背景颜色 修改文本颜色 在表格中插入图片

由于ExtJS版本不断更新,各种渲染方式也随之有所改变,目前大部分书籍还是停留在3版本,对于ExtJS4.1.1版本的表格渲染,设置表格行背景颜色的方式如下: 首先,定义行的样式: 1.yellow-row .x-grid-cell{ 2  background-color:#FFFF00 !important; 3         } 4  .white-row .x-grid-cell{ 5    background-color:#FFFFFF !important; 6         

wpf 修改控件Background

以TextBox 控件为例 一  Brushes.颜色 textBoxName.Background = Brushes.Blue; 二 背景色值#FFD2D2D2 1 .textBoxName.Background=new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFD2D2D2")); 2.textBoxName.Background = new SolidColorBrush(Colors.White);

【转】使用blend改变图片颜色

最近对Core Animation和Core Graphics的内容东西比较感兴趣,自己之前也在这块相对薄弱,趁此机会也想补习一下这块的内容,所以之后几篇可能都会是对CA和CG学习的记录的文章. 在应用里一个很常见的需求是主题变换:同样的图标,同样的素材,但是需要按照用户喜爱变为不同的颜色.在iOS5和6的SDK里部分标准控件引入了tintColor,来满足个性化界面的需求,但是Apple在这方面还远远做的不够.一是现在用默认控件根本难以做出界面优秀的应用,二是tintColor所覆盖的并不够全

PDF格式怎么修改图片水印

PDF中如何修改语法错误 今天看到同事在做产品说明电子档的修改,需要将已经变动的水印改为最新的,小编看到同事用纯技术手段一页页改了半天还没改好,终于没忍住向他推荐了一款专业的PDF编辑软件--捷速PDF编辑器,让他使用试试,修改去除PDF文件格式上的水印真的是很简单. 只要打开捷速PDF编辑器,选择菜单栏上的文件选项,在下拉列表中选择打开选项,也可以按快捷键Ctrl+O,就可以在弹出的窗口中找到需要编辑的Pdf文档了.选择要编辑的Pdf文档并且打开,可以在软件页面缩略图里看到文件的所有页面. 可

利用Photoshop修改图片以达到投稿要求

摘自:http://www.dxy.cn/bbs/thread/8602152#8602152 软件版本为Photoshop CS V8.0.1(中文版),投稿要求参见Neurosci Lett(http://authors.elsevier.com/ArtworkInstructions.html?dc=AI1).具体投稿要求各杂志均有差异.现代科学论文中,图片占有重要的地位,可以说是论文是否被接受的关键之一.文章中的图片大体可以分为三类:1)照片,多来自数码相机或CCD:2)来自采样软件,如

js 动态修改属性值 动态修改图片,字等

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"   http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <meta http-equiv = "content-type" content="text/html;charset=utf-8"/> &

Python 批量修改图片exif属性

一共两个文件 config.ini //放配置文件 exif.py   //主程序文件 config.ini 文件源码 [global] Artist = www.blmm.com ;作者 DateTimeOriginal = now ;时间(now为当前时间,如指定时间则格式为:2017:04:09 14:13:22) Software = Adobe Photoshop CS6 Windows ;程序名称 exif.py 文件源码 #ecoding:utf-8 import pyexiv2

利用色光三原色调整图片颜色

最近学习了android中的图片颜色的处理,现在来总结一下.android中存在三种方式来调整图片的颜色,来达到不同的效果.分别是:利用色光三原色来调整图片颜色,利用颜色矩阵来调整图片颜色,利用调整每一个像素点来调整图片颜色.显然调整颜色的方式是越来越细致的.那么在这一篇文章中,就总结一下通过色光三原色来调整图片的颜色. 一.基础知识 首先说一下基础的颜色知识.android中采取的颜色模型是RGBA模型.即R代表红色,G代表绿色,B代表蓝色,A代表透明度.而通过改变一张图片的三原色的色相,饱和