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. Python基础-列表、元组、字典、字符串

    Python基础-列表.元组.字典.字符串   多维数组 nums1 = [1,2,3] #一维数组 nums2 = [1,2,3,[4,56]] #二维数组 nums3 = [1,2,3,4,['a ...

  2. linux设置变量的三种方法

    1在/etc/profile文件中添加变量对所有用户生效(永久的) 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且是“永久生效”. 例如:编辑/etc/ ...

  3. SQLyog12.0.9下载、安装和破解

    原文转载连接:https://blog.csdn.net/lihua5419/article/details/73881837/ sqlyog百度云链接(永久有效):http://pan.baidu. ...

  4. C位域的初步了解

    以为C中的东西了解的差不多了...今天却是第一次才看到位域这个概念, 闲来无事的时候读起了编程之美,看一个问题的时候有种解答用到了位域, 位域的结构体定义,变量声明和结构体很相似: struct (结 ...

  5. 百度DMLC分布式深度机器学习开源项目(简称“深盟”)上线了如xgboost(速度快效果好的Boosting模型)、CXXNET(极致的C++深度学习库)、Minerva(高效灵活的并行深度学习引擎)以及Parameter Server(一小时训练600T数据)等产品,在语音识别、OCR识别、人脸识别以及计算效率提升上发布了多个成熟产品。

    百度为何开源深度机器学习平台?   有一系列领先优势的百度却选择开源其深度机器学习平台,为何交底自己的核心技术?深思之下,却是在面对业界无奈时的远见之举.   5月20日,百度在github上开源了其 ...

  6. LintCode 合并二维数组

    合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 之前想的是用剑指offer里替换空格那种方法 但是把 ...

  7. 从0开始学习 GitHub 系列之「02.加入 GitHub」

    转载地址: http://blog.csdn.net/googdev/article/details/52787586 看完昨天的文章「从0开始学习 GitHub 系列之「初识 GitHub」」估计不 ...

  8. objectarx MFC 非模态对话框为当前焦点

    dialog.h afx_msg LRESULT OnAcadKeepFocus(WPARAM, LPARAM); dialog.cpp BEGIN_MESSAGE_MAP(CTextDialog, ...

  9. COOKIE与SESSION的详解

    cookie与session的小例子: 包含cookie记住登录名,session防止用户非法登录2个例子: 问我拿吧,这个下载连接挂了 描述 cookie过程描述 网站为了辨别用户身份.进行 ses ...

  10. Ubuntu无法连接无线网

    shell里输入: su ifconfig wlan0 up 不行的话 rfkill block all rfkill unblock all ifconfig wlan0 up