프로젝트

일반

사용자정보

개정판 6b6e937c

ID6b6e937c0280d92364d7871a659cf80c31830fc4
상위 f63cd748
하위 cf390680

김태성이(가) 약 5년 전에 추가함

Compare기능 수정

Change-Id: I3697fbe30f47d5cc4a51ece85df0055f7c596bf2

차이점 보기:

ConvertService/ConverterService/Main/PDFConverter/.vs/config/applicationhost.config
162 162
            </site>
163 163
            <site name="ConvertionWebService" id="2">
164 164
                <application path="/" applicationPool="Clr4IntegratedAppPool">
165
                    <virtualDirectory path="/" physicalPath="C:\Temp\Workspace\MARKUS\ConvertService\ConverterService\ConvertionWebService" />
165
                    <virtualDirectory path="/" physicalPath="D:\Source\Repos\MARKUS\ConvertService\ConverterService\ConvertionWebService" />
166 166
                </application>
167 167
                <bindings>
168 168
                    <binding protocol="http" bindingInformation="*:5295:localhost" />
ConvertService/ServiceBase/ConvertionWebService/Properties/Settings.Designer.cs
34 34
        
35 35
        [global::System.Configuration.ApplicationScopedSettingAttribute()]
36 36
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
37
        [global::System.Configuration.DefaultSettingValueAttribute("tcp://cloud.devdoftech.co.kr:8091/remConverterPDF")]
38
        public string ConverterRemotingUrl {
39
            get {
40
                return ((string)(this["ConverterRemotingUrl"]));
41
            }
42
        }
43
        
44
        [global::System.Configuration.ApplicationScopedSettingAttribute()]
45
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
46 37
        [global::System.Configuration.DefaultSettingValueAttribute("000000,111111")]
47 38
        public string MARKUS_V3_PROJECTS {
48 39
            get {
......
76 67
                return ((string)(this["Excelfilepath"]));
77 68
            }
78 69
        }
70
        
71
        [global::System.Configuration.ApplicationScopedSettingAttribute()]
72
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
73
        [global::System.Configuration.DefaultSettingValueAttribute("tcp://localhost:8091/remConverterPDF")]
74
        public string ConverterRemotingUrl {
75
            get {
76
                return ((string)(this["ConverterRemotingUrl"]));
77
            }
78
        }
79 79
    }
80 80
}
ConvertService/ServiceBase/ConvertionWebService/Properties/Settings.settings
5 5
    <Setting Name="ErrorNoticeID" Type="System.String" Scope="Application">
6 6
      <Value Profile="(Default)" />
7 7
    </Setting>
8
    <Setting Name="ConverterRemotingUrl" Type="System.String" Scope="Application">
9
      <Value Profile="(Default)">tcp://cloud.devdoftech.co.kr:8091/remConverterPDF</Value>
10
    </Setting>
11 8
    <Setting Name="MARKUS_V3_PROJECTS" Type="System.String" Scope="Application">
12 9
      <Value Profile="(Default)">000000,111111</Value>
13 10
    </Setting>
......
20 17
    <Setting Name="Excelfilepath" Type="System.String" Scope="Application">
21 18
      <Value Profile="(Default)">\\172.20.121.220\comment3\TileSource\Excelexport</Value>
22 19
    </Setting>
20
    <Setting Name="ConverterRemotingUrl" Type="System.String" Scope="Application">
21
      <Value Profile="(Default)">tcp://localhost:8091/remConverterPDF</Value>
22
    </Setting>
23 23
  </Settings>
24 24
</SettingsFile>
ConvertService/ServiceBase/ConvertionWebService/Web.config
24 24
  <applicationSettings>
25 25
    <ConvertionWebService.Properties.Settings>
26 26
      <setting name="ErrorNoticeID" serializeAs="String">
27
        <value/>
28
      </setting>
29
      <setting name="ConverterRemotingUrl" serializeAs="String">
30
        <value>tcp://localhost:8091/remConverterPDF</value>
27
        <value />
31 28
      </setting>
32 29
      <setting name="MARKUS_V3_PROJECTS" serializeAs="String">
33 30
        <value>000000,111111</value>
......
41 38
      <setting name="Excelfilepath" serializeAs="String">
42 39
        <value>\\172.20.121.220\comment3\TileSource\Excelexport</value>
43 40
      </setting>
41
      <setting name="ConverterRemotingUrl" serializeAs="String">
42
        <value>tcp://localhost:8091/remConverterPDF</value>
43
      </setting>
44 44
    </ConvertionWebService.Properties.Settings>
45 45
  </applicationSettings>
46 46
  <system.serviceModel>
ConvertService/ServiceBase/ServiceTestApp/MainWindow.xaml.cs
2 2
using Markus.Service;
3 3
using Markus.Service.Extensions;
4 4
using Markus.Service.Helper;
5
using Microsoft.VisualStudio.TestTools.UnitTesting;
6 5
using Microsoft.Win32;
7 6
using Newtonsoft.Json;
8 7
using Newtonsoft.Json.Linq;
......
169 168

  
170 169
        private System.Collections.ObjectModel.ObservableCollection<Markus.Service.Interface.ConvertItem> convertItems = new System.Collections.ObjectModel.ObservableCollection<Markus.Service.Interface.ConvertItem>();
171 170

  
172
        PrivateObject stationObj;
171
        private Object stationObj;
173 172
        Markus.Service.ServiceStation station = new Markus.Service.ServiceStation();
174 173

  
175 174
        private void Button_Click(object sender, RoutedEventArgs e)
ImageComparer/ComparerTestWPF/App.config
1
<?xml version="1.0" encoding="utf-8" ?>
2
<configuration>
3
    <startup> 
4
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5
    </startup>
6
</configuration>
ImageComparer/ComparerTestWPF/App.xaml
1
<Application x:Class="ComparerTestWPF.App"
2
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
             xmlns:local="clr-namespace:ComparerTestWPF"
5
             StartupUri="MainWindow.xaml">
6
    <Application.Resources>
7
         
8
    </Application.Resources>
9
</Application>
ImageComparer/ComparerTestWPF/App.xaml.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Configuration;
4
using System.Data;
5
using System.Linq;
6
using System.Threading.Tasks;
7
using System.Windows;
8

  
9
namespace ComparerTestWPF
10
{
11
    /// <summary>
12
    /// App.xaml에 대한 상호 작용 논리
13
    /// </summary>
14
    public partial class App : Application
15
    {
16
    }
17
}
ImageComparer/ComparerTestWPF/ComparerTestWPF.csproj
1
<?xml version="1.0" encoding="utf-8"?>
2
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4
  <PropertyGroup>
5
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7
    <ProjectGuid>{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}</ProjectGuid>
8
    <OutputType>WinExe</OutputType>
9
    <RootNamespace>ComparerTestWPF</RootNamespace>
10
    <AssemblyName>ComparerTestWPF</AssemblyName>
11
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
12
    <FileAlignment>512</FileAlignment>
13
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
14
    <WarningLevel>4</WarningLevel>
15
    <Deterministic>true</Deterministic>
16
  </PropertyGroup>
17
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
18
    <PlatformTarget>AnyCPU</PlatformTarget>
19
    <DebugSymbols>true</DebugSymbols>
20
    <DebugType>full</DebugType>
21
    <Optimize>false</Optimize>
22
    <OutputPath>bin\Debug\</OutputPath>
23
    <DefineConstants>DEBUG;TRACE</DefineConstants>
24
    <ErrorReport>prompt</ErrorReport>
25
    <WarningLevel>4</WarningLevel>
26
    <Prefer32Bit>false</Prefer32Bit>
27
  </PropertyGroup>
28
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
29
    <PlatformTarget>AnyCPU</PlatformTarget>
30
    <DebugType>pdbonly</DebugType>
31
    <Optimize>true</Optimize>
32
    <OutputPath>bin\Release\</OutputPath>
33
    <DefineConstants>TRACE</DefineConstants>
34
    <ErrorReport>prompt</ErrorReport>
35
    <WarningLevel>4</WarningLevel>
36
  </PropertyGroup>
37
  <ItemGroup>
38
    <Reference Include="System" />
39
    <Reference Include="System.Data" />
40
    <Reference Include="System.Drawing" />
41
    <Reference Include="System.Xml" />
42
    <Reference Include="Microsoft.CSharp" />
43
    <Reference Include="System.Core" />
44
    <Reference Include="System.Xml.Linq" />
45
    <Reference Include="System.Data.DataSetExtensions" />
46
    <Reference Include="System.Net.Http" />
47
    <Reference Include="System.Xaml">
48
      <RequiredTargetFramework>4.0</RequiredTargetFramework>
49
    </Reference>
50
    <Reference Include="Telerik.Windows.Controls, Version=2019.3.917.45, Culture=neutral, PublicKeyToken=5803cfa389c90ce7, processorArchitecture=MSIL" />
51
    <Reference Include="Telerik.Windows.Controls.ImageEditor, Version=2019.3.917.45, Culture=neutral, PublicKeyToken=5803cfa389c90ce7, processorArchitecture=MSIL" />
52
    <Reference Include="Telerik.Windows.Controls.Input, Version=2019.3.917.45, Culture=neutral, PublicKeyToken=5803cfa389c90ce7, processorArchitecture=MSIL" />
53
    <Reference Include="WindowsBase" />
54
    <Reference Include="PresentationCore" />
55
    <Reference Include="PresentationFramework" />
56
  </ItemGroup>
57
  <ItemGroup>
58
    <ApplicationDefinition Include="App.xaml">
59
      <Generator>MSBuild:Compile</Generator>
60
      <SubType>Designer</SubType>
61
    </ApplicationDefinition>
62
    <Page Include="MainWindow.xaml">
63
      <Generator>MSBuild:Compile</Generator>
64
      <SubType>Designer</SubType>
65
    </Page>
66
    <Compile Include="App.xaml.cs">
67
      <DependentUpon>App.xaml</DependentUpon>
68
      <SubType>Code</SubType>
69
    </Compile>
70
    <Compile Include="MainWindow.xaml.cs">
71
      <DependentUpon>MainWindow.xaml</DependentUpon>
72
      <SubType>Code</SubType>
73
    </Compile>
74
    <Page Include="ImageView.xaml">
75
      <SubType>Designer</SubType>
76
      <Generator>MSBuild:Compile</Generator>
77
    </Page>
78
  </ItemGroup>
79
  <ItemGroup>
80
    <Compile Include="Properties\AssemblyInfo.cs">
81
      <SubType>Code</SubType>
82
    </Compile>
83
    <Compile Include="ImageView.xaml.cs">
84
      <DependentUpon>ImageView.xaml</DependentUpon>
85
    </Compile>
86
    <Compile Include="Properties\Resources.Designer.cs">
87
      <AutoGen>True</AutoGen>
88
      <DesignTime>True</DesignTime>
89
      <DependentUpon>Resources.resx</DependentUpon>
90
    </Compile>
91
    <Compile Include="Properties\Settings.Designer.cs">
92
      <AutoGen>True</AutoGen>
93
      <DependentUpon>Settings.settings</DependentUpon>
94
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
95
    </Compile>
96
    <EmbeddedResource Include="Properties\Resources.resx">
97
      <Generator>ResXFileCodeGenerator</Generator>
98
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
99
    </EmbeddedResource>
100
    <None Include="Properties\Settings.settings">
101
      <Generator>SettingsSingleFileGenerator</Generator>
102
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
103
    </None>
104
  </ItemGroup>
105
  <ItemGroup>
106
    <None Include="App.config" />
107
  </ItemGroup>
108
  <ItemGroup>
109
    <ProjectReference Include="..\Markus.ImageComparer\Markus.Image.csproj">
110
      <Project>{b3b05ced-f4eb-4f9d-b458-12fcbe48d546}</Project>
111
      <Name>Markus.Image</Name>
112
    </ProjectReference>
113
  </ItemGroup>
114
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
115
</Project>
ImageComparer/ComparerTestWPF/ImageView.xaml
1
<Window x:Class="ComparerTestWPF.ImageView"
2
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6
        xmlns:local="clr-namespace:ComparerTestWPF.Properties"
7
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
8
        mc:Ignorable="d"
9
        Title="ImageView" Height="450" Width="800">
10
    <Grid>
11
        <telerik:RadImageEditor  x:Name="image"/>
12
    </Grid>
13
</Window>
ImageComparer/ComparerTestWPF/ImageView.xaml.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using System.Windows;
7
using System.Windows.Controls;
8
using System.Windows.Data;
9
using System.Windows.Documents;
10
using System.Windows.Input;
11
using System.Windows.Media;
12
using System.Windows.Media.Imaging;
13
using System.Windows.Shapes;
14

  
15
namespace ComparerTestWPF
16
{
17
    /// <summary>
18
    /// ImageView.xaml에 대한 상호 작용 논리
19
    /// </summary>
20
    public partial class ImageView : Window
21
    {
22
        public ImageView(BitmapSource img)
23
        {
24
            InitializeComponent();
25

  
26
            this.image.Image = new Telerik.Windows.Media.Imaging.RadBitmap(img);
27
        }
28
    }
29
}
ImageComparer/ComparerTestWPF/MainWindow.xaml
1
<Window x:Class="ComparerTestWPF.MainWindow"
2
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6
        xmlns:local="clr-namespace:ComparerTestWPF"
7
        mc:Ignorable="d"
8
        Title="MainWindow" Height="450" Width="800">
9
    <Grid>
10
        <Grid.RowDefinitions>
11
            <RowDefinition Height="Auto"/>
12
            <RowDefinition/>
13
            <RowDefinition/>
14
        </Grid.RowDefinitions>
15
        <StackPanel>
16
            <StackPanel.Resources>
17
                <Style TargetType="TextBlock">
18
                    <Setter Property="FontSize" Value="20"/>
19
                </Style>
20
                <Style TargetType="TextBox">
21
                    <Setter Property="FontSize" Value="20"/>
22
                    <Setter Property="MinWidth" Value="400"/>
23
                </Style>
24
            </StackPanel.Resources>
25
            <TextBlock Text="비교 대상 이미지 선택"/>
26
            <StackPanel Orientation="Horizontal">
27
                <TextBlock Text="원본       "/>
28
                <TextBox x:Name="TxtOriginalImage"/>
29
                <Button Content="찾기" Click="btFindOriginalFile_click"/>
30
            </StackPanel>
31
            <StackPanel Orientation="Horizontal">
32
                <TextBlock Text="비교대상  "/>
33
                <TextBox x:Name="TxtTargetImage"/>
34
                <Button Content="찾기" Click="btFindTargetFile_click"/>
35
            </StackPanel>
36
        </StackPanel>
37
        <Grid Height="100" Width="200" Grid.Row="1">
38
        <Grid.RowDefinitions>
39
            <RowDefinition/>
40
            <RowDefinition/>
41
            <RowDefinition/>
42
        </Grid.RowDefinitions>
43
            <Button Content="동기 이미지 비교" Click="btNoneTask_Click"/>
44
            <Button Content="비동기 이미지 비교" Grid.Row="1" Click="btTask_Click"/>
45
            <Button Content="비동기 URI 이미지 비교" Grid.Row="2" Click="btTaskUri_Click"/>
46
        </Grid>
47
        <Grid Grid.Row="2">
48
            <Grid.ColumnDefinitions>
49
                <ColumnDefinition/>
50
                <ColumnDefinition/>
51
            </Grid.ColumnDefinitions>
52
            <DataGrid x:Name="lstView"/>
53
            <DataGrid x:Name="lstView2" Grid.Column="1"/>
54
        </Grid>
55
    </Grid>
56
</Window>
ImageComparer/ComparerTestWPF/MainWindow.xaml.cs
1
using Microsoft.Win32;
2
using System;
3
using System.Collections.Generic;
4
using System.Linq;
5
using System.Text;
6
using System.Threading.Tasks;
7
using System.Windows;
8
using System.Windows.Controls;
9
using System.Windows.Data;
10
using System.Windows.Documents;
11
using System.Windows.Input;
12
using System.Windows.Media;
13
using System.Windows.Media.Imaging;
14
using System.Windows.Navigation;
15
using System.Windows.Shapes;
16

  
17
namespace ComparerTestWPF
18
{
19
    /// <summary>
20
    /// MainWindow.xaml에 대한 상호 작용 논리
21
    /// </summary>
22
    public partial class MainWindow : Window
23
    {
24
        public MainWindow()
25
        {
26
            InitializeComponent();
27
        }
28

  
29

  
30
        private void btFindOriginalFile_click(object sender, RoutedEventArgs e)
31
        {
32
            TxtOriginalImage.Text = FileOpen();
33
        }
34

  
35
        private void btFindTargetFile_click(object sender, RoutedEventArgs e)
36
        {
37
            TxtTargetImage.Text = FileOpen();
38
        }
39

  
40
        private string FileOpen()
41
        {
42
            string result = null;
43

  
44
            OpenFileDialog openFileDialog = new OpenFileDialog();
45

  
46
            openFileDialog.Filter = "Image Files|*.png;*.jpg;*.bmp";
47

  
48
                if (openFileDialog.ShowDialog() == true)
49
                    result = openFileDialog.FileName;
50
                else
51
                    result = null;
52

  
53
            return result;
54
        }
55

  
56

  
57
        private void btNoneTask_Click(object sender, RoutedEventArgs e)
58
        {
59
            BitmapSource bitmapSource = null;
60
            BitmapSource TargetSource = null;
61

  
62
            using (Markus.Image.ImageComparer imageComparer = new Markus.Image.ImageComparer())
63
            {
64

  
65
                var original = new System.Drawing.Bitmap(TxtOriginalImage.Text);
66
                var target = new System.Drawing.Bitmap(TxtTargetImage.Text);
67

  
68
                var result = imageComparer.CompareDrawRects(original, target, new System.Drawing.Size(20, 20));
69
                
70
                bitmapSource = imageComparer.CreateWriteableBitmapFromBitmap(result);
71

  
72
                //var result2 = imageComparer.CompareDrawRects(target, original, new System.Drawing.Size(20, 20));
73
                //TargetSource = imageComparer.CreateBitmapSourceFromBitmap(result2);
74
                //result2.Dispose();
75
                //result2 = null;
76
                
77
                original.Dispose();
78
                target.Dispose();
79
            }
80

  
81

  
82
            ImageView imageView = new ImageView(bitmapSource);
83

  
84
            imageView.Show();
85

  
86

  
87
            //ImageView imageView2 = new ImageView(TargetSource);
88

  
89
            //imageView2.Show();
90
        }
91

  
92
        private async void btTask_Click(object sender, RoutedEventArgs e)
93
        {
94
            BitmapSource bitmapSource = null;
95
            BitmapSource TargetSource = null;
96

  
97
            using (Markus.Image.ImageComparer imageComparer = new Markus.Image.ImageComparer())
98
            {
99

  
100
                var original = new System.Drawing.Bitmap(TxtOriginalImage.Text);
101
                var target = new System.Drawing.Bitmap(TxtTargetImage.Text);
102

  
103
                var result = await imageComparer.CompareReturnRectsAsync(original, target, new System.Drawing.Size(20, 20));
104
                // bitmapSource = imageComparer.CreateWriteableBitmapFromBitmap(result);
105

  
106
                lstView.ItemsSource = result;
107

  
108
                var original2 = new System.Drawing.Bitmap(TxtOriginalImage.Text);
109
                var target2 = new System.Drawing.Bitmap(TxtTargetImage.Text);
110

  
111

  
112
                var result2 = await imageComparer.CompareReturnRectsAsync(target2, original2, new System.Drawing.Size(20, 20));
113

  
114
                lstView2.ItemsSource = result2;
115
                //TargetSource = imageComparer.CreateWriteableBitmapFromBitmap(result2);
116

  
117
                original.Dispose();
118
                target.Dispose();
119
            }
120
            
121

  
122
            //ImageView imageView = new ImageView(bitmapSource);
123

  
124
            //imageView.Show();
125

  
126
            //ImageView imageView2 = new ImageView(TargetSource);
127

  
128
            //imageView2.Show();
129
        }
130

  
131
        private async void btTaskUri_Click(object sender, RoutedEventArgs e)
132
        {
133

  
134
            using (Markus.Image.ImageComparer imageComparer = new Markus.Image.ImageComparer())
135
            {
136
                var result = await imageComparer.CompareReturnRectsAsync("http://192.168.0.67:5977/TileSource/000000_Tile/110001/11000102/1.png"
137
                    , "http://192.168.0.67:5977/TileSource/000000_Tile/110001/11000101/1.png", new System.Drawing.Size(20, 20));
138
                // bitmapSource = imageComparer.CreateWriteableBitmapFromBitmap(result);
139

  
140
                lstView.ItemsSource = result;
141

  
142
                var result2 = await imageComparer.CompareReturnRectsAsync("http://192.168.0.67:5977/TileSource/000000_Tile/110001/11000101/1.png"
143
                    , "http://192.168.0.67:5977/TileSource/000000_Tile/110001/11000102/1.png", new System.Drawing.Size(20, 20));
144

  
145
                lstView2.ItemsSource = result2;
146
                //TargetSource = imageComparer.CreateWriteableBitmapFromBitmap(result2);
147

  
148
            }
149
        }
150
    }
151
}
ImageComparer/ComparerTestWPF/Properties/AssemblyInfo.cs
1
using System.Reflection;
2
using System.Resources;
3
using System.Runtime.CompilerServices;
4
using System.Runtime.InteropServices;
5
using System.Windows;
6

  
7
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 
8
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
9
// 이러한 특성 값을 변경하세요.
10
[assembly: AssemblyTitle("ComparerTestWPF")]
11
[assembly: AssemblyDescription("")]
12
[assembly: AssemblyConfiguration("")]
13
[assembly: AssemblyCompany("")]
14
[assembly: AssemblyProduct("ComparerTestWPF")]
15
[assembly: AssemblyCopyright("Copyright ©  2020")]
16
[assembly: AssemblyTrademark("")]
17
[assembly: AssemblyCulture("")]
18

  
19
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 
20
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
21
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
22
[assembly: ComVisible(false)]
23

  
24
//지역화 가능 응용 프로그램 빌드를 시작하려면 다음을 설정하세요.
25
//.csproj 파일에서 <PropertyGroup> 내에 <UICulture>CultureYouAreCodingWith</UICulture>를
26
//설정하십시오. 예를 들어 소스 파일에서 영어(미국)를
27
//사용하는 경우 <UICulture>를 en-US로 설정합니다. 그런 다음 아래
28
//NeutralResourceLanguage 특성의 주석 처리를 제거합니다. 아래 줄의 "en-US"를 업데이트하여
29
//프로젝트 파일의 UICulture 설정과 일치시킵니다.
30

  
31
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32

  
33

  
34
[assembly: ThemeInfo(
35
    ResourceDictionaryLocation.None, //테마별 리소스 사전의 위치
36
                                     //(페이지 또는 응용 프로그램 리소스 사진에
37
                                     // 리소스가 없는 경우에 사용됨)
38
    ResourceDictionaryLocation.SourceAssembly //제네릭 리소스 사전의 위치
39
                                              //(페이지 또는 응용 프로그램 리소스 사진에
40
                                              // 리소스가 없는 경우에 사용됨)
41
)]
42

  
43

  
44
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
45
//
46
//      주 버전
47
//      부 버전 
48
//      빌드 번호
49
//      수정 버전
50
//
51
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
52
// 지정되도록 할 수 있습니다.
53
// [assembly: AssemblyVersion("1.0.*")]
54
[assembly: AssemblyVersion("1.0.0.0")]
55
[assembly: AssemblyFileVersion("1.0.0.0")]
ImageComparer/ComparerTestWPF/Properties/Resources.Designer.cs
1
//------------------------------------------------------------------------------
2
// <auto-generated>
3
//     이 코드는 도구를 사용하여 생성되었습니다.
4
//     런타임 버전:4.0.30319.42000
5
//
6
//     파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
7
//     이러한 변경 내용이 손실됩니다.
8
// </auto-generated>
9
//------------------------------------------------------------------------------
10

  
11
namespace ComparerTestWPF.Properties
12
{
13

  
14

  
15
    /// <summary>
16
    ///   지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
17
    /// </summary>
18
    // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
19
    // 클래스에서 자동으로 생성되었습니다.
20
    // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여
21
    // ResGen을 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
22
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25
    internal class Resources
26
    {
27

  
28
        private static global::System.Resources.ResourceManager resourceMan;
29

  
30
        private static global::System.Globalization.CultureInfo resourceCulture;
31

  
32
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33
        internal Resources()
34
        {
35
        }
36

  
37
        /// <summary>
38
        ///   이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
39
        /// </summary>
40
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41
        internal static global::System.Resources.ResourceManager ResourceManager
42
        {
43
            get
44
            {
45
                if ((resourceMan == null))
46
                {
47
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ComparerTestWPF.Properties.Resources", typeof(Resources).Assembly);
48
                    resourceMan = temp;
49
                }
50
                return resourceMan;
51
            }
52
        }
53

  
54
        /// <summary>
55
        ///   이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을
56
        ///   재정의합니다.
57
        /// </summary>
58
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59
        internal static global::System.Globalization.CultureInfo Culture
60
        {
61
            get
62
            {
63
                return resourceCulture;
64
            }
65
            set
66
            {
67
                resourceCulture = value;
68
            }
69
        }
70
    }
71
}
ImageComparer/ComparerTestWPF/Properties/Resources.resx
1
<?xml version="1.0" encoding="utf-8"?>
2
<root>
3
  <!-- 
4
    Microsoft ResX Schema 
5
    
6
    Version 2.0
7
    
8
    The primary goals of this format is to allow a simple XML format 
9
    that is mostly human readable. The generation and parsing of the 
10
    various data types are done through the TypeConverter classes 
11
    associated with the data types.
12
    
13
    Example:
14
    
15
    ... ado.net/XML headers & schema ...
16
    <resheader name="resmimetype">text/microsoft-resx</resheader>
17
    <resheader name="version">2.0</resheader>
18
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23
        <value>[base64 mime encoded serialized .NET Framework object]</value>
24
    </data>
25
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27
        <comment>This is a comment</comment>
28
    </data>
29
                
30
    There are any number of "resheader" rows that contain simple 
31
    name/value pairs.
32
    
33
    Each data row contains a name, and value. The row also contains a 
34
    type or mimetype. Type corresponds to a .NET class that support 
35
    text/value conversion through the TypeConverter architecture. 
36
    Classes that don't support this are serialized and stored with the 
37
    mimetype set.
38
    
39
    The mimetype is used for serialized objects, and tells the 
40
    ResXResourceReader how to depersist the object. This is currently not 
41
    extensible. For a given mimetype the value must be set accordingly:
42
    
43
    Note - application/x-microsoft.net.object.binary.base64 is the format 
44
    that the ResXResourceWriter will generate, however the reader can 
45
    read any of the formats listed below.
46
    
47
    mimetype: application/x-microsoft.net.object.binary.base64
48
    value   : The object must be serialized with 
49
            : System.Serialization.Formatters.Binary.BinaryFormatter
50
            : and then encoded with base64 encoding.
51
    
52
    mimetype: application/x-microsoft.net.object.soap.base64
53
    value   : The object must be serialized with 
54
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55
            : and then encoded with base64 encoding.
56

  
57
    mimetype: application/x-microsoft.net.object.bytearray.base64
58
    value   : The object must be serialized into a byte array 
59
            : using a System.ComponentModel.TypeConverter
60
            : and then encoded with base64 encoding.
61
    -->
62
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63
    <xsd:element name="root" msdata:IsDataSet="true">
64
      <xsd:complexType>
65
        <xsd:choice maxOccurs="unbounded">
66
          <xsd:element name="metadata">
67
            <xsd:complexType>
68
              <xsd:sequence>
69
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
70
              </xsd:sequence>
71
              <xsd:attribute name="name" type="xsd:string" />
72
              <xsd:attribute name="type" type="xsd:string" />
73
              <xsd:attribute name="mimetype" type="xsd:string" />
74
            </xsd:complexType>
75
          </xsd:element>
76
          <xsd:element name="assembly">
77
            <xsd:complexType>
78
              <xsd:attribute name="alias" type="xsd:string" />
79
              <xsd:attribute name="name" type="xsd:string" />
80
            </xsd:complexType>
81
          </xsd:element>
82
          <xsd:element name="data">
83
            <xsd:complexType>
84
              <xsd:sequence>
85
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
86
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
87
              </xsd:sequence>
88
              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
89
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
90
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
91
            </xsd:complexType>
92
          </xsd:element>
93
          <xsd:element name="resheader">
94
            <xsd:complexType>
95
              <xsd:sequence>
96
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
97
              </xsd:sequence>
98
              <xsd:attribute name="name" type="xsd:string" use="required" />
99
            </xsd:complexType>
100
          </xsd:element>
101
        </xsd:choice>
102
      </xsd:complexType>
103
    </xsd:element>
104
  </xsd:schema>
105
  <resheader name="resmimetype">
106
    <value>text/microsoft-resx</value>
107
  </resheader>
108
  <resheader name="version">
109
    <value>2.0</value>
110
  </resheader>
111
  <resheader name="reader">
112
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
113
  </resheader>
114
  <resheader name="writer">
115
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116
  </resheader>
117
</root>
ImageComparer/ComparerTestWPF/Properties/Settings.Designer.cs
1
//------------------------------------------------------------------------------
2
// <auto-generated>
3
//     This code was generated by a tool.
4
//     Runtime Version:4.0.30319.42000
5
//
6
//     Changes to this file may cause incorrect behavior and will be lost if
7
//     the code is regenerated.
8
// </auto-generated>
9
//------------------------------------------------------------------------------
10

  
11
namespace ComparerTestWPF.Properties
12
{
13

  
14

  
15
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18
    {
19

  
20
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21

  
22
        public static Settings Default
23
        {
24
            get
25
            {
26
                return defaultInstance;
27
            }
28
        }
29
    }
30
}
ImageComparer/ComparerTestWPF/Properties/Settings.settings
1
<?xml version='1.0' encoding='utf-8'?>
2
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
3
  <Profiles>
4
    <Profile Name="(Default)" />
5
  </Profiles>
6
  <Settings />
7
</SettingsFile>
ImageComparer/Markus.Image.sln
1

2
Microsoft Visual Studio Solution File, Format Version 12.00
3
# Visual Studio 15
4
VisualStudioVersion = 15.0.28307.902
5
MinimumVisualStudioVersion = 10.0.40219.1
6
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markus.Image", "Markus.ImageComparer\Markus.Image.csproj", "{B3B05CED-F4EB-4F9D-B458-12FCBE48D546}"
7
EndProject
8
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComparerTestWPF", "ComparerTestWPF\ComparerTestWPF.csproj", "{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}"
9
EndProject
10
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuget", "Nuget", "{101826B1-FAA0-42AE-B81E-BF0B4CAD526F}"
11
	ProjectSection(SolutionItems) = preProject
12
		Nuget\Markus.Image.nupkg = Nuget\Markus.Image.nupkg
13
	EndProjectSection
14
EndProject
15
Global
16
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
17
		Debug|Any CPU = Debug|Any CPU
18
		Release|Any CPU = Release|Any CPU
19
	EndGlobalSection
20
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
21
		{B3B05CED-F4EB-4F9D-B458-12FCBE48D546}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22
		{B3B05CED-F4EB-4F9D-B458-12FCBE48D546}.Debug|Any CPU.Build.0 = Debug|Any CPU
23
		{B3B05CED-F4EB-4F9D-B458-12FCBE48D546}.Release|Any CPU.ActiveCfg = Release|Any CPU
24
		{B3B05CED-F4EB-4F9D-B458-12FCBE48D546}.Release|Any CPU.Build.0 = Release|Any CPU
25
		{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26
		{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
27
		{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
28
		{154D99CA-A021-4FFD-A590-5CEBF6C99BB3}.Release|Any CPU.Build.0 = Release|Any CPU
29
	EndGlobalSection
30
	GlobalSection(SolutionProperties) = preSolution
31
		HideSolutionNode = FALSE
32
	EndGlobalSection
33
	GlobalSection(ExtensibilityGlobals) = postSolution
34
		SolutionGuid = {845D8227-7407-4233-A0F3-E2E6CCDCA8B0}
35
	EndGlobalSection
36
EndGlobal
ImageComparer/Markus.ImageComparer/ImageComparer.cs
1
using Emgu.CV;
2
using Emgu.CV.Structure;
3
using System;
4
using System.Collections.Generic;
5
using System.Drawing;
6
using System.Drawing.Imaging;
7
using System.Linq;
8
using System.Text;
9
using System.Threading.Tasks;
10

  
11
namespace Markus.Image
12
{
13
    public class ImageComparer : ImageComparerBase
14
    {
15
        /// <summary>
16
        /// 이미지를 비교 후 원본 이미지에 Rect를 그린다.
17
        /// </summary>
18
        /// <param name="Originalbitmap">원본 이미지</param>
19
        /// <param name="TargatBitmap">비교대상 이미지</param>
20
        /// <param name="ResultRectSize">반환되는 Rect의 사이즈</param>
21
        /// <returns></returns>
22
        public Bitmap CompareDrawRects(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap, Size ResultRectSize)
23
        {
24
            var rects =  CompareReturnRects(Originalbitmap, TargatBitmap, ResultRectSize);
25

  
26
            if (rects.Count != 0)
27
            {
28
                using (Graphics g = Graphics.FromImage(Originalbitmap))
29
                {
30
                    var rect = rects.Select(x => new System.Drawing.Rectangle((int)x.X, (int)x.Y, (int)x.Width, (int)x.Height));
31

  
32
                    g.DrawRectangles(new Pen(Brushes.Blue, 3f), rect.ToArray());
33
                    g.Save();
34

  
35
                    g.Dispose();
36
                }
37
            }
38

  
39
            return Originalbitmap;
40
        }
41

  
42
        public System.Windows.Media.Imaging.BitmapSource CompareDrawRects(System.Windows.Media.Imaging.BitmapSource Originalbitmap, System.Windows.Media.Imaging.BitmapSource TargatBitmap, Size ResultRectSize)
43
        {
44
            var _Originalbitmap = CreateBitmapFromSource(Originalbitmap);
45
            var _TargatBitmap = CreateBitmapFromSource(TargatBitmap);
46

  
47
            var rects = CompareReturnRects(_Originalbitmap, _TargatBitmap, ResultRectSize);
48
         
49
            if (rects.Count != 0)
50
            {
51
                using (Graphics g = Graphics.FromImage(_Originalbitmap))
52
                {
53
                    var rect = rects.Select(x => new System.Drawing.Rectangle((int)x.X, (int)x.Y, (int)x.Width, (int)x.Height));
54

  
55
                    g.DrawRectangles(new Pen(Brushes.Blue, 3f), rect.ToArray());
56
                    g.Save();
57

  
58
                    g.Dispose();
59
                }
60
            }
61

  
62
            return CreateBitmapSourceFromBitmap(_Originalbitmap);
63
        }
64

  
65
        public List<System.Windows.Rect> CompareReturnRects(string OriginalbitmapUri, string TargatBitmapUri, Size ResultRectSize)
66
        {
67
            List<System.Windows.Rect> result = new List<System.Windows.Rect>();
68

  
69
            Bitmap Originalbitmap = null;
70
            Bitmap TargatBitmap = null;
71

  
72
            try
73
            {
74

  
75
                Originalbitmap = LoadPicture(OriginalbitmapUri);
76
                TargatBitmap = LoadPicture(TargatBitmapUri);
77

  
78
                result = CompareReturnRects(Originalbitmap, TargatBitmap, ResultRectSize);
79
            }
80
            catch (Exception)
81
            {
82
                throw;
83
            }
84
            finally
85
            {
86
                Originalbitmap.Dispose();
87
                TargatBitmap.Dispose();
88
            }
89

  
90
            return result;
91
        }
92

  
93
        /// <summary>
94
        /// 이미지를 비교 후 해당 영역을 Rect로 반환한다.
95
        /// </summary>
96
        /// <param name="Originalbitmap">원본 이미지</param>
97
        /// <param name="TargatBitmap">비교대상 이미지</param>
98
        /// <param name="ResultRectSize">반환되는 Rect의 사이즈</param>
99
        /// <returns></returns>
100
        public List<System.Windows.Rect> CompareReturnRects(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap, Size ResultRectSize)
101
        {
102
            List<System.Windows.Rect> result = new List<System.Windows.Rect>();
103

  
104
            try
105
            {
106
                byte[,,] data = MathchesImageData(Originalbitmap, TargatBitmap);
107

  
108
                result =  GetMatchPixels(data, ResultRectSize);
109
            }
110
            catch (Exception ex)
111
            {
112
                throw ex;
113
            }
114
            finally
115
            {
116

  
117
            }
118

  
119
            return result;
120
        }
121

  
122
        /// <summary>
123
        /// 이미지를 비교 후 원본 이미지에 Rect를 그린다.
124
        /// 메모리 문제 발생
125
        /// </summary>
126
        /// <param name="Originalbitmap">원본 이미지</param>
127
        /// <param name="TargatBitmap">비교대상 이미지</param>
128
        /// <param name="ResultRectSize">반환되는 Rect의 사이즈</param>
129
        /// <returns></returns>
130
        public async Task<Bitmap> CompareDrawRectsAsync(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap, Size ResultRectSize)
131
        {
132
            System.Drawing.Bitmap cloneOriginal = Originalbitmap;
133

  
134
            var rects = await CompareReturnRectsAsync(cloneOriginal, TargatBitmap, ResultRectSize);
135

  
136
            if (rects.Count != 0)
137
            {
138
                using (Graphics g = Graphics.FromImage(cloneOriginal))
139
                {
140
                    var rect = rects.Select(x => new System.Drawing.Rectangle((int)x.X, (int)x.Y, (int)x.Width, (int)x.Height));
141

  
142
                    g.DrawRectangles(new Pen(Brushes.Blue, 3f), rect.ToArray());
143
                    g.Save();
144

  
145
                    g.Dispose();
146
                }
147
            }
148

  
149
            return cloneOriginal;
150
        }
151

  
152
        /// <summary>
153
        /// 이미지를 비교 후 원본 이미지에 Rect를 그린다.
154
        /// 메모리 문제 발생
155
        /// </summary>
156
        /// <param name="Originalbitmap">원본 이미지</param>
157
        /// <param name="TargatBitmap">비교대상 이미지</param>
158
        /// <param name="ResultRectSize">반환되는 Rect의 사이즈</param>
159
        /// <returns></returns>
160
        public async Task<System.Windows.Media.Imaging.BitmapSource> CompareDrawRectsAsync(System.Windows.Media.Imaging.BitmapSource Originalbitmap, System.Windows.Media.Imaging.BitmapSource TargatBitmap, Size ResultRectSize)
161
        {
162

  
163
            var _Originalbitmap = CreateBitmapFromSource(Originalbitmap);
164
            var _TargatBitmap = CreateBitmapFromSource(TargatBitmap);
165

  
166
            var rects = await CompareReturnRectsAsync(_Originalbitmap, _TargatBitmap, ResultRectSize);
167

  
168
            if (rects.Count != 0)
169
            {
170
                using (Graphics g = Graphics.FromImage(_Originalbitmap))
171
                {
172
                    var rect = rects.Select(x => new System.Drawing.Rectangle((int)x.X, (int)x.Y, (int)x.Width, (int)x.Height));
173

  
174
                    g.DrawRectangles(new Pen(Brushes.Blue, 3f), rect.ToArray());
175
                    g.Save();
176

  
177
                    g.Dispose();
178
                }
179
            }
180

  
181
            return CreateBitmapSourceFromBitmap(_Originalbitmap);
182
        }
183

  
184
        public Bitmap CreateBitmapFromSource(System.Windows.Media.Imaging.BitmapSource bitmapsource)
185
        {
186
            //convert image format
187
            var src = new System.Windows.Media.Imaging.FormatConvertedBitmap();
188
            src.BeginInit();
189
            src.Source = bitmapsource;
190
            src.DestinationFormat = System.Windows.Media.PixelFormats.Bgr24;
191
            src.EndInit();
192

  
193
            //copy to bitmap
194
            Bitmap bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
195
            var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
196
            src.CopyPixels(System.Windows.Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
197
            bitmap.UnlockBits(data);
198

  
199
            return bitmap;
200
        }
201

  
202
        /// <summary>
203
        /// 메모리 문제 발생
204
        /// </summary>
205
        /// <param name="bitmap"></param>
206
        /// <returns></returns>
207
        public System.Windows.Media.Imaging.WriteableBitmap CreateWriteableBitmapFromBitmap(Bitmap bitmap)
208
        {
209
            System.Windows.Media.Imaging.WriteableBitmap result = null;
210

  
211
            if (bitmap == null)
212
                throw new ArgumentNullException("bitmap");
213

  
214
            try
215
            {
216
                int bytesPerPixel = 4;
217

  
218
                result = new System.Windows.Media.Imaging.WriteableBitmap(bitmap.Width, bitmap.Height,
219
                                                                   bitmap.HorizontalResolution ,bitmap.VerticalResolution,
220
                                                                   bitmap.PixelFormat.Convert(), null);
221

  
222
                Rectangle colorBitmapRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
223
                System.Windows.Int32Rect colorBitmapInt32Rect = new System.Windows.Int32Rect(0, 0, bitmap.Width, bitmap.Height);
224

  
225
                BitmapData data = bitmap.LockBits(colorBitmapRectangle, ImageLockMode.WriteOnly, bitmap.PixelFormat);
226

  
227
                result.WritePixels(colorBitmapInt32Rect, data.Scan0, data.Width * data.Height * bytesPerPixel, data.Stride);
228

  
229
                bitmap.UnlockBits(data);
230
            }
231
            catch (Exception ex)
232
            {
233
                //throw ex;
234
            }
235
            finally
236
            {
237
                bitmap.Dispose();
238
                bitmap = null;
239
                //GC.Collect(2);
240
            }
241

  
242
            return result;
243
        }
244
    
245
        /// <summary>
246
        /// 메모리 문제 발생
247
        /// </summary>
248
        /// <param name="bitmap"></param>
249
        /// <returns></returns>
250
        public System.Windows.Media.Imaging.BitmapSource CreateBitmapSourceFromBitmap(Bitmap bitmap)
251
        {
252
            System.Windows.Media.Imaging.BitmapSource result = null;
253
            
254
            if (bitmap == null)
255
                throw new ArgumentNullException("bitmap");
256

  
257
            try
258
            {
259
                using (var hbitmap = new SafeHBitmapHandle(bitmap.GetHbitmap(), true))
260
                {
261

  
262
                    result = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
263
                        hbitmap.DangerousGetHandle(),
264
                        IntPtr.Zero,
265
                        System.Windows.Int32Rect.Empty,
266
                        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
267

  
268
                   
269
                }
270
            }
271
            catch (Exception ex)
272
            {
273
                //throw ex;
274
            }
275
            finally
276
            {
277
                bitmap.Dispose();
278
                bitmap = null;
279
                //GC.Collect(2);
280
            }
281

  
282
            return result;
283
        }
284

  
285
        public async Task<List<System.Windows.Rect>> CompareReturnRectsAsync(string OriginalbitmapUri, string TargatBitmapUri, Size ResultRectSize)
286
        {
287
            List<System.Windows.Rect> result = new List<System.Windows.Rect>();
288

  
289
            Bitmap Originalbitmap = null;
290
            Bitmap TargatBitmap = null;
291

  
292
            try
293
            {
294

  
295
                Originalbitmap = LoadPicture(OriginalbitmapUri);
296
                TargatBitmap = LoadPicture(TargatBitmapUri);
297

  
298
                result = await CompareReturnRectsAsync(Originalbitmap, TargatBitmap, ResultRectSize);
299
            }
300
            catch (Exception)
301
            {
302
                throw;
303
            }
304
            finally
305
            {
306
                Originalbitmap.Dispose();
307
                TargatBitmap.Dispose();
308
            }
309

  
310
            return result;
311
        }
312

  
313
        /// <summary>
314
        /// 이미지를 비교 후 해당 영역을 Rect로 반환한다.
315
        /// </summary>
316
        /// <param name="Originalbitmap">원본 이미지</param>
317
        /// <param name="TargatBitmap">비교대상 이미지</param>
318
        /// <param name="ResultRectSize">반환되는 Rect의 사이즈</param>
319
        /// <returns></returns>
320
        public async Task<List<System.Windows.Rect>> CompareReturnRectsAsync(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap, Size ResultRectSize)
321
        {
322
            List<System.Windows.Rect> result = new List<System.Windows.Rect>();
323

  
324
            try
325
            {
326
                byte[,,] data = MathchesImageData(Originalbitmap, TargatBitmap);
327

  
328
                result = await GetMatchPixelsAsnc(data, ResultRectSize);
329

  
330
                data = null;
331
            }
332
            catch (Exception ex)
333
            {
334
                throw ex;
335
            }
336
            finally
337
            {
338
            }
339

  
340
            return result;
341
        }
342

  
343
       
344
        protected override void Dispose(bool disposing)
345
        {
346
            base.Dispose(disposing);
347
        }
348
    }
349
}
ImageComparer/Markus.ImageComparer/ImageComparerBase.cs
1
using Emgu.CV;
2
using Emgu.CV.Structure;
3
using System;
4
using System.Collections.Generic;
5
using System.Drawing;
6
using System.Drawing.Imaging;
7
using System.IO;
8
using System.Linq;
9
using System.Net;
10
using System.Text;
11
using System.Threading.Tasks;
12

  
13
namespace Markus.Image
14
{
15
    public class ImageComparerBase : IDisposable
16
    {
17
        Image<Bgr, Byte> OriginalImageData = null;
18
        Image<Bgr, Byte> TargatImageData = null;
19

  
20
        /// <summary>
21
        /// 이미지 비교에 사용되는 점수
22
        /// </summary>
23
        double gMatchScore = 0.9;
24

  
25
        /// <summary>
26
        /// 이미지의 크기와 포멧을 변경한다.
27
        /// </summary>
28
        /// <param name="bitmap"></param>
29
        /// <param name="newSize"></param>
30
        /// <param name="pixelFormat"></param>
31
        /// <returns></returns>
32
        protected System.Drawing.Bitmap ChangeBitmapFormatAndSize(System.Drawing.Bitmap bitmap, Size newSize, PixelFormat pixelFormat)
33
        {
34
            Bitmap result = bitmap;
35

  
36
            if (pixelFormat != bitmap.PixelFormat)
37
            {
38
                Point originPoint = new Point(0, 0);
39
                Rectangle rect = new Rectangle(originPoint, bitmap.Size);
40
                result = bitmap.Clone(rect, pixelFormat);
41
            }
42

  
43
            if (bitmap.Size != newSize)
44
            {
45
                result = new Bitmap(newSize.Width, newSize.Height);
46

  
47
                using (Graphics g = Graphics.FromImage(result))
48
                {
49
                    g.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height);
50
                    g.Dispose();
51
                }
52
            }
53

  
54
            return result;
55
        }
56

  
57
        /// <summary>
58
        /// Originalbitmap에서 TargatBitmap과 비교하여 틀린 부분의 데이터를 Emgu.CV.TDepth형식으로 반환한다.
59
        /// </summary>
60
        /// <param name="Originalbitmap">원본 이미지</param>
61
        /// <param name="TargatBitmap">비교대상 이미지</param>
62
        /// <returns>Emgu.CV.TDepth형식의 byte[,,]</returns>
63
        protected byte[,,] MathchesImageData(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap)
64
        {
65
            byte[,,] result = null;
66

  
67
            try
68
            {
69
                // 원본이미지의 크키와 Format24bppRgb로 타켓 이미지를 변경
70
                // 크기가 틀린 경우 비교시 바이트배열 오류 발생
71
                // 이미지 포멧은 24bit이하로 emgu CV가 작동
72
                Originalbitmap = ChangeBitmapFormatAndSize(Originalbitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
73
                TargatBitmap = ChangeBitmapFormatAndSize(TargatBitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
74

  
75
                OriginalImageData = new Image<Bgr, Byte>(Originalbitmap);
76
                TargatImageData = new Image<Bgr, Byte>(TargatBitmap);
77

  
78
                //Computes absolute different between this image and the other image
79
                // 원본이미지와 타겟이미지를 처리
80
                var tmp = OriginalImageData.AbsDiff(TargatImageData);
81

  
82
                // 틀린부분을 반환
83
                var matches = tmp.Not();
84

  
85
                result = matches.Data;
86

  
87
                matches.Dispose();
88
                tmp.Dispose();
89
            }
90
            catch (Exception ex)
91
            {
92
                throw ex;
93
            }
94
            
95
            return result;
96
        }
97

  
98
        /// <summary>
99
        /// MathchesImageData의 틀린 부분을 Rect로 반환
100
        /// </summary>
101
        /// <param name="data"></param>
102
        /// <param name="currentX"></param>
103
        /// <param name="currentY"></param>
104
        /// <param name="ImageWidth"></param>
105
        /// <param name="ImageHeight"></param>
106
        /// <param name="block"></param>
107
        /// <returns></returns>
108
        protected System.Windows.Rect? DataMatchScore(byte[,,] data, int currentX, int currentY, int ImageWidth, int ImageHeight, Size block)
109
        {
110
            System.Windows.Rect? result = null;
111

  
112
            int x = currentX;
113
            int y = currentY;
114
            int width = ImageWidth;
115
            int height = ImageHeight;
116

  
117
            for (int i = 0; i < block.Width; i++)
118
            {
119
                int wi = x + i;
120
                if (wi >= width) break;
121

  
122
                for (int j = 0; j < block.Height; j++)
123
                {
124
                    int hj = y + j;
125
                    if (hj >= height) break;
126

  
127
                    double matchScore = data[wi, hj, 0];
128

  
129
                    if (matchScore < gMatchScore)
130
                    {
131
                        result = new System.Windows.Rect(y, x, block.Width, block.Height);
132
                        return result;
133
                    }
134
                }
135
            }
136

  
137
            return result;
138
        }
139

  
140
        /// <summary>
141
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
142
        /// </summary>
143
        /// <param name="data"></param>
144
        /// <param name="block"></param>
145
        /// <returns></returns>
146
        protected List<System.Windows.Rect> GetMatchPixels(byte[,,] data, Size block)
147
        {
148
            int width = data.GetLength(0);
149
            int height = data.GetLength(1);
150

  
151
            List<System.Windows.Rect> results = new List<System.Windows.Rect>();
152

  
153
            var heightRange = from h in Enumerable.Range(1, height)
154
                              where h % block.Height == 0
155
                              select h;
156

  
157
            var widthRange = from w in Enumerable.Range(1, width)
158
                             where w % block.Width == 0
159
                             select w;
160

  
161
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
162
            stopwatch.Start();
163

  
164
            Parallel.ForEach(heightRange, (y) =>
165
            {
166
                Parallel.ForEach(widthRange, (x) =>
167
                {
168
                    var rect = DataMatchScore(data, x, y, width, height, block);
169

  
170
                    if (rect != null)
171
                    {
172
                        results.Add(rect.Value);
173
                    }
174
                });
175
            });
176

  
177
            System.Diagnostics.Debug.WriteLine("1 - " + new TimeSpan(stopwatch.ElapsedTicks));
178
            return results;
179
        }
180

  
181
        /// <summary>
182
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
183
        /// </summary>
184
        /// <param name="data"></param>
185
        /// <param name="block"></param>
186
        /// <returns></returns>
187
        protected async Task<List<System.Windows.Rect>> GetMatchPixelsAsnc(byte[,,] data, Size block)
188
        {
189
            return await Task.Factory.StartNew<List<System.Windows.Rect>>(() =>
190
            {
191
                return GetMatchPixels(data, block);
192
            });
193
        }
194

  
195
        protected Bitmap LoadPicture(string url)
196
        {
197
            HttpWebRequest wreq;
198
            HttpWebResponse wresp;
199
            Stream mystream;
200
            Bitmap bmp;
201

  
202
            bmp = null;
203
            mystream = null;
204
            wresp = null;
205
            try
206
            {
207
                wreq = (HttpWebRequest)WebRequest.Create(url);
208
                wreq.AllowWriteStreamBuffering = true;
209

  
210
                wresp = (HttpWebResponse)wreq.GetResponse();
... 이 차이점은 표시할 수 있는 최대 줄수를 초과해서 이 차이점은 잘렸습니다.

내보내기 Unified diff

클립보드 이미지 추가 (최대 크기: 500 MB)