title author date CreateTime categories
WPF 通过位处理合并图片
lindexi
2018-10-20 16:53:49 +0800
2018-10-20 16:1:48 +0800
WPF 图片处理

本文告诉大家,在使用 WPF 合并两张图片的处理,可以使用像素之间的与或和异或的方式,对三个颜色的通道进行处理。

先给大家看一下软件的界面

这就是通过将左边的两张图片叠加合并为一张图片,这里的蓝色的通道就是通过位或的方式,绿色通道使用与的方式,红色也使用或的方式。

WPF 修改图片颜色 已经告诉大家如何修改 WPF 的图片的颜色,但是为了叠加两张图片,还需要先读取图片的颜色

读取图片

在读取图片之前需要从文件加载图片,先在解决方案放两张图片,然后进行解析

在 WPF 如何需要读取解决方案的图片,可以使用 GetResourceStream 的方法,注意图片放在解决方案需要修改生成方式为资源

在 WPF 的读取资源是使用 URL 的方式,我这里在解决方案放的图片是在项目的文件夹,可以通过下面的链接获取

pack://application:,,,/图片文件夹/图片名.jpg

获取资源的代码很简单,但是需要将资源转换为图片,这里转换为图片的时候因为下面需要读取图片的颜色,需要修改图片的格式为 Bgra32 的格式,这个格式就是使用 32 位的 int 存放一个像素,一个像素里的按照8位也是1个byte分为蓝色、绿色红色和透明度

      private WriteableBitmap GetImage(string url)
{
var stream = Application.GetResourceStream(new Uri(url))?.Stream ?? throw new ArgumentException(); 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(); return new WriteableBitmap(formatConvertedBitmap);
}

通过这个方法就可以从解决方案拿到 URL 转换为图片

读取图片像素

获取到图片之后,可以通过下面的方式获取图片的每一个像素

           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];
}

这里的 length 就是拿到图片的像素长度,从上面代码可以看到使用了不安全代码,需要右击项目属性,选择可以使用不安全代码

通过上面的方法拿到两个图片的所有像素,然后将像素一一对应,这里我使用的两张图片的像素长度和像素宽度都是相同的,所以直接通过对应的数组下标就可以对应每个像素,如果是像素不相等的图片,具体业务是怎么处理就进行对应的方法

合并两张图片

从上面的代码可以拿到两张图片的每个像素,然后将两张图片的像素合并为第三个像素放在一个新的数组,最后将这个数组创建为一张图片,也就是显示为中间的图片

先来写一个函数,这个函数传入了枚举 YimiXoujelneTi 和两个 byte 关于枚举请看下面

        enum YimiXoujelneTi
{
Or,
And,
Xor,
}

枚举包含三个值,一个是或一个是与一个是异或,通过上面三个值可以处理传入的两个像素的通道

                                switch (soKooworstarWhisvemsal)
{
case YimiXoujelneTi.Or:
return (byte) (byte1 | byte2);
case YimiXoujelneTi.And:
return (byte) (byte1 & byte2);
case YimiXoujelneTi.Xor:
return (byte) (byte1 ^ byte2);
}

很简单就处理像素,需要对不同的颜色进行处理

在处理颜色之后,可以通过创建一个和处理的图片的像素宽度和像素高度相同的 WriteableBitmap 然后写入处理的数组

界面

已经告诉了大家原理的部分,现在是细节的界面,在界面添加三个图片控件和一个按钮

    <Grid>
<Grid.Resources>
<system:Double x:Key="MicuTisperesemtooImageWidth">100</system:Double>
<system:Double x:Key="MalkersemjemQalreeImageHeight">100</system:Double> <Style x:Key="RootealalheJiqardreImage" TargetType="Image">
<Setter Property="Width" Value="{StaticResource MicuTisperesemtooImageWidth}" />
<Setter Property="Height" Value="{StaticResource MalkersemjemQalreeImageHeight}" />
<Setter Property="Stretch" Value="Fill" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="135*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border BorderThickness="1">
<Border.Resources>
<Style x:Key="CawhemWurYairbeaBiqawjelBorder" TargetType="Border">
<Setter Property="Background" Value="Gray" />
<Setter Property="Margin" Value="10,10,10,10" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Padding" Value="10,10,10,10"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="Black"></Setter>
</Style>
</Border.Resources>
<Grid>
<Grid.Resources> </Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid>
<Border Style="{StaticResource CawhemWurYairbeaBiqawjelBorder}">
<Image x:Name="JaitetiDrokowPiskikaroImage" Style="{StaticResource RootealalheJiqardreImage}"
Source="orion-nebula-11107_640.jpg" />
</Border>
</Grid>
<Grid Grid.Row="1">
<Border Style="{StaticResource CawhemWurYairbeaBiqawjelBorder}">
<Image x:Name="NojerecalkeLeahuBemnercerfi" Style="{StaticResource RootealalheJiqardreImage}"
Source="solar-system-11188_640.jpg" />
</Border>
</Grid>
</Grid></Border>
<Grid Grid.Column="1" Background="Gray" Margin="10,10,10,10">
<Image x:Name="MeamouceaxaPooricoumo" Margin="10,10,10,10" Stretch="Fill" />
</Grid>
<Grid Grid.Column="2">
<StackPanel Margin="10,10,10,10" Width="100">
<StackPanel.Resources>
<Style x:Key="JairrairzeceDairpeCistirtelTextBlock" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style x:Key="KirjasdraRadocemsouMainouhaltuTasmejirComboBox" TargetType="ComboBox">
<Setter Property="Margin" Value="10,10,10,10" />
</Style>
</StackPanel.Resources>
<TextBlock Style="{StaticResource JairrairzeceDairpeCistirtelTextBlock}" Text="合并方式" />
<TextBlock Margin="10,50,10,10" Style="{StaticResource JairrairzeceDairpeCistirtelTextBlock}"
Text="Blue" />
<ComboBox x:Name="BlueDallstartaxaJembere"
Style="{StaticResource KirjasdraRadocemsouMainouhaltuTasmejirComboBox}" /> <TextBlock Margin="10,10,10,10" Style="{StaticResource JairrairzeceDairpeCistirtelTextBlock}"
Text="Green" />
<ComboBox x:Name="GreenTrelqarnelNayke"
Style="{StaticResource KirjasdraRadocemsouMainouhaltuTasmejirComboBox}" /> <TextBlock Margin="10,10,10,10" Style="{StaticResource JairrairzeceDairpeCistirtelTextBlock}"
Text="Red" />
<ComboBox x:Name="RedNemriTailowhayi"
Style="{StaticResource KirjasdraRadocemsouMainouhaltuTasmejirComboBox}" />
</StackPanel>
<Button Margin="10,10,10,10" VerticalAlignment="Bottom" Content="确定" Click="JowhuRudi_OnClick" />
</Grid>
</Grid>

在后台代码的构造函数加载图片

       public MainWindow()
{
InitializeComponent(); var caitelooPeeSidreharTadri = Enum.GetNames(typeof(YimiXoujelneTi)).ToList();
BlueDallstartaxaJembere.ItemsSource = caitelooPeeSidreharTadri;
GreenTrelqarnelNayke.ItemsSource = caitelooPeeSidreharTadri;
RedNemriTailowhayi.ItemsSource = caitelooPeeSidreharTadri; BlueDallstartaxaJembere.SelectedIndex = 0;
GreenTrelqarnelNayke.SelectedIndex = 0;
RedNemriTailowhayi.SelectedIndex = 0; _kearsisawjurNerasJaspahir = GetImage("pack://application:,,,/orion-nebula-11107_640.jpg");
_pasfuTeabou = GetImage("pack://application:,,,/solar-system-11188_640.jpg"); JaitetiDrokowPiskikaroImage.Source = _kearsisawjurNerasJaspahir;
NojerecalkeLeahuBemnercerfi.Source = _pasfuTeabou;
} private WriteableBitmap GetImage(string url)
{
var stream = Application.GetResourceStream(new Uri(url))?.Stream ?? throw new ArgumentException(); 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(); return new WriteableBitmap(formatConvertedBitmap);
} private WriteableBitmap _kearsisawjurNerasJaspahir;
private WriteableBitmap _pasfuTeabou;

在按钮点击的时候按照选项创建中间图片

        private void JowhuRudi_OnClick(object sender, RoutedEventArgs e)
{
unsafe
{
var lardiqaMesearToseNurrai = (byte*) _kearsisawjurNerasJaspahir.BackBuffer;
var tayjaytumalFoubor = _kearsisawjurNerasJaspahir.PixelWidth * _kearsisawjurNerasJaspahir.PixelHeight *
_kearsisawjurNerasJaspahir.Format.BitsPerPixel / 8; var yearcayralBawa = (byte*) _pasfuTeabou.BackBuffer;
var douxouJebirjapowMerema = _pasfuTeabou.PixelWidth * _pasfuTeabou.PixelHeight *
_pasfuTeabou.Format.BitsPerPixel / 8; var risnistaDurjair = new WriteableBitmap(_kearsisawjurNerasJaspahir.PixelWidth,
_kearsisawjurNerasJaspahir.PixelHeight, 96, 96, PixelFormats.Bgra32, null); byte[] saworCearsouCallfekenai = new byte[tayjaytumalFoubor]; for (int i = 0; i + 4 < tayjaytumalFoubor; i += 4)
{
var blue = lardiqaMesearToseNurrai[i];
var green = lardiqaMesearToseNurrai[i + 1];
var red = lardiqaMesearToseNurrai[i + 2];
var alpha = lardiqaMesearToseNurrai[i + 3]; if (i + 4 < douxouJebirjapowMerema)
{
blue = MupalSiluburwor(blue, yearcayralBawa[i],
BlueDallstartaxaJembere.SelectedItem?.ToString());
green = MupalSiluburwor(green, yearcayralBawa[i + 1],
GreenTrelqarnelNayke.SelectedItem?.ToString());
red = MupalSiluburwor(red, yearcayralBawa[i + 2], RedNemriTailowhayi.SelectedItem?.ToString()); byte MupalSiluburwor(byte celtroosiBalhaibelsowPisdelairjem, byte jenalearTurdoumou,
string pisemBalvetay)
{
if (string.IsNullOrEmpty(pisemBalvetay))
{
return celtroosiBalhaibelsowPisdelairjem;
} if (Enum.TryParse(pisemBalvetay, out YimiXoujelneTi soKooworstarWhisvemsal))
{
switch (soKooworstarWhisvemsal)
{
case YimiXoujelneTi.Or:
return (byte) (celtroosiBalhaibelsowPisdelairjem | jenalearTurdoumou);
case YimiXoujelneTi.And:
return (byte) (celtroosiBalhaibelsowPisdelairjem & jenalearTurdoumou);
case YimiXoujelneTi.Xor:
return (byte) (celtroosiBalhaibelsowPisdelairjem ^ jenalearTurdoumou);
}
} return celtroosiBalhaibelsowPisdelairjem;
}
} saworCearsouCallfekenai[i] = blue;
saworCearsouCallfekenai[i + 1] = green;
saworCearsouCallfekenai[i + 2] = red;
saworCearsouCallfekenai[i + 3] = alpha;
} risnistaDurjair.WritePixels(
new Int32Rect(0, 0, _kearsisawjurNerasJaspahir.PixelWidth, _kearsisawjurNerasJaspahir.PixelHeight),
saworCearsouCallfekenai, 4 * risnistaDurjair.PixelWidth, 0); MeamouceaxaPooricoumo.Source = risnistaDurjair;
}
}

2018-10-20-WPF-通过位处理合并图片的更多相关文章

  1. WPF 通过位处理合并图片

    原文:WPF 通过位处理合并图片 本文告诉大家,在使用 WPF 合并两张图片的处理,可以使用像素之间的与或和异或的方式,对三个颜色的通道进行处理. 先给大家看一下软件的界面 这就是通过将左边的两张图片 ...

  2. OSC Source Code Innovation Salon(2018.10.20)

    时间:2018.10.20地点:北京 朝阳 浦项中心B座2层

  3. 2018.10.20 2018-2019 ICPC,NEERC,Southern Subregional Contest(Online Mirror, ACM-ICPC Rules)

    i207M的“怕不是一个小时就要弃疗的flag”并没有生效,这次居然写到了最后,好评=.= 然而可能是退役前和i207M的最后一场比赛了TAT 不过打得真的好爽啊QAQ 最终结果: 看见那几个罚时没, ...

  4. 【2018.10.20】CXM笔记(思维)

    1. 给你个环状字符串,问从哪个地方拆开能使它的字典序最小. 先预处理任意子串的哈希值. 然后枚举拆点,将它与当前最优的拆点比较谁更优(就是从哪拆的字典序更小),具体方法是二分+哈希找出两串最长的相同 ...

  5. 2018.10.20 XMYZ Day1总结

    上周的忘写了……题目没有作者…… T1.backpack 期望得分100,实际得分100. 感觉我自己真是不如以前了……以前做这种题都是秒掉的,现在怎么想了10分钟啊…… 因为物品的体积和价值都非常小 ...

  6. POI 2018.10.20

    [POI2005]BANK-Cash Dispenser 有多少个4位字符串是所有操作序列的子串. 10^4枚举字符串.暴力判断会TLE 发现,我们就是在每个操作序列中不断找第一个出现的c字符. 预处 ...

  7. 2018.10.20 bzoj2748: [HAOI2012]音量调节(背包)

    传送门 这题是不是太sbsbsb了一点. 难度直逼普及-. 直接背包判存在性就行了. 代码: #include<bits/stdc++.h> using namespace std; bo ...

  8. 2018.10.20 bzoj1925: [Sdoi2010]地精部落(dp)

    传送门 dp好题. 设f[i][j]f[i][j]f[i][j]表示iii个数结尾是jjj且结尾两个数递增的方案数. 那么显然可以对称的定义出g[i][j]g[i][j]g[i][j]表示iii个数结 ...

  9. 2018.10.20 bzoj1079: [SCOI2008]着色方案(多维dp)

    传送门 dp妙题. f[a][b][c][d][e][last]f[a][b][c][d][e][last]f[a][b][c][d][e][last]表示还剩下aaa个可以用一次的,还剩下bbb个可 ...

  10. 2018.10.20 bzoj1068: [SCOI2007]压缩(区间dp)

    传送门 这题转移很妙啊. f[l][r][1/0]f[l][r][1/0]f[l][r][1/0]表示对于区间[l,r][l,r][l,r]有/无重复的机会时压缩的最小值. 那么可以从三种情况转移过来 ...

随机推荐

  1. Django高级实战 开发企业级问答网站

    Django高级实战 开发企业级问答网站 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的 ...

  2. Python网络爬虫与信息提取[request库的应用](单元一)

    ---恢复内容开始--- 注:学习中国大学mooc 嵩天课程 的学习笔记 request的七个主要方法 request.request() 构造一个请求用以支撑其他基本方法 request.get(u ...

  3. 2019.8.7 NOIP模拟测试14 反思总结

    先扔代码 调完自闭网络流了,新一轮考试前看看能不能赶完…… 考得极其爆炸,心态也极其爆炸,真的是认识到自己能力上的不足 思维跑偏,代码能力差 就这样吧,再努力努力,不行就AFO T1旋转子段: 因为我 ...

  4. Leetcode46. Permutations全排列

    给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1 ...

  5. MS17-010远程溢出漏洞 - 永恒之蓝 [CVE-2017-0143]

    MS17-010远程溢出漏洞(永恒之蓝) Ti:2019-12-25 By:Mirror王宇阳 MS17-010 CVE-2017-0143 MS17-010 CVE-2017-0144 MS17-0 ...

  6. 【JZOJ4711】【NOIP2016提高A组模拟8.17】Binary

    题目描述 输入 输出 样例输入 6 6 8 9 1 13 9 3 1 4 5 2 6 9 1 3 7 2 7 7 1 6 1 2 11 13 样例输出 45 19 21 数据范围 解法 40%暴力即可 ...

  7. 洛谷 P1858 多人背包 DP

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 题面 题目链接 洛谷 P1858 多人背包 题目描述 求01背包前k优解的价值 ...

  8. 【水滴石穿】RNNewsGo

    项目地址为:https://github.com/ImVeryGood/RNNewsGo 我们先来看一下页面 分析了一下项目,项目也是有用到redux-saga的 然后模块比较清晰 接下来我们分析代码 ...

  9. 【水滴石穿】react-native-app

    项目地址:https://github.com/WQone/react-native-app 这个是一个非常优秀的小姐姐写的,希望大家能够以她为榜样,一起加油进步呀- 先看效果 分析package.j ...

  10. spark-ML基础

    一.ML组件 ML的标准API使用管道(pipeline)这样的方式,可以将多个算法或者数据处理过程整合到一个管道或者一个流程里运行,其中包含下面几个部分: 1. dataFrame:用于ML的dat ...