title author date CreateTime categories
WPF 修改图片颜色
lindexi
2018-08-10 19:16:53 +0800
2018-07-03 15:47:55 +0800
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

2018-8-10-WPF-修改图片颜色的更多相关文章

  1. WPF 修改图片颜色

    原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...

  2. xml代码修改图片颜色

    <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http ...

  3. Android动态修改图片颜色的实现方式分析

    版权声明:本文为博主原创文章,未经博主允许不得转载. 1.修改色相.饱和度.亮度 参看:http://blog.csdn.NET/sjf0115/article/details/7267063 2.使 ...

  4. c# 快速修改图片颜色

    public static void ChangeColour(this Bitmap bmp, byte inColourR, byte inColourG, byte inColourB, byt ...

  5. word中批量修改图片大小的两个方法

    前言: 对于把ppt的内容拷贝到word中: 对ppt的一页进行复制,然后粘贴到word中 如果要的是ppt运行过程中的内容,在qq运行的情况下,按Ctrl+Alt+A截屏,按勾,然后可以直接粘贴到w ...

  6. Android 使用ColorMatrix改变图片颜色

    原文链接:http://blog.csdn.net/janice0529/article/details/49207939 ColorMatrix的颜色矩阵介绍 颜色矩阵M是一个5*4的矩阵,在And ...

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

    摘自:http://www.dxy.cn/bbs/thread/8602152#8602152 利用Photoshop修改图片以达到投稿要求 软件版本为Photoshop CS V8.0.1(中文版) ...

  8. tabbarItem字体及图片颜色设置

    tabbarItem设置图片后运行往往与我们原始图片颜色有出入,这是因为在默认情况下,未选中状态图片和字体颜色为灰色,选中状态下图片和字体颜色为蓝色.   UIImage 在呈现(render)时会选 ...

  9. Gradify - 提取图片颜色,创建响应式的 CSS渐变

    被请求的HTTP对象之间的延迟会有一个时间段,这个期间网页看起来不完整.Gradify 可以分析出图像中4个最常见的颜色,创建一个梯度(或纯色)作为图片占位符.Gradify 可以在在任何图像发现最突 ...

随机推荐

  1. Dubbo报org.I0Itec.zkclient.exception.ZkNoNodeException异常

    解决办法就是添加zkclient的jar,maven工程的话增加如下引用: <dependency>     <groupId>com.github.sgroschupf< ...

  2. jQuery第3天

    复习 如何区别 JS DOM对象和 JQ 包装对象? JQ对象其实是经过包装的DOM对象,包装后可调用 JQ 的方法. JS 对象基本上都是属性为主,JQ基本上都方法为主. 可通过 console.d ...

  3. zabbix源码编译安装以及添加第一台host监控

    基础准备 硬件需求 数据库需求   软件需求 其他软件需求 安装 安装方式 source code 编译好的二进制包 rpm或者deb 源码编译安装部署zabbix以及附件 前提准备 最小化安装操作系 ...

  4. MySQL运算符和函数

    运算符 1.算数运算符 加(+):mysql> SELECT 1+1; 减(-):mysql> SELECT 3-2; 乘(*):mysql> SELECT 2*3; 除(/):my ...

  5. iOS 警告收录及科学快速的消除方法

    http://www.cocoachina.com/ios/20150914/13287.html 作者:董铂然 授权本站转载. 前言:现在你维护的项目有多少警告?看着几百条警告觉得心里烦么?你真的觉 ...

  6. wepy中组件之间通信方法

    events events是WePY组件事件处理函数对象,存放响应组件之间通过broadcast.emit.$invoke所传递的事件的函数. $broadcast —— 父往子传 $broadcas ...

  7. poj 3107 Godfather 求树的重心【树形dp】

    poj 3107 Godfather 和poj 1655差不多,那道会了这个也就差不多了. 题意:从小到大输出树的重心. 题会卡stl,要用邻接表存树..... #include<iostrea ...

  8. 2016 Asia Jakarta Regional Contest L - Tale of a Happy Man UVALive - 7722

    UVALive - 7722 一定要自己做出来!

  9. @atcoder - CODE FESTIVAL 2017 Final - J@ Tree MST

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 N 个点,第 i 点有一个点权 Xi,再给定一棵边带权的树 ...

  10. D - Denouncing Mafia DFS

    这道题其实很简单,求k个到根的链,使得链上的节点的个数尽可能多,如果节点被计算过了,就不能再被计算了,其实我们发现,只要k>=叶子节点,那么肯定是全部,所以我们考虑所有的叶子节点,DFS到根节点 ...