├── .gitignore ├── SeamCarving ├── Images │ └── Desert_VerySimpleLandscape.jpg ├── SeamCarving │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Program.cs │ ├── Form1.cs │ ├── Form1.Designer.cs │ ├── SeamCarving.csproj │ ├── Form1.resx │ └── BitmapHelper.cs └── SeamCarving.sln └── StringMatching ├── StringMatching.sln ├── TestProject ├── Properties │ └── AssemblyInfo.cs ├── PatternMatchingTest.cs ├── StringDiffTests.cs └── TestProject.csproj └── StringMatching ├── Properties └── AssemblyInfo.cs ├── StringMatching.csproj ├── StringMatcher.cs └── StringDiff.cs /.gitignore: -------------------------------------------------------------------------------- 1 | _ReSharper* 2 | *.resharper* 3 | bin 4 | obj 5 | *.suo 6 | *.zip 7 | *.cache 8 | *.user -------------------------------------------------------------------------------- /SeamCarving/Images/Desert_VerySimpleLandscape.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcbozonier/Dynamic-Programming-Sample/master/SeamCarving/Images/Desert_VerySimpleLandscape.jpg -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace SeamCarving 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | Application.Run(new Form1()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeamCarving", "SeamCarving\SeamCarving.csproj", "{2E88758B-7B19-4151-8EFC-F9DDA5972FF1}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {2E88758B-7B19-4151-8EFC-F9DDA5972FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {2E88758B-7B19-4151-8EFC-F9DDA5972FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {2E88758B-7B19-4151-8EFC-F9DDA5972FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {2E88758B-7B19-4151-8EFC-F9DDA5972FF1}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Form1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace SeamCarving 11 | { 12 | public partial class Form1 : Form 13 | { 14 | public Form1() 15 | { 16 | InitializeComponent(); 17 | var bitmap = new Bitmap(@"C:\Code\DynamicProgramming\SeamCarving\Images\Desert_VerySimpleLandscape.jpg"); 18 | var newImage = ImagerBitmap.LaplaceGreyscale(bitmap); 19 | var bounds = new Rectangle(Point.Empty, newImage.Size); 20 | 21 | var imageEneryMatrix = new List>(bounds.Width); 22 | 23 | foreach(var xIndex in Enumerable.Range(0, bounds.Width)) 24 | { 25 | var yIndexVector = new List(); 26 | imageEneryMatrix.Add(yIndexVector); 27 | foreach(var yIndex in Enumerable.Range(0, bounds.Height)) 28 | { 29 | yIndexVector.Add(newImage.GetPixel(xIndex, yIndex).GetBrightness()); 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.3053 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SeamCarving.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.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 | } 31 | -------------------------------------------------------------------------------- /StringMatching/StringMatching.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StringMatching", "StringMatching\StringMatching.csproj", "{7B62224E-B789-47EC-ACCA-DA37FA43A591}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{385C369E-1F02-4DC2-986C-ADBBA4C5AC47}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {7B62224E-B789-47EC-ACCA-DA37FA43A591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {7B62224E-B789-47EC-ACCA-DA37FA43A591}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {7B62224E-B789-47EC-ACCA-DA37FA43A591}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {7B62224E-B789-47EC-ACCA-DA37FA43A591}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {385C369E-1F02-4DC2-986C-ADBBA4C5AC47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {385C369E-1F02-4DC2-986C-ADBBA4C5AC47}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {385C369E-1F02-4DC2-986C-ADBBA4C5AC47}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {385C369E-1F02-4DC2-986C-ADBBA4C5AC47}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SeamCarving")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SeamCarving")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("de12b6bd-1a6f-4a73-b48a-01ab92560128")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /StringMatching/TestProject/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestProject")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestProject")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("09b066ee-7539-44a2-824c-75bf745cd043")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /StringMatching/StringMatching/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("StringMatching")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("StringMatching")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5cab46f4-d926-4980-862b-7e989d3a408c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /StringMatching/TestProject/PatternMatchingTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NUnit.Framework; 6 | using StringMatching; 7 | 8 | namespace TestProject 9 | { 10 | [TestFixture] 11 | public class Simple_strings 12 | { 13 | [Test] 14 | public void Simplest_strings_both_match() 15 | { 16 | Assert.IsTrue(StringMatcher.IsMatch("a", "a")); 17 | } 18 | 19 | [Test] 20 | public void Simplest_strings_neither_match() 21 | { 22 | Assert.IsFalse(StringMatcher.IsMatch("a", "z")); 23 | } 24 | 25 | [Test] 26 | public void Simplest_strings_simplest_pattern_matches() 27 | { 28 | Assert.IsTrue(StringMatcher.IsMatch(".", "z")); 29 | } 30 | 31 | [Test] 32 | public void Simplest_strings_simplest_pattern_asterisk_matches() 33 | { 34 | Assert.IsTrue(StringMatcher.IsMatch("*", "z")); 35 | } 36 | } 37 | 38 | [TestFixture] 39 | public class Off_by_one_matchers 40 | { 41 | [Test] 42 | public void String_off_by_one_case_1_matches() 43 | { 44 | Assert.IsTrue(StringMatcher.IsMatch("a.c.e", "abcde")); 45 | } 46 | 47 | [Test] 48 | public void String_off_by_one_case_2_no_match() 49 | { 50 | Assert.IsFalse(StringMatcher.IsMatch("a.c.", "abcde")); 51 | } 52 | 53 | } 54 | 55 | [TestFixture] 56 | public class Off_by_many_matchers 57 | { 58 | [Test] 59 | public void String_off_by_many_case_1_matches() 60 | { 61 | Assert.IsTrue(StringMatcher.IsMatch(".a*.j*", "cadeajmn")); 62 | } 63 | 64 | [Test] 65 | public void String_off_by_many_case_2_no_match() 66 | { 67 | Assert.IsFalse(StringMatcher.IsMatch("a.d*", "abcde")); 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace SeamCarving 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.myPicture = new System.Windows.Forms.PictureBox(); 32 | ((System.ComponentModel.ISupportInitialize)(this.myPicture)).BeginInit(); 33 | this.SuspendLayout(); 34 | // 35 | // myPicture 36 | // 37 | this.myPicture.Location = new System.Drawing.Point(12, 12); 38 | this.myPicture.Name = "myPicture"; 39 | this.myPicture.Size = new System.Drawing.Size(456, 426); 40 | this.myPicture.TabIndex = 0; 41 | this.myPicture.TabStop = false; 42 | // 43 | // Form1 44 | // 45 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 46 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 47 | this.ClientSize = new System.Drawing.Size(480, 450); 48 | this.Controls.Add(this.myPicture); 49 | this.Name = "Form1"; 50 | this.Text = "Form1"; 51 | ((System.ComponentModel.ISupportInitialize)(this.myPicture)).EndInit(); 52 | this.ResumeLayout(false); 53 | 54 | } 55 | 56 | #endregion 57 | 58 | private System.Windows.Forms.PictureBox myPicture; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /StringMatching/TestProject/StringDiffTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NUnit.Framework; 6 | using StringMatching; 7 | 8 | namespace TestProject 9 | { 10 | [TestFixture] 11 | public class StringDiffTests 12 | { 13 | [Test] 14 | public void SimplestExecutionPlan() 15 | { 16 | var stringA = "a"; 17 | var stringB = "a"; 18 | 19 | var diff = new StringDiff(); 20 | var executionPlan = diff.Between(stringA, stringB); 21 | 22 | Assert.AreEqual(0, executionPlan.Steps.Count); 23 | } 24 | 25 | [Test] 26 | public void SimplestDiff_Test() 27 | { 28 | var stringA = "a"; 29 | var stringB = "b"; 30 | 31 | var diff = new StringDiff(); 32 | var executionPlan = diff.Between(stringA, stringB); 33 | 34 | Assert.AreEqual(1, executionPlan.Steps.Count); 35 | } 36 | 37 | [Test] 38 | public void MultiItem_Diff_Test() 39 | { 40 | var stringA = "abcba"; 41 | var stringB = "bbcbb"; 42 | 43 | var diff = new StringDiff(); 44 | var executionPlan = diff.Between(stringA, stringB); 45 | 46 | Assert.AreEqual(2, executionPlan.Steps.Count); 47 | } 48 | 49 | [Test] 50 | public void MultiItem_Diff_Assymetrical_Test() 51 | { 52 | var stringA = "desk"; 53 | var stringB = "pesticide"; 54 | 55 | var diff = new StringDiff(); 56 | var executionPlan = diff.Between(stringA, stringB); 57 | 58 | Assert.AreEqual(7, executionPlan.Steps.Count); 59 | } 60 | 61 | [Test] 62 | public void MultiItem_Diff_Horizontal_Assymetrical_Test() 63 | { 64 | var stringA = "bcdeffghi"; 65 | var stringB = "abcdefghij"; 66 | 67 | var diff = new StringDiff(); 68 | var executionPlan = diff.Between(stringA, stringB); 69 | 70 | Assert.AreEqual(3, executionPlan.Steps.Count); 71 | } 72 | 73 | [Test] 74 | public void MultiItem_Diff_Assymetrical_Test_With_Print() 75 | { 76 | var stringA = "desk"; 77 | var stringB = "pesticide"; 78 | 79 | var diff = new StringDiff(); 80 | var executionPlan = diff.Between(stringA, stringB); 81 | 82 | var printedPlan = executionPlan.PrintAllSteps(); 83 | Assert.IsNotNullOrEmpty(printedPlan); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /StringMatching/StringMatching/StringMatching.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {7B62224E-B789-47EC-ACCA-DA37FA43A591} 9 | Library 10 | Properties 11 | StringMatching 12 | StringMatching 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 3.5 37 | 38 | 39 | 3.5 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.3053 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SeamCarving.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.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 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 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("SeamCarving.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 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 | } 72 | -------------------------------------------------------------------------------- /StringMatching/TestProject/TestProject.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {385C369E-1F02-4DC2-986C-ADBBA4C5AC47} 9 | Library 10 | Properties 11 | TestProject 12 | TestProject 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 3.5 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {7B62224E-B789-47EC-ACCA-DA37FA43A591} 56 | StringMatching 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /StringMatching/StringMatching/StringMatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace StringMatching 7 | { 8 | public class StringMatcher 9 | { 10 | private const string _OffByOneLiteral = "."; 11 | private const string _OffByManyLiteral = "*"; 12 | 13 | public static bool IsMatch(string pattern, string str) 14 | { 15 | var patternMatrix = _GetPatternMatrix(pattern, str); 16 | 17 | return _HasCompletePath(patternMatrix, pattern.Length-1, str.Length-1, pattern); 18 | } 19 | 20 | private static bool _HasCompletePath(IList> matrix, int patternIndex, int stringIndex, string pattern) 21 | { 22 | var result = false; 23 | 24 | if(patternIndex < 0 || stringIndex < 0) 25 | return false; 26 | 27 | if (patternIndex == 0 && stringIndex == 0 && matrix[patternIndex][stringIndex]) 28 | { 29 | result = true; 30 | } 31 | else if(matrix[patternIndex][stringIndex]) 32 | { 33 | var tempResult = _HasCompletePath(matrix, patternIndex - 1, stringIndex - 1, pattern); 34 | if(!tempResult && _HasCompletePath(matrix, patternIndex, stringIndex-1, pattern) && pattern[patternIndex] == '*') 35 | { 36 | tempResult = true; 37 | } 38 | result |= tempResult; 39 | } 40 | 41 | return result; 42 | } 43 | 44 | private static List> _GetPatternMatrix(string pattern, string str) 45 | { 46 | var patternMatrix = new List>(pattern.Length); 47 | for (var i = 0; i < pattern.Length; i++) 48 | patternMatrix.Add(new List(str.Length)); 49 | 50 | //First fill out table 51 | foreach(var patternIndex in Enumerable.Range(0, pattern.Length)) 52 | { 53 | var patternCharacter = pattern[patternIndex]; 54 | 55 | var isLiteralMatch = patternCharacter != '*' && patternCharacter != '.'; 56 | foreach(var stringIndex in Enumerable.Range(0, str.Length)) 57 | { 58 | var stringCharacter = str[stringIndex]; 59 | 60 | if(isLiteralMatch) 61 | { 62 | patternMatrix[patternIndex].Add(_IsMatch(patternCharacter, stringCharacter)); 63 | } 64 | else 65 | { 66 | patternMatrix[patternIndex].Add(true); 67 | } 68 | 69 | } 70 | } 71 | return patternMatrix; 72 | } 73 | 74 | private static bool _IsMatch(char pattern, char str) 75 | { 76 | if (pattern == '*') 77 | return true; 78 | if(pattern == '.') 79 | return true; 80 | if(pattern == str) 81 | return true; 82 | 83 | return false; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/SeamCarving.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {2E88758B-7B19-4151-8EFC-F9DDA5972FF1} 9 | WinExe 10 | Properties 11 | SeamCarving 12 | SeamCarving 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 3.5 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Form 55 | 56 | 57 | Form1.cs 58 | 59 | 60 | 61 | 62 | Form1.cs 63 | 64 | 65 | ResXFileCodeGenerator 66 | Resources.Designer.cs 67 | Designer 68 | 69 | 70 | True 71 | Resources.resx 72 | 73 | 74 | SettingsSingleFileGenerator 75 | Settings.Designer.cs 76 | 77 | 78 | True 79 | Settings.settings 80 | True 81 | 82 | 83 | 84 | 91 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/Form1.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /StringMatching/StringMatching/StringDiff.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace StringMatching 7 | { 8 | public class StringDiff 9 | { 10 | public StringDeltaExecutionPlan Between(string a, string b) 11 | { 12 | var editDistanceMatrix = _GetDiffMatrix(a, b); 13 | var executionPlan = _CreateExecutionPlan(a, b, editDistanceMatrix); 14 | return executionPlan; 15 | } 16 | 17 | private StringDeltaExecutionPlan _CreateExecutionPlan(string oldString, string newString, List> editDistanceMatrix) 18 | { 19 | var executionPlanBuilder = new StringDeltaExecutionPlan(oldString, newString); 20 | 21 | // String from bottom right corner of the matrix and work our 22 | // way up to the upper left corner. 23 | 24 | var oldStringIndex = oldString.Length - 1; 25 | var newStringIndex = newString.Length - 1; 26 | 27 | var transformedString = oldString.Clone().ToString(); 28 | 29 | while (oldStringIndex >= 0 || newStringIndex >= 0) 30 | { 31 | // Deal with current cell 32 | 33 | // Decide how to move. 34 | var leftPathIsValid = oldStringIndex > 0; 35 | var topPathIsValid = newStringIndex > 0; 36 | 37 | if(leftPathIsValid && topPathIsValid) 38 | { 39 | var leftPathValue = editDistanceMatrix[oldStringIndex - 1][newStringIndex]; 40 | var topLeftPathValue = editDistanceMatrix[oldStringIndex - 1][newStringIndex - 1]; 41 | var topPathValue = editDistanceMatrix[oldStringIndex][newStringIndex - 1]; 42 | 43 | if(topLeftPathValue <= leftPathValue && topLeftPathValue <= topPathValue) 44 | { 45 | if(oldString[oldStringIndex] != newString[newStringIndex]) 46 | { 47 | executionPlanBuilder.Swap(newStringIndex, oldStringIndex); 48 | } 49 | newStringIndex--; 50 | oldStringIndex--; 51 | 52 | continue; 53 | } 54 | 55 | if(leftPathValue <= topLeftPathValue && leftPathValue <= topPathValue) 56 | { 57 | executionPlanBuilder.Delete(oldStringIndex); 58 | oldStringIndex--; 59 | 60 | continue; 61 | } 62 | 63 | if(topPathValue <= topLeftPathValue && topPathValue <= leftPathValue) 64 | { 65 | executionPlanBuilder.Insert(newStringIndex, oldStringIndex); 66 | newStringIndex--; 67 | 68 | continue; 69 | } 70 | } 71 | 72 | if (leftPathIsValid && 73 | editDistanceMatrix[oldStringIndex-1][newStringIndex] <= editDistanceMatrix[oldStringIndex][newStringIndex]) 74 | { 75 | executionPlanBuilder.Delete(oldStringIndex); 76 | oldStringIndex--; 77 | continue; 78 | } 79 | 80 | if(topPathIsValid && 81 | editDistanceMatrix[oldStringIndex][newStringIndex-1] <= editDistanceMatrix[oldStringIndex][newStringIndex]) 82 | { 83 | executionPlanBuilder.Insert(newStringIndex, oldStringIndex); 84 | newStringIndex--; 85 | continue; 86 | } 87 | 88 | if (!leftPathIsValid && !topPathIsValid) 89 | { 90 | if(!executionPlanBuilder.FirstCharacterEquals(oldString[oldStringIndex])) 91 | { 92 | executionPlanBuilder.Swap(newStringIndex, oldStringIndex); 93 | } 94 | oldStringIndex--; 95 | newStringIndex--; 96 | } 97 | } 98 | 99 | return executionPlanBuilder; 100 | } 101 | 102 | private static List> _GetDiffMatrix(string oldString, string newString) 103 | { 104 | var editDistanceMatrix = new List>(oldString.Length); 105 | for (var i = 0; i < oldString.Length; i++) 106 | editDistanceMatrix.Add(new List(newString.Length)); 107 | 108 | //First fill out table 109 | foreach (var oldCharacterIndex in Enumerable.Range(0, oldString.Length)) 110 | { 111 | foreach (var newCharacterIndex in Enumerable.Range(0, newString.Length)) 112 | { 113 | var editDistanceAtCell = _CalculateMinimumCellEditDistance(editDistanceMatrix, oldString, oldCharacterIndex, newString, newCharacterIndex); 114 | 115 | editDistanceMatrix[oldCharacterIndex].Add(editDistanceAtCell); 116 | } 117 | } 118 | 119 | return editDistanceMatrix; 120 | } 121 | 122 | private static int _CalculateMinimumCellEditDistance(List> matrix, string oldString, int oldCharacterIndex, string newString, int newCharacterIndex) 123 | { 124 | var oldChar = oldString[oldCharacterIndex]; 125 | var newChar = newString[newCharacterIndex]; 126 | 127 | var localEditDistance = oldChar == newChar ? 0 : 1; 128 | 129 | var leftArrayValue = _GetCellValue(matrix, oldCharacterIndex - 1, newCharacterIndex) + 1; 130 | var topLeftArrayValue = _GetCellValue(matrix, oldCharacterIndex - 1, newCharacterIndex - 1) + localEditDistance; 131 | var topArrayValue = _GetCellValue(matrix, oldCharacterIndex, newCharacterIndex - 1) + 1; 132 | 133 | var minEditDistance = Math.Min(Math.Min(leftArrayValue, topLeftArrayValue), topArrayValue); 134 | 135 | return minEditDistance; 136 | } 137 | 138 | private static int _GetCellValue(List> matrix, int oldCharacterIndex, int newCharacterIndex) 139 | { 140 | if (oldCharacterIndex < 0 && newCharacterIndex < 0) 141 | return 0; 142 | if (oldCharacterIndex < 0) 143 | return newCharacterIndex + 1; 144 | if (newCharacterIndex < 0) 145 | return oldCharacterIndex + 1; 146 | return matrix[oldCharacterIndex][newCharacterIndex]; 147 | 148 | } 149 | } 150 | 151 | public class StringDeltaExecutionPlan 152 | { 153 | private string _OldString; 154 | private string _NewString; 155 | public readonly Stack Steps; 156 | 157 | public StringDeltaExecutionPlan(string oldString, string newString) 158 | { 159 | _OldString = oldString; 160 | _NewString = newString; 161 | Steps = new Stack(); 162 | } 163 | 164 | public void Swap(int newStringIndex, int oldStringIndex) 165 | { 166 | Steps.Push(new SwapStep(newStringIndex, oldStringIndex)); 167 | } 168 | 169 | public void Delete(int oldStringIndex) 170 | { 171 | Steps.Push(new DeleteStep(oldStringIndex)); 172 | } 173 | 174 | public void Insert(int newStringIndex, int oldStringIndex) 175 | { 176 | Steps.Push(new InsertStep(oldStringIndex, newStringIndex)); 177 | } 178 | 179 | public string PrintStep(int index) 180 | { 181 | var steps = Steps.ToArray(); 182 | return steps[index].Print(_OldString, _NewString); 183 | } 184 | 185 | public string PrintAllSteps() 186 | { 187 | var result = ""; 188 | 189 | var steps = Steps.ToArray(); 190 | foreach(var step in steps) 191 | { 192 | result += step.Print(_OldString, _NewString) + "\n"; 193 | } 194 | 195 | return result; 196 | } 197 | 198 | public bool FirstCharacterEquals(char oldCharacter) 199 | { 200 | if(Steps.Count > 0) 201 | { 202 | var firstStep = Steps.First(); 203 | 204 | if(firstStep is InsertStep) 205 | { 206 | var insertStep = (InsertStep) firstStep; 207 | if (insertStep._OldStringIndex == 0) 208 | return _NewString[insertStep._NewStringIndex].Equals(oldCharacter); 209 | } 210 | } 211 | 212 | return _NewString[0].Equals(oldCharacter); 213 | } 214 | } 215 | 216 | public class SwapStep : Step 217 | { 218 | public int _NewStringIndex; 219 | public int _OldStringIndex; 220 | 221 | public SwapStep(int newStringIndex, int oldStringIndex) 222 | { 223 | _NewStringIndex = newStringIndex; 224 | _OldStringIndex = oldStringIndex; 225 | } 226 | 227 | public override string Print(string oldString, string newString) 228 | { 229 | return String.Format("Old character \"{0}\" swapped with new character \"{1}\"", 230 | oldString[_OldStringIndex], 231 | newString[_NewStringIndex]); 232 | } 233 | } 234 | 235 | public class DeleteStep : Step 236 | { 237 | private int _OldStringIndex; 238 | 239 | public DeleteStep(int oldStringIndex) 240 | { 241 | _OldStringIndex = oldStringIndex; 242 | } 243 | 244 | public override string Print(string oldString, string newString) 245 | { 246 | return String.Format("Deleted old character \"{0}\"", oldString[_OldStringIndex]); 247 | } 248 | } 249 | 250 | public class InsertStep : Step 251 | { 252 | public int _NewStringIndex; 253 | public int _OldStringIndex; 254 | 255 | public InsertStep(int oldStringIndex, int newStringIndex) 256 | { 257 | _NewStringIndex = newStringIndex; 258 | _OldStringIndex = oldStringIndex; 259 | } 260 | 261 | public override string Print(string oldString, string newString) 262 | { 263 | return String.Format("Inserted new character \"{0}\" at index {1}", newString[_NewStringIndex], _OldStringIndex); 264 | } 265 | } 266 | 267 | public abstract class Step 268 | { 269 | public abstract string Print(string oldString, string newString); 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /SeamCarving/SeamCarving/BitmapHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System; 6 | using System.Drawing; 7 | using System.Drawing.Imaging; 8 | using System.Drawing.Drawing2D; 9 | using System.IO; 10 | 11 | namespace SeamCarving 12 | { 13 | /// 14 | /// This class provides methods to Resize and Apply Filters to bitmap images. 15 | /// 16 | /// ideas from 17 | /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp11152001.asp 18 | /// http://www.msnewsgroups.net/group/microsoft.public.dotnet.languages.csharp/topic9351.aspx 19 | /// 20 | public unsafe class ImagerBitmap 21 | { 22 | /// 23 | /// This struct is used to hold the RGB values when we find a pixel using the pointer 24 | /// 25 | private struct PixelData 26 | { 27 | public byte Blue; 28 | public byte Green; 29 | public byte Red; 30 | } 31 | /// 32 | /// This object contains pointer addressable information about the bitmap 33 | /// 34 | private BitmapData _bitmapData = null; 35 | /// 36 | /// The pointer to the upper left corner of the bitmap 37 | /// 38 | private byte* pBase = null; 39 | private Bitmap _bitmap = null; 40 | /// 41 | /// Get the Image we are working with 42 | /// 43 | public Bitmap Bitmap 44 | { 45 | get 46 | { 47 | return _bitmap; 48 | } 49 | } 50 | /// 51 | /// Constructor 52 | /// 53 | /// Bitmap to use as the basis of the Imager 54 | private ImagerBitmap(Bitmap b) 55 | { 56 | if (b.PixelFormat != PixelFormat.Format24bppRgb) 57 | { 58 | //Convert the image into Format24bppRgb since our unmanaged code 59 | //can walk that image type 60 | Bitmap b2 = new Bitmap(b.Size.Width, b.Size.Height, PixelFormat.Format24bppRgb); 61 | Graphics g = Graphics.FromImage(b2); 62 | g.DrawImage(b, new Point(0, 0)); 63 | _bitmap = b2; 64 | g.Dispose(); 65 | } 66 | else 67 | { 68 | _bitmap = b; 69 | } 70 | LockBitmap(); 71 | } 72 | /// 73 | /// Load a pixel with color 74 | /// 75 | /// Column 76 | /// Row 77 | /// Color 78 | private void SetPixel(int x, int y, Color c) 79 | { 80 | PixelData* p = PixelAt(x, y); 81 | p->Red = c.R; 82 | p->Green = c.G; 83 | p->Blue = c.B; 84 | } 85 | /// 86 | /// Get a pixel 87 | /// 88 | /// Column 89 | /// Row 90 | /// Color 91 | private Color GetPixel(int x, int y) 92 | { 93 | PixelData* p = PixelAt(x, y); 94 | return Color.FromArgb((int)p->Red, (int)p->Green, (int)p->Blue); 95 | } 96 | /// 97 | /// Get the Grey value for a give pixel 98 | /// 99 | /// Column 100 | /// Row 101 | /// Grey value for the pixel 102 | private int GetGreyPixel(int column, int row) 103 | { 104 | return (int)((GetPixel(column, row).R * 0.3) + (GetPixel(column, row).G * 0.59) 105 | + (GetPixel(column, row).B * 0.11)); 106 | } 107 | /// 108 | /// Use the 2 most signifigant bits from each of the values in the RGB to get an in value 109 | /// for the histogram 110 | /// 111 | /// Column 112 | /// Row 113 | /// Histogram Value 114 | public int GetRGBHistogramValue(int column, int row) 115 | { 116 | Color c = GetPixel(column, row); 117 | int val = 0; 118 | int tmp = 0; 119 | tmp = c.R; 120 | if (tmp - 128 > 0) 121 | { 122 | tmp -= 128; 123 | val += 32; 124 | } 125 | if (tmp - 64 > 0) 126 | { 127 | val += 16; 128 | } 129 | tmp = c.G; 130 | if (tmp - 128 > 0) 131 | { 132 | tmp -= 128; 133 | val += 8; 134 | } 135 | if (tmp - 64 > 0) 136 | { 137 | val += 4; 138 | } 139 | tmp = c.B; 140 | if (tmp - 128 > 0) 141 | { 142 | tmp -= 128; 143 | val += 2; 144 | } 145 | if (tmp - 64 > 0) 146 | { 147 | val += 1; 148 | } 149 | return val; 150 | } 151 | /// 152 | /// Lock the bitmap so we can use the pointers to access it 153 | /// 154 | private void LockBitmap() 155 | { 156 | _bitmapData = _bitmap.LockBits(new Rectangle(0, 0, _bitmap.Width, _bitmap.Height), 157 | ImageLockMode.ReadWrite, _bitmap.PixelFormat); 158 | pBase = (Byte*)_bitmapData.Scan0.ToPointer(); 159 | } 160 | /// 161 | /// Get a pointer to a pixel 162 | /// 163 | /// Column 164 | /// Row 165 | /// 166 | private unsafe PixelData* PixelAt(int x, int y) 167 | { 168 | return (PixelData*)(pBase + y * _bitmapData.Stride + x * sizeof(PixelData)); 169 | } 170 | /// 171 | /// Unlock the bitmap to end the pointer access session 172 | /// 173 | private void UnlockBitmap() 174 | { 175 | _bitmap.UnlockBits(_bitmapData); 176 | _bitmapData = null; 177 | pBase = null; 178 | } 179 | /// 180 | /// Get a 3x3 matrix of the pixles around the center 181 | /// 182 | /// Center Row 183 | /// Center Column 184 | /// 3x3 matrix of the pixles around the center 185 | private Color[,] Get3x3(int row, int column) 186 | { 187 | Color[,] c = new Color[3, 3]; 188 | c[0, 0] = this.GetPixel(column - 1, row - 1); 189 | c[0, 1] = this.GetPixel(column - 1, row); 190 | c[0, 2] = this.GetPixel(column - 1, row + 1); 191 | c[1, 0] = this.GetPixel(column, row - 1); 192 | c[1, 1] = this.GetPixel(column, row); 193 | c[1, 2] = this.GetPixel(column, row + 1); 194 | c[2, 0] = this.GetPixel(column + 1, row - 1); 195 | c[2, 1] = this.GetPixel(column + 1, row); 196 | c[2, 2] = this.GetPixel(column + 1, row + 1); 197 | return c; 198 | } 199 | private int[,] GetGrey3x3(int row, int column) 200 | { 201 | int[,] c = new int[3, 3]; 202 | c[0, 0] = this.GetGreyPixel(column - 1, row - 1); 203 | c[0, 1] = this.GetGreyPixel(column - 1, row); 204 | c[0, 2] = this.GetGreyPixel(column - 1, row + 1); 205 | c[1, 0] = this.GetGreyPixel(column, row - 1); 206 | c[1, 1] = this.GetGreyPixel(column, row); 207 | c[1, 2] = this.GetGreyPixel(column, row + 1); 208 | c[2, 0] = this.GetGreyPixel(column + 1, row - 1); 209 | c[2, 1] = this.GetGreyPixel(column + 1, row); 210 | c[2, 2] = this.GetGreyPixel(column + 1, row + 1); 211 | return c; 212 | } 213 | /// 214 | /// Get at 5x5 matrix of the pixels around the center 215 | /// 216 | /// Center Row 217 | /// Center Column 218 | /// 5x5 matrix of pixles around center 219 | private Color[,] Get5x5(int row, int column) 220 | { 221 | Color[,] c = new Color[5, 5]; 222 | c[0, 0] = this.GetPixel(column - 2, row - 2); 223 | c[0, 1] = this.GetPixel(column - 2, row - 1); 224 | c[0, 2] = this.GetPixel(column - 2, row); 225 | c[0, 3] = this.GetPixel(column - 2, row + 1); 226 | c[0, 4] = this.GetPixel(column - 2, row + 2); 227 | c[1, 0] = this.GetPixel(column - 1, row - 2); 228 | c[1, 1] = this.GetPixel(column - 1, row - 1); 229 | c[1, 2] = this.GetPixel(column - 1, row); 230 | c[1, 3] = this.GetPixel(column - 1, row + 1); 231 | c[1, 4] = this.GetPixel(column - 1, row + 2); 232 | c[2, 0] = this.GetPixel(column, row - 2); 233 | c[2, 1] = this.GetPixel(column, row - 1); 234 | c[2, 2] = this.GetPixel(column, row); 235 | c[2, 3] = this.GetPixel(column, row + 1); 236 | c[2, 4] = this.GetPixel(column, row + 2); 237 | c[3, 0] = this.GetPixel(column + 1, row - 2); 238 | c[3, 1] = this.GetPixel(column + 1, row - 1); 239 | c[3, 2] = this.GetPixel(column + 1, row); 240 | c[3, 3] = this.GetPixel(column + 1, row + 1); 241 | c[3, 4] = this.GetPixel(column + 1, row + 2); 242 | c[4, 0] = this.GetPixel(column + 2, row - 2); 243 | c[4, 1] = this.GetPixel(column + 2, row - 1); 244 | c[4, 2] = this.GetPixel(column + 2, row); 245 | c[4, 3] = this.GetPixel(column + 2, row + 1); 246 | c[4, 4] = this.GetPixel(column + 2, row + 2); 247 | return c; 248 | } 249 | /// 250 | /// Perform laplace edge detection on the image 251 | /// 252 | /// Source Image 253 | /// Edges 254 | public static Bitmap Laplace(Bitmap b) 255 | { 256 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 257 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 258 | for (int column = 1; column < i.Bitmap.Width - 1; column++) 259 | { 260 | for (int row = 1; row < i.Bitmap.Height - 1; row++) 261 | { 262 | Color[,] c = i.Get3x3(row, column); 263 | int red = (((c[0, 0].R + c[0, 1].R + c[0, 2].R + c[1, 0].R + c[1, 2].R + c[2, 0].R 264 | + c[2, 1].R + c[2, 2].R) * -1) + (c[1, 1].R * 8)) + 128; 265 | int green = (((c[0, 0].G + c[0, 1].G + c[0, 2].G + c[1, 0].G + c[1, 2].G 266 | + c[2, 0].G + c[2, 1].G + c[2, 2].G) * -1) + (c[1, 1].G * 8)) + 128; 267 | int blue = (((c[0, 0].B + c[0, 1].B + c[0, 2].B + c[1, 0].B + c[1, 2].B + c[2, 0].B 268 | + c[2, 1].B + c[2, 2].B) * -1) + (c[1, 1].B * 8)) + 128; 269 | if (red >= 128) red = 0; else red = 255; 270 | if (green >= 128) green = 0; else green = 255; 271 | if (blue >= 128) blue = 0; else blue = 255; 272 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 273 | } 274 | } 275 | i.UnlockBitmap(); 276 | i2.UnlockBitmap(); 277 | return i2.Bitmap.Clone() as Bitmap; 278 | } 279 | public static Bitmap LaplaceGreyscale(Bitmap b) 280 | { 281 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 282 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 283 | for (int column = 1; column < i.Bitmap.Width - 1; column++) 284 | { 285 | for (int row = 1; row < i.Bitmap.Height - 1; row++) 286 | { 287 | int[,] c = i.GetGrey3x3(row, column); 288 | int val = (((c[0, 0] + c[0, 1] + c[0, 2] + c[1, 0] + c[1, 2] + c[2, 0] + c[2, 1] 289 | + c[2, 2]) * -1) + (c[1, 1] * 8)) + 128; 290 | if (val >= 128) val = 0; else val = 255; 291 | i2.SetPixel(column, row, Color.FromArgb(val, val, val)); 292 | } 293 | } 294 | i.UnlockBitmap(); 295 | i2.UnlockBitmap(); 296 | return i2.Bitmap.Clone() as Bitmap; 297 | } 298 | 299 | /// 300 | /// Subtract b2 from b1 and normalize the image 301 | /// 302 | /// Image 303 | /// Image 304 | /// Normalized Image 305 | public static Bitmap Subtract(Bitmap b1, Bitmap b2) 306 | { 307 | if (b1.Width != b2.Width || b1.Height != b2.Height) 308 | throw new Exception("Images not the same size cannot subtract"); 309 | ImagerBitmap i = new ImagerBitmap(b1.Clone() as Bitmap); 310 | ImagerBitmap i2 = new ImagerBitmap(b2.Clone() as Bitmap); 311 | int[,] red = new int[i.Bitmap.Width, i.Bitmap.Height]; 312 | int[,] blue = new int[i.Bitmap.Width, i.Bitmap.Height]; 313 | int[,] green = new int[i.Bitmap.Width, i.Bitmap.Height]; 314 | int redMax = 0; 315 | int redMin = 0; 316 | int redRange = 0; 317 | int blueMax = 0; 318 | int blueMin = 0; 319 | int blueRange = 0; 320 | int greenMax = 0; 321 | int greenMin = 0; 322 | int greenRange = 0; 323 | //fill the arrays with the subtracted values 324 | //Keep track of the min and max values for later 325 | for (int column = 0; column < i.Bitmap.Width; column++) 326 | { 327 | for (int row = 0; row < i.Bitmap.Height; row++) 328 | { 329 | Color c1 = i.GetPixel(column, row); 330 | Color c2 = i2.GetPixel(column, row); 331 | red[column, row] = c2.R - c1.R; 332 | blue[column, row] = c2.B - c1.B; 333 | green[column, row] = c2.G - c1.G; 334 | if (red[column, row] > redMax) redMax = red[column, row]; 335 | if (red[column, row] < redMin) redMin = red[column, row]; 336 | if (blue[column, row] > blueMax) blueMax = blue[column, row]; 337 | if (blue[column, row] < blueMin) blueMin = blue[column, row]; 338 | if (green[column, row] > greenMax) greenMax = green[column, row]; 339 | if (green[column, row] < greenMin) greenMin = green[column, row]; 340 | } 341 | } 342 | //find the range of the min an max 343 | redRange = Math.Abs(redMax - redMin); 344 | blueRange = Math.Abs(blueMax - blueMin); 345 | greenRange = Math.Abs(greenRange - greenMin); 346 | //Normalize the values in the arrays and load the result image 347 | for (int column = 0; column < i.Bitmap.Width; column++) 348 | { 349 | for (int row = 0; row < i.Bitmap.Height; row++) 350 | { 351 | if (redRange != 0) 352 | red[column, row] = 255 - (((redMax - red[column, row]) * 255) / redRange); 353 | if (blueRange != 0) 354 | blue[column, row] = 255 - (((blueMax - blue[column, row]) * 255) / blueRange); 355 | if (greenRange != 0) 356 | green[column, row] = 255 - (((greenMax - green[column, row]) * 255) / greenRange); 357 | if (red[column, row] < 0) 358 | red[column, row] = 0; 359 | if (blue[column, row] < 0) 360 | blue[column, row] = 0; 361 | if (green[column, row] < 0) 362 | green[column, row] = 0; 363 | i2.SetPixel(column, row, Color.FromArgb(red[column, row], green[column, row], 364 | blue[column, row])); 365 | } 366 | } 367 | i.UnlockBitmap(); 368 | i2.UnlockBitmap(); 369 | return i2.Bitmap.Clone() as Bitmap; 370 | } 371 | /// 372 | /// Get the red pixels from the bitmap 373 | /// 374 | /// Image to Process 375 | /// Filtered Image 376 | public static Bitmap GetRedBitmap(Bitmap b) 377 | { 378 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 379 | for (int column = 0; column < i.Bitmap.Width; column++) 380 | { 381 | for (int row = 0; row < i.Bitmap.Height; row++) 382 | { 383 | i.SetPixel(column, row, Color.FromArgb(i.GetPixel(column, row).R, 0, 0)); 384 | } 385 | } 386 | i.UnlockBitmap(); 387 | return i.Bitmap.Clone() as Bitmap; 388 | } 389 | /// 390 | /// Get the Blue Pixes from the bitmap 391 | /// 392 | /// Image to Process 393 | /// Filtered Image 394 | public static Bitmap GetBlueBitmap(Bitmap b) 395 | { 396 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 397 | for (int column = 0; column < i.Bitmap.Width; column++) 398 | { 399 | for (int row = 0; row < i.Bitmap.Height; row++) 400 | { 401 | i.SetPixel(column, row, Color.FromArgb(0, 0, i.GetPixel(column, row).B)); 402 | } 403 | } 404 | i.UnlockBitmap(); 405 | return i.Bitmap.Clone() as Bitmap; 406 | } 407 | /// 408 | /// Get the green pixels from the image 409 | /// 410 | /// Image to Process 411 | /// Filtered Image 412 | public static Bitmap GetGreenBitmap(Bitmap b) 413 | { 414 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 415 | for (int column = 0; column < i.Bitmap.Width; column++) 416 | { 417 | for (int row = 0; row < i.Bitmap.Height; row++) 418 | { 419 | i.SetPixel(column, row, Color.FromArgb(0, i.GetPixel(column, row).G, 0)); 420 | } 421 | } 422 | i.UnlockBitmap(); 423 | return i.Bitmap.Clone() as Bitmap; 424 | } 425 | /// 426 | /// Make the image Grey scale 427 | /// 428 | /// Image to Process 429 | /// Filtered Image 430 | public static Bitmap GetGreyScaleBitmap(Bitmap b) 431 | { 432 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 433 | for (int column = 0; column < i.Bitmap.Width; column++) 434 | { 435 | for (int row = 0; row < i.Bitmap.Height; row++) 436 | { 437 | int val = i.GetGreyPixel(column, row); 438 | i.SetPixel(column, row, Color.FromArgb(val, val, val)); 439 | } 440 | } 441 | i.UnlockBitmap(); 442 | return i.Bitmap.Clone() as Bitmap; 443 | } 444 | /// 445 | /// Make the image black and white 446 | /// 447 | /// Image to Process 448 | /// Filtered Image 449 | public static Bitmap GetBlackAndWhiteBitmap(Bitmap b) 450 | { 451 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 452 | double[] histogram = new double[256]; 453 | for (int column = 0; column < i.Bitmap.Width; column++) 454 | { 455 | for (int row = 0; row < i.Bitmap.Height; row++) 456 | { 457 | histogram[i.GetGreyPixel(column, row)]++; 458 | } 459 | } 460 | //find the position of the max value on the left 461 | int leftK = 0; 462 | for (int k = 0; k < 128; k++) 463 | { 464 | if (histogram[k] > histogram[leftK]) leftK = k; 465 | } 466 | //find the position of the max value on the right 467 | int rightK = 0; 468 | for (int k = 128; k < 256; k++) 469 | { 470 | if (histogram[k] > histogram[rightK]) rightK = k; 471 | } 472 | //find the min value between the 2 local maxes 473 | int localMin = rightK; 474 | for (int k = leftK; k < rightK; k++) 475 | { 476 | if (histogram[k] < histogram[localMin]) localMin = k; 477 | } 478 | for (int column = 0; column < i.Bitmap.Width; column++) 479 | { 480 | for (int row = 0; row < i.Bitmap.Height; row++) 481 | { 482 | int val = (i.GetPixel(column, row).R + i.GetPixel(column, row).G 483 | + i.GetPixel(column, row).B) / 3; 484 | if (val > localMin) 485 | val = 255; 486 | else 487 | val = 0; 488 | i.SetPixel(column, row, Color.FromArgb(val, val, val)); 489 | } 490 | } 491 | i.UnlockBitmap(); 492 | return i.Bitmap.Clone() as Bitmap; 493 | } 494 | public static Bitmap GetBlackAndWhiteBitmap2(Bitmap b) 495 | { 496 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 497 | double[] histogram = new double[256]; 498 | for (int column = 0; column < i.Bitmap.Width; column++) 499 | { 500 | for (int row = 0; row < i.Bitmap.Height; row++) 501 | { 502 | histogram[i.GetGreyPixel(column, row)]++; 503 | } 504 | } 505 | double k = b.Width * b.Height; 506 | double half = k / 2; 507 | int middle = 0; 508 | while (k > half) 509 | { 510 | k = k - histogram[middle]; 511 | middle++; 512 | } 513 | for (int column = 0; column < i.Bitmap.Width; column++) 514 | { 515 | for (int row = 0; row < i.Bitmap.Height; row++) 516 | { 517 | int val = (i.GetPixel(column, row).R + i.GetPixel(column, row).G 518 | + i.GetPixel(column, row).B) / 3; 519 | if (val > middle) 520 | val = 255; 521 | else 522 | val = 0; 523 | i.SetPixel(column, row, Color.FromArgb(val, val, val)); 524 | } 525 | } 526 | i.UnlockBitmap(); 527 | return i.Bitmap.Clone() as Bitmap; 528 | } 529 | /// 530 | /// Perform a Box filter using a 3x3 Mask 531 | /// 532 | /// Image to Process 533 | /// Filtered Image 534 | public static Bitmap Box3x3(Bitmap b) 535 | { 536 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 537 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 538 | for (int column = 1; column < i.Bitmap.Width - 1; column++) 539 | { 540 | for (int row = 1; row < i.Bitmap.Height - 1; row++) 541 | { 542 | Color[,] c = i.Get3x3(row, column); 543 | int red = (c[0, 0].R + c[0, 1].R + c[0, 2].R + c[1, 0].R + c[1, 2].R + c[2, 0].R 544 | + c[2, 1].R + c[2, 2].R + c[1, 1].R) / 9; 545 | int green = (c[0, 0].G + c[0, 1].G + c[0, 2].G + c[1, 0].G + c[1, 2].G + c[2, 0].G 546 | + c[2, 1].G + c[2, 2].G + c[1, 1].G) / 9; 547 | int blue = (c[0, 0].B + c[0, 1].B + c[0, 2].B + c[1, 0].B + c[1, 2].B + c[2, 0].B 548 | + c[2, 1].B + c[2, 2].B + c[1, 1].B) / 9; 549 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 550 | } 551 | } 552 | i.UnlockBitmap(); 553 | i2.UnlockBitmap(); 554 | return i2.Bitmap.Clone() as Bitmap; 555 | } 556 | /// 557 | /// Perform a Bionomial filter using a 3x3 Mask 558 | /// 559 | /// Image to Process 560 | /// Filtered Image 561 | public static Bitmap Binomial3x3(Bitmap b) 562 | { 563 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 564 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 565 | for (int column = 1; column < i.Bitmap.Width - 1; column++) 566 | { 567 | for (int row = 1; row < i.Bitmap.Height - 1; row++) 568 | { 569 | Color[,] c = i.Get3x3(row, column); 570 | int red = ((c[0, 0].R * 1) + (c[0, 1].R * 2) + (c[0, 2].R * 1) + (c[1, 0].R * 2) 571 | + (c[1, 1].R * 4) + (c[1, 2].R * 2) + (c[2, 0].R * 1) + (c[2, 1].R * 2) 572 | + (c[2, 2].R * 1)) / 16; 573 | int green = ((c[0, 0].G * 1) + (c[0, 1].G * 2) + (c[0, 2].G * 1) + (c[1, 0].G * 2) 574 | + (c[1, 1].G * 4) + (c[1, 2].G * 2) + (c[2, 0].G * 1) + (c[2, 1].G * 2) 575 | + (c[2, 2].G * 1)) / 16; 576 | int blue = ((c[0, 0].B * 1) + (c[0, 1].B * 2) + (c[0, 2].B * 1) + (c[1, 0].B * 2) 577 | + (c[1, 1].B * 4) + (c[1, 2].B * 2) + (c[2, 0].B * 1) + (c[2, 1].B * 2) 578 | + (c[2, 2].B * 1)) / 16; 579 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 580 | } 581 | } 582 | i.UnlockBitmap(); 583 | i2.UnlockBitmap(); 584 | return i2.Bitmap.Clone() as Bitmap; 585 | } 586 | /// 587 | /// Perform a Median filter using a 3x3 mask 588 | /// 589 | /// Image to Process 590 | /// Filtered Image 591 | public static Bitmap Median3x3(Bitmap b) 592 | { 593 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 594 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 595 | for (int column = 1; column < i.Bitmap.Width - 1; column++) 596 | { 597 | for (int row = 1; row < i.Bitmap.Height - 1; row++) 598 | { 599 | Color[,] c = i.Get3x3(row, column); 600 | int red = Median(c[0, 0].R, c[0, 1].R, c[0, 2].R, c[1, 0].R, c[1, 1].R, c[1, 2].R, 601 | c[2, 0].R, c[2, 1].R, c[2, 2].R); 602 | int green = Median(c[0, 0].G, c[0, 1].G, c[0, 2].G, c[1, 0].G, c[1, 1].G, 603 | c[1, 2].G, c[2, 0].G, c[2, 1].G, c[2, 2].G); 604 | int blue = Median(c[0, 0].B, c[0, 1].B, c[0, 2].B, c[1, 0].B, c[1, 1].B, c[1, 2].B, 605 | c[2, 0].B, c[2, 1].B, c[2, 2].B); 606 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 607 | } 608 | } 609 | i.UnlockBitmap(); 610 | i2.UnlockBitmap(); 611 | return i2.Bitmap.Clone() as Bitmap; 612 | } 613 | /// 614 | /// Perform a Box filter using a 5x5 Mask 615 | /// 616 | /// Image to Process 617 | /// Filtered Image 618 | public static Bitmap Box5x5(Bitmap b) 619 | { 620 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 621 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 622 | for (int column = 2; column < i.Bitmap.Width - 2; column++) 623 | { 624 | for (int row = 2; row < i.Bitmap.Height - 2; row++) 625 | { 626 | Color[,] c = i.Get5x5(row, column); 627 | int red = (c[0, 0].R + c[0, 1].R + c[0, 2].R + c[0, 3].R + c[0, 4].R + c[1, 0].R 628 | + c[1, 1].R + c[1, 2].R + c[1, 3].R + c[1, 4].R + c[2, 0].R + c[2, 1].R 629 | + c[2, 2].R + c[2, 3].R + c[2, 4].R + c[3, 0].R + c[3, 1].R + c[3, 2].R 630 | + c[3, 3].R + c[3, 4].R + c[4, 0].R + c[4, 1].R + c[4, 2].R + c[4, 3].R 631 | + c[4, 4].R) / 25; 632 | int green = (c[0, 0].G + c[0, 1].G + c[0, 2].G + c[0, 3].G + c[0, 4].G + c[1, 0].G 633 | + c[1, 1].G + c[1, 2].G + c[1, 3].G + c[1, 4].G + c[2, 0].G + c[2, 1].G 634 | + c[2, 2].G + c[2, 3].G + c[2, 4].G + c[3, 0].G + c[3, 1].G + c[3, 2].G 635 | + c[3, 3].G + c[3, 4].G + c[4, 0].G + c[4, 1].G + c[4, 2].G + c[4, 3].G 636 | + c[4, 4].G) / 25; 637 | int blue = (c[0, 0].B + c[0, 1].B + c[0, 2].B + c[0, 3].B + c[0, 4].B + c[1, 0].B 638 | + c[1, 1].B + c[1, 2].B + c[1, 3].B + c[1, 4].B + c[2, 0].B + c[2, 1].B 639 | + c[2, 2].B + c[2, 3].B + c[2, 4].B + c[3, 0].B + c[3, 1].B + c[3, 2].B 640 | + c[3, 3].B + c[3, 4].B + c[4, 0].B + c[4, 1].B + c[4, 2].B + c[4, 3].B 641 | + c[4, 4].B) / 25; 642 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 643 | } 644 | } 645 | i.UnlockBitmap(); 646 | i2.UnlockBitmap(); 647 | return i2.Bitmap.Clone() as Bitmap; 648 | } 649 | /// 650 | /// Perform a Binomial filter using a 5x5 Mask 651 | /// 652 | /// Image to Process 653 | /// Filtered Image 654 | public static Bitmap Binomial5x5(Bitmap b) 655 | { 656 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 657 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 658 | for (int column = 2; column < i.Bitmap.Width - 2; column++) 659 | { 660 | for (int row = 2; row < i.Bitmap.Height - 2; row++) 661 | { 662 | Color[,] c = i.Get5x5(row, column); 663 | int red = ((c[0, 0].R * 1) + (c[0, 1].R * 4) + (c[0, 2].R * 6) + (c[0, 3].R * 4) 664 | + (c[0, 4].R * 1) + (c[1, 0].R * 4) + (c[1, 1].R * 16) + (c[1, 2].R * 24) 665 | + (c[1, 3].R * 16) + (c[1, 4].R * 4) + (c[2, 0].R * 6) + (c[2, 1].R * 24) 666 | + (c[2, 2].R * 36) + (c[2, 3].R * 24) + (c[2, 4].R * 6) + (c[3, 0].R * 4) 667 | + (c[3, 1].R * 16) + (c[3, 2].R * 24) + (c[3, 3].R * 16) + (c[3, 4].R * 4) 668 | + (c[4, 0].R * 1) + (c[4, 1].R * 4) + (c[4, 2].R * 6) + (c[4, 3].R * 4) 669 | + (c[4, 4].R * 1)) / 256; 670 | int green = ((c[0, 0].G * 1) + (c[0, 1].G * 4) + (c[0, 2].G * 6) + (c[0, 3].G * 4) 671 | + (c[0, 4].G * 1) + (c[1, 0].G * 4) + (c[1, 1].G * 16) + (c[1, 2].G * 24) 672 | + (c[1, 3].G * 16) + (c[1, 4].G * 4) + (c[2, 0].G * 6) + (c[2, 1].G * 24) 673 | + (c[2, 2].G * 36) + (c[2, 3].G * 24) + (c[2, 4].G * 6) + (c[3, 0].G * 4) 674 | + (c[3, 1].G * 16) + (c[3, 2].G * 24) + (c[3, 3].G * 16) + (c[3, 4].G * 4) 675 | + (c[4, 0].G * 1) + (c[4, 1].G * 4) + (c[4, 2].G * 6) + (c[4, 3].G * 4) 676 | + (c[4, 4].G * 1)) / 256; 677 | int blue = ((c[0, 0].B * 1) + (c[0, 1].B * 4) + (c[0, 2].B * 6) + (c[0, 3].B * 4) 678 | + (c[0, 4].B * 1) + (c[1, 0].B * 4) + (c[1, 1].B * 16) + (c[1, 2].B * 24) 679 | + (c[1, 3].B * 16) + (c[1, 4].B * 4) + (c[2, 0].B * 6) + (c[2, 1].B * 24) 680 | + (c[2, 2].B * 36) + (c[2, 3].B * 24) + (c[2, 4].B * 6) + (c[3, 0].B * 4) 681 | + (c[3, 1].B * 16) + (c[3, 2].B * 24) + (c[3, 3].B * 16) + (c[3, 4].B * 4) 682 | + (c[4, 0].B * 1) + (c[4, 1].B * 4) + (c[4, 2].B * 6) + (c[4, 3].B * 4) 683 | + (c[4, 4].B * 1)) / 256; 684 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 685 | } 686 | } 687 | i.UnlockBitmap(); 688 | i2.UnlockBitmap(); 689 | return i2.Bitmap.Clone() as Bitmap; 690 | } 691 | /// 692 | /// Perform a Median fiter using a 5x5 Mask 693 | /// 694 | /// Image to Process 695 | /// Filtered Image 696 | public static Bitmap Median5x5(Bitmap b) 697 | { 698 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 699 | ImagerBitmap i2 = new ImagerBitmap(b.Clone() as Bitmap); 700 | for (int column = 2; column < i.Bitmap.Width - 2; column++) 701 | { 702 | for (int row = 2; row < i.Bitmap.Height - 2; row++) 703 | { 704 | Color[,] c = i.Get5x5(row, column); 705 | int red = Median(c[0, 0].R, c[0, 1].R, c[0, 2].R, c[0, 3].R, c[0, 4].R, c[1, 0].R, 706 | c[1, 1].R, c[1, 2].R, c[1, 3].R, c[1, 4].R, c[2, 0].R, c[2, 1].R, c[2, 2].R, 707 | c[2, 3].R, c[2, 4].R, c[3, 0].R, c[3, 1].R, c[3, 2].R, c[3, 3].R, c[3, 4].R, 708 | c[4, 0].R, c[4, 1].R, c[4, 2].R, c[4, 3].R, c[4, 4].R); 709 | int green = Median(c[0, 0].G, c[0, 1].G, c[0, 2].G, c[0, 3].G, c[0, 4].G, c[1, 0].G, 710 | c[1, 1].G, c[1, 2].G, c[1, 3].G, c[1, 4].G, c[2, 0].G, c[2, 1].G, c[2, 2].G, 711 | c[2, 3].G, c[2, 4].G, c[3, 0].G, c[3, 1].G, c[3, 2].G, c[3, 3].G, c[3, 4].G, 712 | c[4, 0].G, c[4, 1].G, c[4, 2].G, c[4, 3].G, c[4, 4].G); 713 | int blue = Median(c[0, 0].B, c[0, 1].B, c[0, 2].B, c[0, 3].B, c[0, 4].B, c[1, 0].B, 714 | c[1, 1].B, c[1, 2].B, c[1, 3].B, c[1, 4].B, c[2, 0].B, c[2, 1].B, c[2, 2].B, 715 | c[2, 3].B, c[2, 4].B, c[3, 0].B, c[3, 1].B, c[3, 2].B, c[3, 3].B, c[3, 4].B, 716 | c[4, 0].B, c[4, 1].B, c[4, 2].B, c[4, 3].B, c[4, 4].B); 717 | i2.SetPixel(column, row, Color.FromArgb(red, green, blue)); 718 | } 719 | } 720 | i.UnlockBitmap(); 721 | i2.UnlockBitmap(); 722 | return i2.Bitmap.Clone() as Bitmap; 723 | } 724 | /// 725 | /// Find the Median value in an array of int's 726 | /// 727 | /// Array of values 728 | /// Median value 729 | private static int Median(params int[] values) 730 | { 731 | Array.Sort(values); 732 | return values[((values.Length - 1) / 2) + 1]; 733 | } 734 | /// 735 | /// Resize an image 736 | /// 737 | /// Image to resize 738 | /// Width in pixels 739 | /// Height in pixels 740 | /// New Image 741 | public static Bitmap Resize(Bitmap b, int width, int height) 742 | { 743 | Bitmap b2 = new Bitmap(width, height, PixelFormat.Format24bppRgb); 744 | Graphics g = Graphics.FromImage(b2); 745 | g.DrawImage(b, new Rectangle(0, 0, width, height), 0, 0, b.Width, b.Height, 746 | GraphicsUnit.Pixel); 747 | g.Dispose(); 748 | return b2; 749 | } 750 | 751 | public static void GenerateExcelFile(Bitmap b) 752 | { 753 | ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap); 754 | string fileName = "output.txt"; 755 | int f = 0; 756 | using (StreamWriter sw = new StreamWriter(fileName, false)) 757 | { 758 | sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", "Index", "Row", "Column", "Red", 759 | "Green", "Blue", "Gray"); 760 | for (int column = 0; column < i.Bitmap.Width; column++) 761 | { 762 | for (int row = 0; row < i.Bitmap.Height; row++) 763 | { 764 | f++; 765 | Color c = i.GetPixel(column, row); 766 | int g = i.GetGreyPixel(column, row); 767 | sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", f, 768 | row, column, c.R, c.G, c.B, g); 769 | } 770 | } 771 | } 772 | i.UnlockBitmap(); 773 | System.Diagnostics.Process.Start(fileName); 774 | } 775 | } 776 | } 777 | --------------------------------------------------------------------------------