wpf通过位处理合并图片(代码片段)

lonelyxmas lonelyxmas     2023-02-18     158

关键词:

原文: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;
            
        

技术分享图片


本文会经常更新,请阅读原文: https://lindexi.gitee.io/lindexi/post/WPF-%E9%80%9A%E8%BF%87%E4%BD%8D%E5%A4%84%E7%90%86%E5%90%88%E5%B9%B6%E5%9B%BE%E7%89%87.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

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

wpf修改图片颜色(代码片段)

...修改里面的元素的值。如我需要去掉图片的蓝色,就可以通过修改ARBG数组的元素,设置所有蓝色为0,去掉蓝色。读取图片首先找到一张好看的图片,放在解决方案读取解决方案的图片varstream=Application.GetResourceStream(newUri("pack://app... 查看详情

cf662cbinarytable按位处理

...也不知道叫啥了,说状压也不对,说fwt也不太对,就叫按位处理得了。显然有$O(2^nm)$暴力,先枚举每行是否取反,然后枚举每列,如果0多就取反,否则不取。但我们发现我们完全可以将本质相同的列 查看详情

在wpf显示动态gif图片(代码片段)

....gif"/>上面这种用法是预览的GIF图片是静止不动的。通过使用WpfAnimatedGif我们可以在WPF应用程序中预览、控制GIF图片。WpfAnimatedGif的gitbub地址https://github.com/XamlAnimatedGif/WpfAnimatedGifWpfAnimatedGif的使用方法https://github.com/XamlAnimatedG... 查看详情

wpf加载图片(代码片段)

WPF加载图片并且不占用文件资源的方式:ImageSource=BitmapFrame.Create(newUri(info.FileName),BitmapCreateOptions.None,BitmapCacheOption.OnLoad);  查看详情

wpf图片查看器(代码片段)

一、功能需求:1、打开图片、打开文件夹;2、下一张、上一张图片;3、支持拖动、缩放、还原图片显示适当大小;cs部分代码1///<summary>2///InteractionlogicforImageView.xaml3///</summary>4publicpartialclassImageView:UserControl56publicImageView... 查看详情

wpf自定义图片按钮(代码片段)

原文:WPF自定义图片按钮此文档仅仅是一个BaseCode,已做后续查阅XAML代码:<Buttonx:Class="IM.UI.UC.IM_ImageButton"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/ 查看详情

浅谈trie(代码片段)

trie介绍算法思想trie是一种字符串处理操作,是通过将重复的地方重合起来实现对内存的压缩比如说对于ILLAKIOIILLBEAKEDBYIOI进行合并那么就是通过压位处理将公共部分ILL合并起来就行了但是我们还是有不同的部分那么在分开存储不... 查看详情

wpf保存image控件里的图片(代码片段)

原文:WPF保存image控件里的图片stringProImgPath=ProcessPath+name+".png";//要保存的图片的地址,包含文件名BitmapSourceBS=(BitmapSource)ImgPro.Source;PngBitmapEncoderPBE=newPngBitmapEncoder();PBE.Frames.Add(BitmapFrame.Create(BS)) 查看详情

wpfの命中测试(代码片段)

...vas中元素增加到一定数量,并且有重合的时候,我们如何通过在Canvas中点击鼠标,获得我们想要的元素,然后再对该元素做出相应的控制?命中测试,可以很好地解决这个问题本文目的: 使用命中测试,选取Canvas中相应Elemen... 查看详情

wpf中datagrid显示图片,绑定图片路径显示(代码片段)

Xaml页面<Pagex:Class="WpfSnqkGasAnalysis.PageUser"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xam 查看详情

streamsapi(代码片段)

StreamsAPI允许JavaScript以编程的方式访问通过网络接收的数据流,并根据开发人员的需要处理它们。概念和用法流将你希望通过网络接收的资源拆分成小块,然后按位处理它。这正是浏览器在接收用于显示web页面的资源时做... 查看详情

一个非常简陋的基于lfsr和feistel网络的加解密运算,有位处理。c

刚布置的热乎作业,马上就写了。。如果是正在做这个作业的同学搜到别抄,写得垃圾不要抄不要抄不要抄,特别是吉大的同学,谢谢==1#include<stdio.h>2#include<math.h>3#defineN1284#defineindexint567voidFFunc(char*Result,char*R,charkey,intlen... 查看详情

wpf通过附加属性控制窗口关闭(代码片段)

场景1当使用ShowDialog()方式显示窗口时,通过定义附加属性的方式可实现在ViewModel中进行数据绑定(bool?)来控制子窗口的显示和关闭publicclassExWindowpublicstaticbool?GetDialogResult(DependencyObjectobj)return(bool?)obj.GetValue(DialogResultProperty);p 查看详情

wpf通过名称查找属性(dependencyproperty)(代码片段)

...名称来查找DependencyProperty。如果有这样的需求,则是需要通过DependencyPropertyDescriptor来查找。通常是使用附加属性或者依赖属性的方法。下面给出附加属性的例子:  这个是注册附加属性,利用string来输入要查找的属性publi... 查看详情

wpf钟表效果实现(代码片段)

...为WpfClock,新建一个images文件夹,并准备一个钟表的背景图片和程序图标素材。2、编辑MainWindow.xaml文件,对UI进行定制,代码如下(指针都是用Rectangle实现的,当然可以用图片代替):1< 查看详情

wpf下两种图片合成或加水印的方式(转载)(代码片段)

...:http://www.cnblogs.com/lxblog/ 最近项目中应用多次应用了图片合成,为了今后方便特此记下。在WPF下有两种图片合成的方式,一种还是用原来C#提供的GDI+方式,命名空间是System.Drawing和 System.Drawing.Imaging,另一种是WPF中新添加... 查看详情

wpf抽屉效果(代码片段)

...开发中有抽屉效果,就是在页面的边上有一个按钮,可以通过点击或者拖拽这个按钮,让页面显示。Wpf也可以实现相同的效果。 主要是通过一个DoubleAnimation和RectAnimation动画实现<GridHorizontalAlignment="Center"Width="90"Height="130"Back... 查看详情

wpf中的多点触摸事件(代码片段)

...摸事件UIElement在WPF4下添加了很多支持多点触摸的事件,通过它们可以在硬件支持的情况下处理多点触摸,以下通过代码来说明通过处理这些事件,我们可以做些什么:一.触摸相关的多种事件,跟鼠标事件是对应的,通过这些事... 查看详情