commit 91de52b22219b2a90c914165e0354ed95587f26a Author: BlubbFish Date: Sun Nov 15 18:29:27 2015 +0000 openclfilter hinzugefügt diff --git a/AForge.Video.DirectShow.dll b/AForge.Video.DirectShow.dll new file mode 100644 index 0000000..d8d48b4 Binary files /dev/null and b/AForge.Video.DirectShow.dll differ diff --git a/AForge.Video.dll b/AForge.Video.dll new file mode 100644 index 0000000..fc5e5c6 Binary files /dev/null and b/AForge.Video.dll differ diff --git a/AForge.dll b/AForge.dll new file mode 100644 index 0000000..8879d4f Binary files /dev/null and b/AForge.dll differ diff --git a/OpenCL.NET.dll b/OpenCL.NET.dll new file mode 100644 index 0000000..1cb7ace Binary files /dev/null and b/OpenCL.NET.dll differ diff --git a/OpenCL.NET.xml b/OpenCL.NET.xml new file mode 100644 index 0000000..3026ddc --- /dev/null +++ b/OpenCL.NET.xml @@ -0,0 +1,143 @@ + + + + OpenCL.NET + + + + + This class provides the driver interface for OpenGL interoperability + with OpenCL standard. + + + + + This class provides the driver interface to OpenCL functions. + + + + + Used to represent a platform dependent sized variable. + On 32 bit platforms it is 4 bytes wide (int, uint), on 64 bit it is + 8 bytes wide (long, ulong). + + This class maps to the C/C++ native size_t data type. + + + + + Creates a new instance based on the given value. + + Integer value to represent. + + + + Creates a new instance based on the given value. + + Integer value to represent. + + + + Creates a new instance based on the given value. + + Integer value to represent. + + + + Creates a new instance based on the given value. + + Integer value to represent. + + + + Converts the object to int. + + Object to convert. + Integer value represented by the object. + + + + Converts the object to uint. + + Object to convert. + Integer value represented by the object. + + + + Converts the object to long. + + Object to convert. + Integer value represented by the object. + + + + Converts the object to ulong. + + Object to convert. + Integer value represented by the object. + + + + Converts the given integer to an object. + + Integer value to convert. + New object representing this value. + + + + Converts the given integer to an object. + + Integer value to convert. + New object representing this value. + + + + Converts the given integer to an object. + + Integer value to convert. + New object representing this value. + + + + Converts the given integer to an object. + + Integer value to convert. + New object representing this value. + + + + Compares two SizeT objects. + + First value to compare. + Second value to compare. + true or false for the comparison result. + + + + Compares two SizeT objects. + + First value to compare. + Second value to compare. + true or false for the comparison result. + + + + Returns a value indicating whether this instance is equal to a specified object. + + An object to compare with this instance or null. + true if obj is an instance of System.IntPtr and equals the value of this instance; otherwise, false. + + + + Converts the numeric value of the current object to its equivalent string representation. + + The string representation of the value of this instance. + + + + Returns the hash code for this instance. + + A 32-bit signed integer hash code. + + + diff --git a/OpenCLFilter.sln b/OpenCLFilter.sln new file mode 100644 index 0000000..7343792 --- /dev/null +++ b/OpenCLFilter.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCLFilter", "OpenCLFilter\OpenCLFilter.csproj", "{E40C284E-CF7A-4208-B586-C56E3D6DA194}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E40C284E-CF7A-4208-B586-C56E3D6DA194}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E40C284E-CF7A-4208-B586-C56E3D6DA194}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E40C284E-CF7A-4208-B586-C56E3D6DA194}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E40C284E-CF7A-4208-B586-C56E3D6DA194}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpenCLFilter/CLFilter.cs b/OpenCLFilter/CLFilter.cs new file mode 100644 index 0000000..67a81ef --- /dev/null +++ b/OpenCLFilter/CLFilter.cs @@ -0,0 +1,309 @@ +using System; +using System.Collections.Generic; +using OpenCLTemplate; +using System.Text; + +//By Douglas Andrade douglas@cmsoft.com.br +//http://www.cmsoft.com.br +//Filter examples: visit http://www.gamedev.net/reference/programming/features/imageproc/page2.asp + +namespace OpenCLFilter +{ + /// Applies filter to a given image + public static class CLFilter + { + /// Static class already initialized? + private static bool Initialized = false; + + /// Apply filter kernel + private static CLCalc.Program.Kernel kernelApplyFilter; + /// Apply filter kernel + private static CLCalc.Program.Kernel kernelApplyFilterWorkDim2; + + /// Filter values + private static CLCalc.Program.Variable varFilter; + + /// Initializes class + private static void Init(int FilterSize) + { + if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.Unknown) CLCalc.InitCL(); + + //Compiles source code + CLCalc.Program.Compile((new CLFilterSrc()).src); + + //Creates kernel + kernelApplyFilter = new CLCalc.Program.Kernel("ApplyFilter"); + kernelApplyFilterWorkDim2 = new CLCalc.Program.Kernel("ImgFilter"); + + //Creates filter + varFilter = new CLCalc.Program.Variable(new float[3 * FilterSize * FilterSize]); + //Width + varWidth = new CLCalc.Program.Variable(new int[1]); + + Initialized = true; + } + + private static float[] FilteredVals; + private static CLCalc.Program.Variable varFiltered; + private static CLCalc.Program.Variable varWidth; + + /// Applies given filter to the image + /// Image to be filtered + /// Filter. [3*size*size] + public static void ApplyFilter(ImageData imgDt, float[] Filter, bool useOpenCL, bool useWorkDim2) + { + int FilterSize = (int)Math.Sqrt(Filter.Length/3); + + if (Filter.Length != 3 * FilterSize * FilterSize) + throw new Exception("Invalid filter"); + + if (!Initialized && useOpenCL) Init(FilterSize); + + //Writes filter to device + if(useOpenCL) varFilter.WriteToDevice(Filter); + + if (FilteredVals == null || FilteredVals.Length != imgDt.Height * imgDt.Width * 3) + { + //Filtered values + FilteredVals = new float[imgDt.Height * imgDt.Width * 3]; + varFiltered = new CLCalc.Program.Variable(FilteredVals); + } + + //Width + if (useOpenCL) varWidth.WriteToDevice(new int[] { imgDt.Width }); + + + //Executes filtering + int mean = (FilterSize - 1) / 2; + if (useOpenCL) + { + CLCalc.Program.Variable[] args = new CLCalc.Program.Variable[] { imgDt.varData, varFilter, varFiltered, varWidth }; + if (useWorkDim2) + { + kernelApplyFilterWorkDim2.Execute(args, new int[] { imgDt.Width - FilterSize, imgDt.Height - FilterSize }); + } + else + { + kernelApplyFilter.Execute(args, new int[] { imgDt.Height - FilterSize }); + } + //Reads data back + varFiltered.ReadFromDeviceTo(FilteredVals); + + } + else + { + ApplyFilter(imgDt.Data, Filter, FilteredVals, new int[] { imgDt.Width }, imgDt.Height - FilterSize); + } + + //Writes to image data + for (int y = mean; y < imgDt.Height - mean - 1; y++) + { + int wy = imgDt.Width * y; + for (int x = mean; x < imgDt.Width - mean - 1; x++) + { + int ind = 3 * (x + wy); + imgDt.Data[ind] = (byte)FilteredVals[ind]; + imgDt.Data[ind + 1] = (byte)FilteredVals[ind + 1]; + imgDt.Data[ind + 2] = (byte)FilteredVals[ind + 2]; + } + } + + //Writes filtered values + //In the future this rewriting can be avoided + //because byte_addressable will be widely available + if (useOpenCL) imgDt.varData.WriteToDevice(imgDt.Data); + } + + private const int FILTERSIZE = 7; + private const int CENTER = 3; + + private static void ApplyFilter(byte[] ImgData, + float[] Filter, + float[] FilteredImage, + int[] ImgWidth, int n) + { + for (int y = 0; y < n; y++) + { + int w = ImgWidth[0]; + + //Image values + float[, ,] ImgValues = new float[3, FILTERSIZE, FILTERSIZE]; + + //Copies filter to local memory + float[, ,] localfilter = new float[3, FILTERSIZE, FILTERSIZE]; + + //Initialization of ImgValues + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE; j++) + { + ImgValues[0, i, j] = ImgData[3 * ((y + i) * w + j)]; + ImgValues[1, i, j] = ImgData[3 * ((y + i) * w + j) + 1]; + ImgValues[2, i, j] = ImgData[3 * ((y + i) * w + j) + 2]; + + localfilter[0, i, j] = Filter[3 * (i * FILTERSIZE + j)]; + localfilter[1, i, j] = Filter[3 * (i * FILTERSIZE + j) + 1]; + localfilter[2, i, j] = Filter[3 * (i * FILTERSIZE + j) + 2]; + } + } + + + int xMax = w - CENTER - 1; + int ind = 0; + for (int x = 0; x < xMax; x++) + { + //Calculates filtered value + float[] filteredValue = new float[3]; + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE - 1; j++) + { + // float4 pixVals = (float4)(ImgValues[0][i][j],ImgValues[1][i][j],ImgValues[2][i][j],0); + // float4 filterVals = (float4)(localfilter[0][i][j],localfilter[1][i][j],localfilter[2][i][j],0); + // + // filteredValue = mad(pixVals,filterVals,filteredValue); + + filteredValue[0] = ImgValues[0, i, j] * localfilter[0, i, j] + filteredValue[0]; + filteredValue[1] = ImgValues[1, i, j] * localfilter[1, i, j] + filteredValue[1]; + filteredValue[2] = ImgValues[2, i, j] * localfilter[2, i, j] + filteredValue[2]; + } + } + ind = 3 * ((y + CENTER) * w + x + CENTER); + FilteredImage[ind] = Math.Min(Math.Max(filteredValue[0], 0), 255); + FilteredImage[ind + 1] = Math.Min(Math.Max(filteredValue[1], 0), 255); + FilteredImage[ind + 2] = Math.Min(Math.Max(filteredValue[2], 0), 255); + + //Gets next filter values + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE - 1; j++) + { + ImgValues[0, i, j] = ImgValues[0, i, j + 1]; + ImgValues[1, i, j] = ImgValues[1, i, j + 1]; + ImgValues[2, i, j] = ImgValues[2, i, j + 1]; + } + ind = 3 * ((y + i) * w + x + FILTERSIZE - 1); + ImgValues[0, i, FILTERSIZE - 1] = ImgData[ind]; + ImgValues[1, i, FILTERSIZE - 1] = ImgData[ind + 1]; + ImgValues[2, i, FILTERSIZE - 1] = ImgData[ind + 2]; + } + + } + } + } + + /// Filter source + private class CLFilterSrc + { + public string src = @" + +#define FILTERSIZE 7 +#define CENTER 3 + +__kernel void ApplyFilter(__global uchar * ImgData, + __global float * Filter, + __global float * FilteredImage, + __global int * ImgWidth) + +{ + int y = get_global_id(0); + int w = ImgWidth[0]; + + //Image values + float ImgValues[3][FILTERSIZE][FILTERSIZE]; + + //Copies filter to local memory + float localfilter[3][FILTERSIZE][FILTERSIZE]; + + //Initialization of ImgValues + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE; j++) + { + ImgValues[0][i][j] = ImgData[3*((y+i)*w+j)]; + ImgValues[1][i][j] = ImgData[3*((y+i)*w+j)+1]; + ImgValues[2][i][j] = ImgData[3*((y+i)*w+j)+2]; + + localfilter[0][i][j] = Filter[3*(i*FILTERSIZE + j)]; + localfilter[1][i][j] = Filter[3*(i*FILTERSIZE + j)+1]; + localfilter[2][i][j] = Filter[3*(i*FILTERSIZE + j)+2]; + } + } + + + int xMax = w-CENTER; + int ind = 0; + for (int x = 0; x < xMax; x++) + { + //Calculates filtered value + float4 filteredValue = 0; + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE-1; j++) + { + float4 pixVals = (float4)(ImgValues[0][i][j],ImgValues[1][i][j],ImgValues[2][i][j],0); + float4 filterVals = (float4)(localfilter[0][i][j],localfilter[1][i][j],localfilter[2][i][j],0); + + filteredValue = pixVals*filterVals+filteredValue; + +// filteredValue.x = mad(ImgValues[0][i][j], localfilter[0][i][j], filteredValue.x); +// filteredValue.y = mad(ImgValues[1][i][j], localfilter[1][i][j], filteredValue.y); +// filteredValue.z = mad(ImgValues[2][i][j], localfilter[2][i][j], filteredValue.z); + } + } + ind = 3*((y+CENTER)*w+x+CENTER); + FilteredImage[ind] = clamp(filteredValue.x,0,255); + FilteredImage[ind+1] = clamp(filteredValue.y,0,255); + FilteredImage[ind+2] = clamp(filteredValue.z,0,255); + + //Gets next filter values + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE-1; j++) + { + ImgValues[0][i][j] = ImgValues[0][i][j+1]; + ImgValues[1][i][j] = ImgValues[1][i][j+1]; + ImgValues[2][i][j] = ImgValues[2][i][j+1]; + } + ind = 3*((y+i)*w+x+FILTERSIZE-1); + ImgValues[0][i][FILTERSIZE-1] = ImgData[ind]; + ImgValues[1][i][FILTERSIZE-1] = ImgData[ind+1]; + ImgValues[2][i][FILTERSIZE-1] = ImgData[ind+2]; + } + + } +} + +kernel void ImgFilter(global uchar * image, + global float * Filter, + global float * FilteredImage, + global int * Width) + +{ + int x = get_global_id(0); + int y = get_global_id(1); + int w = Width[0]; + int ind = 0; + int ind2 = 0; + + float4 filteredVal = (float4)(0,0,0,0); + for (int i = 0; i < FILTERSIZE; i++) + { + for (int j = 0; j < FILTERSIZE; j++) + { + ind = 3*(x+j + w*(y+i)); + ind2 = 3*(i*FILTERSIZE + j); + filteredVal.x = mad(Filter[ind2] , (float)image[ind], filteredVal.x); + filteredVal.y = mad(Filter[ind2+1] , (float)image[ind+1],filteredVal.y); + filteredVal.z = mad(Filter[ind2+2] , (float)image[ind+2],filteredVal.z); + } + } + ind = 3*(x+CENTER + w*(y+CENTER)); + FilteredImage[ind] = clamp(filteredVal.x,0,255); + FilteredImage[ind+1] = clamp(filteredVal.y,0,255); + FilteredImage[ind+2] = clamp(filteredVal.z,0,255); +} +"; + } + } +} diff --git a/OpenCLFilter/Form1.Designer.cs b/OpenCLFilter/Form1.Designer.cs new file mode 100644 index 0000000..630ea20 --- /dev/null +++ b/OpenCLFilter/Form1.Designer.cs @@ -0,0 +1,276 @@ +namespace OpenCLFilter +{ + partial class frmMainFilter + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMainFilter)); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.btnOpenFile = new System.Windows.Forms.ToolStripButton(); + this.btnSave = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.btnApplyFilter = new System.Windows.Forms.ToolStripButton(); + this.cmbWorkDim = new System.Windows.Forms.ToolStripComboBox(); + this.btnFilterNoOpenCL = new System.Windows.Forms.ToolStripButton(); + this.btnConfigFilter = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.btnStartWebCam = new System.Windows.Forms.ToolStripButton(); + this.btnDeactivateCam = new System.Windows.Forms.ToolStripButton(); + this.lblFps = new System.Windows.Forms.ToolStripLabel(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.btnCLConfig = new System.Windows.Forms.ToolStripButton(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.pic = new System.Windows.Forms.PictureBox(); + this.toolStrip1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pic)).BeginInit(); + this.SuspendLayout(); + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnOpenFile, + this.btnSave, + this.toolStripSeparator1, + this.btnApplyFilter, + this.cmbWorkDim, + this.btnFilterNoOpenCL, + this.btnConfigFilter, + this.toolStripSeparator2, + this.btnStartWebCam, + this.btnDeactivateCam, + this.lblFps, + this.toolStripSeparator3, + this.btnCLConfig}); + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(702, 55); + this.toolStrip1.TabIndex = 0; + this.toolStrip1.Text = "toolStrip1"; + // + // btnOpenFile + // + this.btnOpenFile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnOpenFile.Image = ((System.Drawing.Image)(resources.GetObject("btnOpenFile.Image"))); + this.btnOpenFile.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnOpenFile.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnOpenFile.Name = "btnOpenFile"; + this.btnOpenFile.Size = new System.Drawing.Size(52, 52); + this.btnOpenFile.Text = "Load picture to be filtered"; + this.btnOpenFile.Click += new System.EventHandler(this.btnOpenFile_Click); + // + // btnSave + // + this.btnSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnSave.Image = ((System.Drawing.Image)(resources.GetObject("btnSave.Image"))); + this.btnSave.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnSave.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnSave.Name = "btnSave"; + this.btnSave.Size = new System.Drawing.Size(52, 52); + this.btnSave.ToolTipText = "Save image"; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 55); + // + // btnApplyFilter + // + this.btnApplyFilter.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnApplyFilter.Image = ((System.Drawing.Image)(resources.GetObject("btnApplyFilter.Image"))); + this.btnApplyFilter.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnApplyFilter.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnApplyFilter.Name = "btnApplyFilter"; + this.btnApplyFilter.Size = new System.Drawing.Size(52, 52); + this.btnApplyFilter.ToolTipText = "Apply filter"; + this.btnApplyFilter.Click += new System.EventHandler(this.btnApplyFilter_Click); + // + // cmbWorkDim + // + this.cmbWorkDim.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbWorkDim.Items.AddRange(new object[] { + "Work_dim = 1", + "Work_dim = 2"}); + this.cmbWorkDim.Name = "cmbWorkDim"; + this.cmbWorkDim.Size = new System.Drawing.Size(121, 55); + this.cmbWorkDim.SelectedIndexChanged += new System.EventHandler(this.cmbWorkDim_SelectedIndexChanged); + this.cmbWorkDim.Click += new System.EventHandler(this.cmbWorkDim_Click); + // + // btnFilterNoOpenCL + // + this.btnFilterNoOpenCL.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnFilterNoOpenCL.Image = ((System.Drawing.Image)(resources.GetObject("btnFilterNoOpenCL.Image"))); + this.btnFilterNoOpenCL.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnFilterNoOpenCL.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnFilterNoOpenCL.Name = "btnFilterNoOpenCL"; + this.btnFilterNoOpenCL.Size = new System.Drawing.Size(52, 52); + this.btnFilterNoOpenCL.ToolTipText = "Filter image without using OpenCL"; + this.btnFilterNoOpenCL.Click += new System.EventHandler(this.btnFilterNoOpenCL_Click); + // + // btnConfigFilter + // + this.btnConfigFilter.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnConfigFilter.Image = ((System.Drawing.Image)(resources.GetObject("btnConfigFilter.Image"))); + this.btnConfigFilter.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnConfigFilter.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnConfigFilter.Name = "btnConfigFilter"; + this.btnConfigFilter.Size = new System.Drawing.Size(52, 52); + this.btnConfigFilter.Text = "Change filter configuration"; + this.btnConfigFilter.Click += new System.EventHandler(this.btnConfigFilter_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(6, 55); + // + // btnStartWebCam + // + this.btnStartWebCam.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnStartWebCam.Image = ((System.Drawing.Image)(resources.GetObject("btnStartWebCam.Image"))); + this.btnStartWebCam.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnStartWebCam.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnStartWebCam.Name = "btnStartWebCam"; + this.btnStartWebCam.Size = new System.Drawing.Size(52, 52); + this.btnStartWebCam.ToolTipText = "Activate webcam real-time filtering"; + this.btnStartWebCam.Click += new System.EventHandler(this.btnStartWebCam_Click); + // + // btnDeactivateCam + // + this.btnDeactivateCam.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnDeactivateCam.Image = ((System.Drawing.Image)(resources.GetObject("btnDeactivateCam.Image"))); + this.btnDeactivateCam.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnDeactivateCam.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnDeactivateCam.Name = "btnDeactivateCam"; + this.btnDeactivateCam.Size = new System.Drawing.Size(52, 52); + this.btnDeactivateCam.Text = "toolStripButton3"; + this.btnDeactivateCam.ToolTipText = "Deactivate webcam real-time filtering"; + this.btnDeactivateCam.Click += new System.EventHandler(this.btnDeactivateCam_Click); + // + // lblFps + // + this.lblFps.AutoSize = false; + this.lblFps.Name = "lblFps"; + this.lblFps.Size = new System.Drawing.Size(60, 52); + this.lblFps.Text = "0 fps"; + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(6, 55); + // + // btnCLConfig + // + this.btnCLConfig.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnCLConfig.Image = ((System.Drawing.Image)(resources.GetObject("btnCLConfig.Image"))); + this.btnCLConfig.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.btnCLConfig.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnCLConfig.Name = "btnCLConfig"; + this.btnCLConfig.Size = new System.Drawing.Size(52, 52); + this.btnCLConfig.ToolTipText = "Open OpenCL configuration"; + this.btnCLConfig.Click += new System.EventHandler(this.btnCLConfig_Click); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.panel1); + this.groupBox1.Location = new System.Drawing.Point(12, 58); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(678, 305); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Picture"; + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.AutoScroll = true; + this.panel1.Controls.Add(this.pic); + this.panel1.Location = new System.Drawing.Point(6, 19); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(666, 280); + this.panel1.TabIndex = 0; + // + // pic + // + this.pic.Location = new System.Drawing.Point(3, 3); + this.pic.Name = "pic"; + this.pic.Size = new System.Drawing.Size(150, 116); + this.pic.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pic.TabIndex = 0; + this.pic.TabStop = false; + // + // frmMainFilter + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(702, 375); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.toolStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "frmMainFilter"; + this.Text = "CMSoft OpenCL image filtering Case Study"; + this.Load += new System.EventHandler(this.frmMainFilter_Load); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmMainFilter_FormClosing); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pic)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton btnOpenFile; + private System.Windows.Forms.ToolStripButton btnApplyFilter; + private System.Windows.Forms.ToolStripButton btnSave; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripButton btnConfigFilter; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripButton btnStartWebCam; + private System.Windows.Forms.ToolStripButton btnDeactivateCam; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.PictureBox pic; + private System.Windows.Forms.ToolStripButton btnCLConfig; + private System.Windows.Forms.ToolStripLabel lblFps; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripButton btnFilterNoOpenCL; + private System.Windows.Forms.ToolStripComboBox cmbWorkDim; + } +} + diff --git a/OpenCLFilter/Form1.cs b/OpenCLFilter/Form1.cs new file mode 100644 index 0000000..dbbf137 --- /dev/null +++ b/OpenCLFilter/Form1.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using AForge.Video; +using AForge.Video.DirectShow; + +namespace OpenCLFilter +{ + public partial class frmMainFilter : Form + { + public frmMainFilter() + { + InitializeComponent(); + } + + frmCfgFilter frmFilter; + private void btnConfigFilter_Click(object sender, EventArgs e) + { + if (frmFilter == null || frmFilter.IsDisposed) + frmFilter = new frmCfgFilter(); + + frmFilter.Show(); + } + + #region Open and store file, apply filter to bitmap + Bitmap bmp; + ImageData imgDt; + private void btnOpenFile_Click(object sender, EventArgs e) + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "Pictures|*.jpg"; + + if (ofd.ShowDialog() == DialogResult.OK) + { + try + { + bmp = new Bitmap(ofd.FileName); + imgDt = new ImageData(bmp); + pic.Image = bmp; + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString(), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void btnApplyFilter_Click(object sender, EventArgs e) + { + System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch(); + sWatch.Start(); + + if (frmFilter == null || frmFilter.IsDisposed) + frmFilter = new frmCfgFilter(); + + frmFilter.Show(); + + float[] filter = frmFilter.GetFilters(); + + CLFilter.ApplyFilter(imgDt, filter, true, cmbWorkDim.SelectedIndex == 1); + + bmp = imgDt.GetStoredBitmap(bmp); + pic.Image = bmp; + + sWatch.Stop(); + lblFps.Text = sWatch.Elapsed.ToString(); + } + + private void btnFilterNoOpenCL_Click(object sender, EventArgs e) + { + System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch(); + sWatch.Start(); + + if (frmFilter == null || frmFilter.IsDisposed) + frmFilter = new frmCfgFilter(); + + frmFilter.Show(); + + float[] filter = frmFilter.GetFilters(); + + CLFilter.ApplyFilter(imgDt, filter, false, false); + + bmp = imgDt.GetStoredBitmap(bmp); + pic.Image = bmp; + + sWatch.Stop(); + lblFps.Text = sWatch.Elapsed.ToString(); + + } + #endregion + + + + private void btnCLConfig_Click(object sender, EventArgs e) + { + OpenCLTemplate.frmCLInfo frmCL = new OpenCLTemplate.frmCLInfo(); + frmCL.ShowDialog(); + + } + + #region Webcam + + VideoCaptureDevice vcd; + ImageData ImgDtWebCam; + private void btnStartWebCam_Click(object sender, EventArgs e) + { + if (frmFilter == null || frmFilter.IsDisposed) + frmFilter = new frmCfgFilter(); + + frmFilter.Show(); + filterWebCam = frmFilter.GetFilters(); + + + FilterInfoCollection devs = new FilterInfoCollection(FilterCategory.VideoInputDevice); + delegRefreshPic = RefreshPic; + vcd = new VideoCaptureDevice(devs[0].MonikerString); + vcd.NewFrame += new NewFrameEventHandler(vcd_NewFrame); + vcd.DesiredFrameSize = new Size(600, 400); + vcd.Start(); + } + + System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); + bool processando = false; + int nFrames = 0; double fRate = 1; + float[] filterWebCam; + void vcd_NewFrame(object sender, NewFrameEventArgs eventArgs) + { + try + { + if (!processando) + { + processando = true; + + bmp = (Bitmap)eventArgs.Frame.Clone(); + if (ImgDtWebCam == null) + ImgDtWebCam = new ImageData(bmp); + else ImgDtWebCam.ReadBmp(bmp); + + //Filter + if (!frmFilter.IsDisposed) filterWebCam = frmFilter.GetFilters(); + + CLFilter.ApplyFilter(ImgDtWebCam, filterWebCam, true, WorkDim2); + bmp = ImgDtWebCam.GetStoredBitmap(bmp); + + + if (!sw.IsRunning) sw.Start(); + + + nFrames++; + fRate = nFrames / sw.Elapsed.TotalSeconds; + + this.Invoke(delegRefreshPic); + + processando = false; + } + } + catch (Exception ex) + { + System.Windows.Forms.MessageBox.Show(ex.ToString()); + } + + } + + private delegate void voidFunc(); + voidFunc delegRefreshPic; + + private void RefreshPic() + { + pic.Image = bmp; + pic.Refresh(); + lblFps.Text = Math.Round(fRate, 3).ToString(); + } + + private void btnDeactivateCam_Click(object sender, EventArgs e) + { + sw.Stop(); sw.Reset(); + nFrames = 0; fRate = 1; + CloseVIdeo(); + } + + private void CloseVIdeo() + { + if (vcd != null) + { + if (vcd.IsRunning) + { + vcd.SignalToStop(); + vcd = null; + } + + + } + } + + private void frmMainFilter_FormClosing(object sender, FormClosingEventArgs e) + { + CloseVIdeo(); + } + #endregion + + private void frmMainFilter_Load(object sender, EventArgs e) + { + cmbWorkDim.SelectedIndex = 1; + } + + bool WorkDim2 = true; + private void cmbWorkDim_Click(object sender, EventArgs e) + { + } + + private void cmbWorkDim_SelectedIndexChanged(object sender, EventArgs e) + { + WorkDim2 = (cmbWorkDim.SelectedIndex == 1); + } + + + + + + } +} diff --git a/OpenCLFilter/Form1.resx b/OpenCLFilter/Form1.resx new file mode 100644 index 0000000..de71c34 --- /dev/null +++ b/OpenCLFilter/Form1.resx @@ -0,0 +1,719 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + gg== + + + + + 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 + lf8PxJedC/iiEG4AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAyFSURBVGhDxVpnU1tZEvVf3R0vA9hgwGAyJgeBhJAESCCC + EDkJJHLOOWcwJthgnLPHk6rO9rme5wJMEIat/XBL6b73uk+fjle3/v77b3iz/vrrL/zxxx/47bff8PHj + R7x//x5v377Fmzdv8Pr16++Ln/k9f+e+z58/48uXL+o6vvLzp0+f8OHDB7VHW9zL3/kMPssbmbjnFjef + tf7880/1UArz7NkzPHnyBDs7O9ja2sLa2hqWlpawsLCA2dlZTE9PY2pqSr3Oz89jZWVF7dvb28PR0ZFS + 7t27d2rxPb/j/R4/fozNzU2srq6qa/i6sbGB7e1tPH36VIFDGSjLeXLeosba4sbff/9dIceH8AHr6+tK + UAo4OjqKwcFB9Pb2oqurC21tbXC73XC5XGhsbERTUxNaW1vR09ODsbExpSTvQQA0y7x48QL7+/tKUCo7 + Pj6Ovr4+da/m5mZ1L762t7djaGhI7SEQtBRlOy4v35+wAL8gQkSCF1Lwubk5TE5OKuEHBgZ+EL6hoQHV + 1dWorKxUq66uTilFJSjc4uKiQnl3d1cJQnR5f96XSlJ4Kl1bW4vS0lLk5+fDZDIhJycHubm5KCoqQn19 + vdr7/PlzpcRxa9wi6toi8hS6s7MTHR0d6iGkCxcF0azQ39+vfifiFJoPycvLg8ViUQ+12WwoKSlBVVUV + qCAVIsJElcLyMy1GwSg4ASgvL1fXWK1WGI1GpKWlIT4+HpGRkWrxewJCSxy3wgkF+CPRrqioUA+fmJhQ + wpOftAh/GxkZ+W7ympoaFBQUICsrCwkJCYiKikJERIRa0dHRSoCUlBTodDoYDAYlGFd2drb6zFeiTeUp + IBff87vMzEx1fUhICHx8fNT9CRypeBz0Ez7ACEFuEimiQnSam93KIt3d3YoWGv+JIlEj6snJyQgPD0dg + YCD8/Pzg6+urXgMCApQAVCguLk4JkZiYqJb2PjU1VQlLxcxms1p8z+9jYmIU+klJSQpUsoMR7IQFjn8g + v2gFRpCenl6UOsqQkZmlltmSC7tQhUIT+SpR0OFwKNSIJpGOjY1VD6Qyp62QkZGhLKXX69Xie67TlsnS + G5CanoHomDjEPYyHVehIQOk3jIinHfmEBTRlvn79isPDZ2hta0dSagb8A4IQHPoA0bFxSElLR7Y4WL4I + XlRUDKfzm0JcVI5KcTmdToWaZsmTXC9V1LOIvxjlXnqDUMqYA6MlDwZzHhJSMhAe/RB5tkIMj4zi1atX + KpyejkAqCp31pZawVtc3UFJWgeAHUfC5ew8Bwfdx/0EEYuMToMvSw1ZQiEZXk/jFqDLv4j+5geFzeXlZ + +Q5f5+W3MXHAzs4u1NbVo6i4BCazBem6TCQmpyA+MQUZBhNMthKY7U4k6ozINObC09aBI4k858n4Qxg9 + nSzeS7YcHh2DKc+G4PBohIgiD6JiEJeQBJ0+GwX2Yrg9LSL8Ip4dPfuegZlluZi4Xgp6e/tPMDe/IJGo + QwmfoctSFAkODUNA0H2ERsYiLduCfEcNTEUVyMjJR2VdI9YEQLLhvCTG78+1ALUj3/afPEWTpxWpmdmI + jEvAw6RUJKfrhEZm2EUYWoDh9eDwUJUJvIaLJv8gYZkKPN7ZxfjEpELfkJ2DqOhYBNwLhq9/APyEnpEP + k6HPsysFdOYCWIud6Bscxhvh/EXoX2oBasj6ZGFpGeXVtUjR6ZEqK0uEsOTlo6TUgXqJ88Mjw9jd21UK + aNmc172TgHAkmXdz6xEGh0ZQXlEltMlCWHgE/O8GwsfvLgJCHiAxIxuWonLkFDhhEEVcnjbsSNLT6qIL + LXA8pp71njchikSksLgMWUYzLPk22ArtKBMHbpCE1D/QL0Jufk/3Cv0PH/FKsvq+1DSLyyvo7OqRKFai + OB8UEopf/e/ARywQFvUQOpNVFKhApqUQjso6TE7PqnLmMvS9sgC1JyW2H++gtb0LVrtky8JilJaVo7Kq + Gi7Jxj29PcphWYaQs5//Qf/5i5d4vLuH6dk5NLlbYM7NR5REMv+AQNz+1Q9+gcGITc5AtrVEVily7WVo + 7+oTf3p+YQF3bilxkTWI6MzcPBqbPChyOFEplKqVUoCFFws7VqUHBwcKOTrwq1ev8fTgEOsbWxIIxlFd + W48sCZdh4ZGC/l3c9r2joluq3gKjzSHUKUJtowfLK2v4ck7IPDOMXsSv479RuSNBZmhkDLUNTagSgZok + S7s9HpWpWaewUFNVp0Sf58L93b19RZ/uvn6UiNJJKWkIDArBL4I+6RMhzpspTqvPL0aRsxoDw2Ny/dsL + o85peU/UQpf5Ax1zY1OydN8g6hqb0Cy0aJHijJmSlSpj/sHhAV68fIkngv7mo21MzczC09quklJMXDz8 + xHmpwN2QMCSI82YJ8uZCB9xtXdiWaEUKesN9bc+5Dc15lnn79h1mGdM7u+Fye9DW3iEZu01o1K3C6bbU + /4dS/xP9lbV1DI+Ni8Vc0BtNCBX63Pb1xy+yQsV5U7Ml8+YVo7K+WfxkXtHPW0Zo+65kAVro69dvuWF0 + fBLulnZ4WtrECm2qTGazsyQhl0gS/VlJcN19Aygrr5L6JhOBwaEKfb/AEMQk65BhkmjmqJI9Q6L00ZWQ + /26By2hz1u8fP35S6Pb2D8LV7FHZuIldlPQITFgrq+vy+wbGp2akHOiUyFUs5UcifO8E4l8+vrgXFin0 + McKQX4RGT7vaS3r+jCwXZuKLuEgnnZqZU/VKvfhDA9tKyco9vf2Ykjg+O78oTjmKOlczciz5qgT5j5/E + flGCzpsm9CmtqheKTUr4ffNT6F9YzF3mSJ8/f8GW0KRfElyN1C3VNXUSWmsk3nsksQ1hRCjW0dOHssoa + pGUaECjJ698+fvAPClX0MVqL0dLZq+h2XqV5mQzXUoAXs1aZE6Q9rR1wVlQL16UvlvzQIlbpEe675dVe + WiblcTruSO1zW0JniDhvst6MqkY3ZuRaFozeCHrenp+mEG/IkEeHHhSqlFfVwl5ShmKpj2rqpA8Wpepd + buTa7IiSItBXynG/e/cRmZAGi2Tc3sFR5bhnTRquotCVw+jpMMcWb3l1TfmCTcqMfBG4uNSJKqFVeXUd + DKZcKZdjRIEgBIXHIEXQd7V2YU3yCalz1bD5QyK7irZn7SWCrF2YoYsd5TBImU2nVcpIzZQs4TNAkpav + hM4HsYmwlZRjZGJaCr2fd9wTPfF1EeD1RHJdEHVJZk7PylacT81g6W2Q1jBOIs89cd4wJKYb4Onowc7u + /g/znZ+V41o+cBwJls59A4OScc3SuUVK2IwV7iciNCJGJa6A+xGw2IoxJuifnu1chwXX9gENOTr0rFSr + ljyrlAxRSE7LVGU3G/WHSWlKGaeE1PWNTa8aFW8tcmMWIIrsCdhmJgqFSp2VKpG1S81ERXR6o/QObpmV + 7lwrbJ621o1ZgIhtyAzUIeMUNvysk+gX45NTEpXKVA/dKjUTB7veouvNvhu1wKNHj2TgVaMqTzr00sqq + ZOohWAvsMvcxqcqVClyH8/9TC1C4hkYXcsy5UuR9U6BXHJs9NBXolM6NXZs3yHq750YtQOFIkzxrobLA + wtIKevoHlGMbTWYp9HrVWcGNWuBnStjzruHhBWeqBZLEaAG2k6yJciQSGU0W6doG8VK6tZt85o1agMPX + ETkIcTgrpCpt/WaBfxTgRGJEpnycXNyoBW7yZmwJp2dmUFFVoyxABdjQs7wgjcblvIFKsnm5bDG7czG/ + aNO+M6cSN6kAH7YstGmUJsYtraZmgWyhT76tQA5MJtWkmUqctThLZZbmWIZFona6qSnxP1eAD9iSUNoq + lWlbR9c3HxAnzpGzBU7yeM7F00meQGqLjn8oc1UeKtI/OJahAhxTHrfAuf2At+HK230UkB0Zub+0vKrq + o1yrDYX2IpmPDqkjK558asepPPijEgwAtAppSMG1PkFzeK+OWW+CTkRyfHxCDXMXFpel8R8Q+hSiQCzA + ARjP3Th+4RkCEx+FJ61IHaJ+EV2uNZnz1gLkMc8LRscmML+4pCxA+ljFBziG5BkblaAFqCzpoiF+Gdpn + yXCjYZQIEcU1ociUjFQ4S6UFCoQ+eTKO5xkyDwp54qnNUf/vLeVpVKjEY/lLwoxMpKdlrNjT26foYxML + tLS0YEbCLP1EG59f9DcCb6x+4xagAvsi4NTUtByGd6JGjmoL7XZ1CMhzZtZLpM11kdf84UbLaSJGRDla + XyT/JYk1y3myR5Cn8KSNds57XeS/z0a9/VvLVfYxkvB/DdofRfhfCcZ47cDuKve6bO9/AQS0G5E7BnTw + AAAAAElFTkSuQmCC + + + + + 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 + XmlnU6d2ATQzdW+YrQN146KbnBb9YfH60tXTgERelafFj6aRjphuFWe7rNZ+3Z1YKZV0j5r3unLDrEXS + splNsS5nao70toWW06251vPRJR6LQAAEQAAEQAAEQAAEQCCEwAdvJl7skTF2UQAAAABJRU5ErkJggg== + + + + + AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/39/f/6Ojo/9fX1//Q0ND/2dnZ/+rq6v/39/f/+/v7//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz//Pz8//z8/P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//r6+v/s6+v/0tHR/7++vv+ysrH/tLSz/8nJ + yf/k5OT/8/Pz//n5+f/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i4uH/y8rK/7m4 + uP+qqqn/nJyb/6mpqf/Jycn/4eHh//Hx8f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//n5 + +f/e3t3/zs3M/83My/++vbz/nJua/5qZmf+0tLT/zMzM/+Li4v/y8vL/+fn5//r6+v/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//T09P/X19b/zMrK/8/OzP/Av73/nZya/5eWlv+rq6v/vLy8/8/Pz//k5OT/8vLy//j4 + +P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7/+/v7//R0ND/yMbF/9LRz//BwL7/nJuZ/5qZmP+xsbH/vb29/8jI + yP/Y2Nj/5+fn//Hx8f/29vb/+Pj4//r6+v/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+fn5//Ix8f/xMLB/9PR0P/Av73/m5mX/5yb + mv+5ubn/yMjI/8rKyv/S0tL/29vb/+Tk5P/r6+v/8PDw//T09P/39/f/+Pj4//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/+Li4v/CwL//wL68/9XT + 0v/BwL7/mZiV/52cm//CwsH/1tbW/9fX1//Y2Nj/3Nzc/+Dg4P/k5OT/6enp/+7u7v/y8vL/9vb2//j4 + +P/5+fn/+vr6//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/9vb + 2v+4trX/uri2/9TT0f/Av7z/lZSR/5ybmf/Gxsb/4uLi/+Pj4//j4+P/4+Pj/+Tk5P/l5eX/5+fn/+rq + 6v/t7e3/8fHx//T09P/29vb/9/f3//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/9/f3/9TT0/+xr67/trSy/9TS0P/Avrz/lJKP/5qZl//JyMj/6+vr/+7u7v/u7u7/7u7u/+7u + 7v/u7u7/7u7u/+/v7//w8PD/8fHx//Pz8//19fX/9vb2//f39//4+Pj/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/8vLy/8zMy/+pp6X/tLGv/9TS0P+/vrv/k5GO/5iWlP/IyMf/7u7u//X1 + 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/29vb/9/f3//j4+P/4+Pj/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/7u7u/8XFxP+lo6H/tbKw/9TS0P/Avrz/lpSR/5eV + k//GxcT/7Ozs//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/6enp/728vP+fnJr/tLGv/9TT + 0f/Avrz/lpSR/5SSkP/BwMD/6urq//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/5OTk/7a1 + tf+bmJb/tLKv/9TS0P/Av7z/mJaU/5OSkP+9vbz/5ubm//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/4eHh/6+urf+Vk5H/tLGv/9XU0v/BwL3/mZeU/5KQjv+6urn/5OTk//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/29vb/6mop/+SkI3/tLKv/9XU0v/Cwb//nJqY/5KQjv+4t7b/4eHh//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/2dnY/6Ojof+PjYr/t7Sy/9rZ1//Kycf/oqCe/5OR + j/+2tbX/4eHh//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/1NTU/5+enP+IhYL/pqOg/8XD + wP+7ubf/npuY/5CNiv+ysK//3t3d//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//39/f/z87N/5iW + lP96d3T/i4eE/56bmP+WlJD/h4N//4J+ev+ppqP/2djX//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/s7Ov/wcC+/5OQjf95dnL/fXp2/4J+ev98eHT/cm5p/3hzbf+emZT/y8jG//Dw8P/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//b29v/a2df/tLKv/4+MiP+IhYH/jYmG/46Khv9+e3f/b2tm/3Vwav+OiIL/vLiz/+Hf + 3v/4+Pj/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+Pj4/+jn5v/GxML/pKGe/5ORjv+XlJH/n5yZ/56bl/+LiIT/dXJt/3Ju + aP+CfXb/pJ+Z/8vIxP/t7Ov/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/8/Pz/9bV0/+4trP/n5yZ/5yZl/+joJ7/rqun/6uo + pP+Vko7/fHl0/3BsaP98d3D/k42F/7q1r//a2db/9vb2//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/39/f/4+Lh/8XDwf+qp6T/op+c/6Gg + nv+tq6n/uLWy/7KvrP+cmZX/gX56/29saP9zb2n/h4F5/6KclP/Fwb3/5+bl//j4+P/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/u7u3/0c/O/7i1 + s/+opaP/pqSi/6qopv+4trT/wL68/7i2sv+ioJz/iIWB/3Fva/9tamT/f3py/5ONhP+yrqf/0c/M//Hx + 8P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//X0 + 9P/c29r/w8G//66rqf+rqaj/qaim/7OysP/CwL//ycfE/768uP+ppqL/jouH/3Rybv9pZmL/dHBq/4qE + fP+emJD/vbm0/9/e3P/29vb/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5/+np6P/OzMr/uLaz/7CurP+vr63/sK+u/7+9vP/Ny8r/0c/N/8XDwP+xr6v/l5SR/3x6 + dv9raWX/bmtm/4R/eP+Wj4f/rKeg/8nGw//t7Oz/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/8/Ly/9fW1P/Bv73/s7Gv/7Szsv+xsbD/uLi3/8nIx//X1dT/2NbU/8zK + x/+5trP/npyY/4KAff9ua2j/aGZh/3l1b/+QiYH/nZeO/7ezrv/Y1tT/9fX1//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/49/f/4+Lh/8nHxf+3tLL/trSz/7a1tP+1tbX/wcHB/9PS + 0v/f3tz/3NvZ/9HQzf/Avrv/p6Si/4uIhv90cW7/aWdj/3Juaf+KhHz/mZKJ/6ehmf/Cvrv/5+bl//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//v7u7/0M/N/7u5tv+zsq//uLe2/7a2 + tf+7urr/ysrK/93d3P/m5uX/4eDf/9fW1P/HxsP/r62q/5KQjf95d3T/amhk/2poY/9/enT/lo+G/56W + jv+xrKb/z83L//Ly8v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//X19f/a2dj/wb68/7Cu + q/+0srH/tbW0/7e3t//AwMD/09PT/+Tl5P/q6un/5eTi/9zb2f/NzMr/t7Wz/5uZlv+Afnz/bmxp/2ln + Y/91cmz/j4mB/52WjP+hm5P/uray/9/e3P/39/f/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+vr6/+jn + 5//GxML/sK2q/6yqp/+ysbD/s7Oy/7m5uf/Hx8f/3Nzc/+3t7f/v7+7/6eno/+Hg3//U09H/v767/6Oh + n/+HhYP/cnBu/2lnY/9tamb/hH94/5qTi/+el43/qKOd/8bDwP/u7e3/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/8vHx/8/OzP+zsK7/o6Gd/6qopv+srKr/sbGx/7q6uv/Nzc3/5OTk//Ly8v/x8fH/7Ovr/+Xk + 4//a2Nf/x8XD/6yqqP+Pjoz/eXd1/2xqZ/9raGT/enZx/5SNhv+hmZD/nZaO/7Ouqv/W1NP/9vb1//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//4+Pj/3t3c/7q3tf+fnJj/npuY/6SioP+op6b/sLCv/7y9vP/U1NT/7Ozs//f3 + 9//19fT/8PDv/+rp6P/g393/zs3L/7SysP+XlZP/fn16/25tav9pZ2T/cW5p/4mEff+fmI//oJiP/6Kc + lf++urf/6Ofm//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/r6+r/w8G+/6Kem/+TkIz/mZeU/5ybmf+ko6L/rq6t/7/A + v//Z2tn/8PDw//j4+P/29vb/8vHx/+zs6//j4+H/1NPR/7y6uf+fnZz/hYSC/3RycP9ramf/bWpm/396 + df+Ykor/pZ2U/5uUi/+rpqH/zcvJ//Ly8v/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//X19f/T0tD/qqik/42Khf+Niob/kY+M/5eW + lP+hoJ//ra2s/8PEw//f4N//9PT0//r6+v/4+Pj/9fX1//Dw7//p6ef/29rZ/8TCwf+npaT/jIqI/3h3 + df9ubGr/bGlm/3Zybf+PiYL/pJ2U/6Oakf+clo7/trOv/+Dg3v/5+fn/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+Pj4/+Pi4f+1s7D/j4uG/4F+ + ef+Gg3//ioiE/5ORj/+fnpz/sK+u/8rKyv/l5eT/9PT0//j4+P/4+Pj/9vb2//Ly8f/r6+r/397d/8nI + x/+sq6r/kY+O/317ev9xb23/bWpo/3Btaf+Ef3n/nJaN/6mhl/+ak4r/o56Y/8PBvv/u7u3/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/8fHw/8bF + w/+ZlpL/e3dx/3p2cv98enb/g4F+/4+Niv+enJr/tLOy/9HQ0P/m5+b/7u7u//Dw8P/x8fH/8fHx/+/v + 7//r6+r/4uHg/9DPzv+4trb/n56d/4yKif9+fHv/dXRx/3Nwbf99eXT/lI+H/6mhl/+lnZL/l5GJ/66r + pv/Y19b/9/f3//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/29vb/2NfV/6Win/96dnH/b2xm/3Nxbf94dnP/gYB9/42Miv+bmpn/sK+u/8XExP/Q0ND/0tLR/9DQ + 0P/S0tL/09PT/9TU1P/T09P/0NDP/8fHxv+6ubn/rKuq/5+enf+Uk5L/i4qI/4WEgv+FgoD/ko6J/5+Z + kv+jnJP/kIqC/5WQi/+4trP/6Ojn//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//f39//m5eX/t7a1/4mGg/9wbWr/dnRx/359e/+Ih4X/kZGP/5iYl/+enZ3/pKOj/6mp + qf+pqan/pKSk/6Ghof+hoaH/o6Oj/6Wlpf+oqKj/qqqq/6qqqv+oqKj/pKSk/6Cfn/+ampr/lZWU/5GR + kP+Pjo3/kZCO/5aUkP+Wk47/iYWB/397d/+bmZb/xcTD/+vr6//29vb/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/4+Pj/8PDw/9ra2v+9vLz/oqGg/4yLif+Mi4n/lZST/52dnP+kpKT/qamp/6io + p/+hoaH/mJiY/46Ojv+FhYX/fX19/3l5ef93d3f/eHh4/3t7e/+AgID/hYWF/4mJif+MjIz/jY2N/42N + jf+MjIz/jIyM/46Ojv+QkJD/kJCQ/4+Pj/+OjYz/iYiG/358e/+Af37/mZmY/7e3t//V1dX/7u7u//j4 + +P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/09PT/2NjY/7e3t/+oqKj/qqqq/7Kxsf+5ubn/u7u7/7y8 + vP+9vb3/urq6/7Kysv+kpKT/lJSU/4SEhP93d3f/bm5u/2lpaf9oaGj/aWlp/21tbf9ycnL/eHh4/35+ + fv+BgYH/goKC/4KCgv+BgYH/goKC/4aGhv+Li4v/kJCQ/5OTk/+Tk5P/kJCQ/4aGhv98fHz/eXl5/4OD + g/+lpaX/0NDQ//Pz8//5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/w8PD/ycnJ/6Wlpf+np6f/yMjI/9bW + 1v/U1NT/z8/P/8nJyf/ExMT/vr6+/7a2tv+pqan/mpqa/4yMjP+BgYH/enp6/3h4eP94eHj/e3t7/4CA + gP+FhYX/ioqK/46Ojv+QkJD/kJCQ/4+Pj/+Ojo7/j4+P/5KSkv+Wlpb/mJiY/5iYmP+Wlpb/kpKS/4uL + i/+AgID/cnJy/2ZmZv+BgYH/v7+//+3t7f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/y8vL/0NDQ/7m5 + uf+4uLj/zs7O/9bW1v/W1tb/0dHR/8rKyv/FxcX/v7+//7i4uP+wsLD/pqam/52dnf+Wlpb/lJSU/5WV + lf+ZmZn/n5+f/6enp/+tra3/srKy/7a2tv+3t7f/tbW1/7Kysv+urq7/rKys/6qqqv+oqKj/pKSk/5+f + n/+YmJj/kJCQ/4eHh/+AgID/eXl5/3l5ef+YmJj/x8fH//Dw8P/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//5+fn/7Ozs/9XV1f/Pz8//0NDQ/87Ozv/Jycn/xcXF/8DAwP+9vb3/urq6/7a2tv+ysrL/ra2t/6io + qP+mpqb/pqam/6urq/+ysrL/vLy8/8fHx//R0dH/2dnZ/9/f3//g4OD/3Nzc/9XV1f/Ozs7/xsbG/76+ + vv+1tbX/qqqq/6CgoP+Xl5f/kpKS/5GRkf+VlZX/nZ2d/6ysrP/Gxsb/6Ojo//j4+P/7+/v/+/v7//v7 + +//5+fn/+fn5//n5+f/6+vr/+Pj4//Ly8v/n5+f/3d3d/9fX1//Q0ND/ysrK/8XFxf/BwcH/vb29/7q6 + uv+2trb/srKy/6+vr/+urq7/sLCw/7W1tf+8vLz/xsbG/9LS0v/d3d3/5ubm/+3t7f/u7u7/6enp/+Hh + 4f/Y2Nj/z8/P/8fHx/++vr7/tra2/7Gxsf+vr6//sbGx/7e3t//CwsL/z8/P/+Dg4P/w8PD/+Pj4//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/9vb2/+7u7v/m5ub/4uLi/97e + 3v/a2tr/1tbW/9LS0v/Q0ND/zc3N/8vLy//Kysr/y8vL/8/Pz//U1NT/2tra/+Dg4P/n5+f/7Ozs/+/v + 7//v7+//7Ozs/+fn5//i4uL/3d3d/9nZ2f/V1dX/1NTU/9XV1f/Y2Nj/3Nzc/+Pj4//t7e3/9vb2//r6 + +v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz/+/v7//n5+f/29vb/8vLy//Dw8P/u7u7/7e3t/+zs7P/s7Oz/7Ozs/+3t7f/u7u7/8PDw//Ly + 8v/09PT/9fX1//b29v/19fX/9PT0//Pz8//x8fH/8PDw//Dw8P/w8PD/8vLy//X19f/5+fn/+/v7//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P8AAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQ= + + + \ No newline at end of file diff --git a/OpenCLFilter/ImageData.cs b/OpenCLFilter/ImageData.cs new file mode 100644 index 0000000..4dd0068 --- /dev/null +++ b/OpenCLFilter/ImageData.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; +using OpenCLTemplate; + +namespace OpenCLFilter +{ + /// Stores image data in OpenCL memory + public class ImageData + { + /// Pixel size + private const int PIXELSIZE = 3; + + /// OpenCL byte array that stores the image data + public CLCalc.Program.Variable varData; + /// Host memory image data + public byte[] Data; + + private int width, height; + + /// Gets image width + public int Width + { + get { return width; } + } + + /// Gets image height + public int Height + { + get { return height; } + } + + /// ImageData constructor. Reads data from a bitmap + /// Bitmap to read from + public ImageData(Bitmap bmp) + { + if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.Unknown) CLCalc.InitCL(); + + width = bmp.Width; + height = bmp.Height; + + //Allocates space for data + Data = new byte[3 * width * height]; + + //Reads bmp to local Data variable + ReadToLocalData(bmp); + + //Transfer data to OpenCL device + varData = new CLCalc.Program.Variable(Data); + } + + /// Reads data from a bitmap. + /// Source bitmap + public void ReadBmp(Bitmap bmp) + { + ReadToLocalData(bmp); + varData.WriteToDevice(Data); + } + + /// Returns stored data in a bitmap + /// Reference bitmap + public Bitmap GetStoredBitmap(Bitmap bmp) + { + Bitmap resp = new Bitmap(width, height, bmp.PixelFormat); + + BitmapData bmd = resp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), + System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat); + + //Write data + unsafe + { + for (int y = 0; y < bmd.Height; y++) + { + byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride); + + for (int x = 0; x < bmd.Width; x++) + { + row[x * PIXELSIZE] = Data[3 * (x + width * y)]; + row[x * PIXELSIZE + 1] = Data[3 * (x + width * y) + 1]; + row[x * PIXELSIZE + 2] = Data[3 * (x + width * y) + 2]; + } + } + } + + //Unlock bits + resp.UnlockBits(bmd); + + return resp; + } + + /// Copies bitmap data to local Data + /// Bitmap to copy + private void ReadToLocalData(Bitmap bmp) + { + //Lock bits + BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), + System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat); + //Read data + unsafe + { + for (int y = 0; y < bmd.Height; y++) + { + byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride); + + for (int x = 0; x < bmd.Width; x++) + { + Data[3 * (x + width * y)] = row[x * PIXELSIZE]; + Data[3 * (x + width * y) + 1] = row[x * PIXELSIZE + 1]; + Data[3 * (x + width * y) + 2] = row[x * PIXELSIZE + 2]; + } + } + } + + //Unlock bits + bmp.UnlockBits(bmd); + } + } +} diff --git a/OpenCLFilter/OpenCLFilter.csproj b/OpenCLFilter/OpenCLFilter.csproj new file mode 100644 index 0000000..13fe873 --- /dev/null +++ b/OpenCLFilter/OpenCLFilter.csproj @@ -0,0 +1,165 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E40C284E-CF7A-4208-B586-C56E3D6DA194} + WinExe + Properties + OpenCLFilter + OpenCLFilter + v3.5 + 512 + filter.ico + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + true + + + + False + ..\AForge.dll + + + False + ..\AForge.Video.dll + + + False + ..\AForge.Video.DirectShow.dll + + + False + ..\OpenCL.NET.dll + + + False + ..\OpenCLTemplate.dll + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + Form + + + Form1.cs + + + Form + + + frmCfgFilter.cs + + + + + + Form1.cs + + + frmCfgFilter.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/OpenCLFilter/OpenCLFilter.csproj.user b/OpenCLFilter/OpenCLFilter.csproj.user new file mode 100644 index 0000000..2e1cf71 --- /dev/null +++ b/OpenCLFilter/OpenCLFilter.csproj.user @@ -0,0 +1,13 @@ + + + + + + + + + + de-DE + false + + \ No newline at end of file diff --git a/OpenCLFilter/Program.cs b/OpenCLFilter/Program.cs new file mode 100644 index 0000000..081d222 --- /dev/null +++ b/OpenCLFilter/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace OpenCLFilter +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmMainFilter()); + } + } +} diff --git a/OpenCLFilter/Properties/AssemblyInfo.cs b/OpenCLFilter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..dd11cb5 --- /dev/null +++ b/OpenCLFilter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenCLFilter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("OpenCLFilter")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e6ff6ed6-ad02-47a5-99e2-a2f233b4b0e1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenCLFilter/Properties/Resources.Designer.cs b/OpenCLFilter/Properties/Resources.Designer.cs new file mode 100644 index 0000000..b49a3ff --- /dev/null +++ b/OpenCLFilter/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.1 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace OpenCLFilter.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenCLFilter.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/OpenCLFilter/Properties/Resources.resx b/OpenCLFilter/Properties/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/OpenCLFilter/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/OpenCLFilter/Properties/Settings.Designer.cs b/OpenCLFilter/Properties/Settings.Designer.cs new file mode 100644 index 0000000..f958495 --- /dev/null +++ b/OpenCLFilter/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.1 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace OpenCLFilter.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/OpenCLFilter/Properties/Settings.settings b/OpenCLFilter/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/OpenCLFilter/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/OpenCLFilter/filter.ico b/OpenCLFilter/filter.ico new file mode 100644 index 0000000..14a594a Binary files /dev/null and b/OpenCLFilter/filter.ico differ diff --git a/OpenCLFilter/frmCfgFilter.Designer.cs b/OpenCLFilter/frmCfgFilter.Designer.cs new file mode 100644 index 0000000..ffafd4e --- /dev/null +++ b/OpenCLFilter/frmCfgFilter.Designer.cs @@ -0,0 +1,392 @@ +namespace OpenCLFilter +{ + partial class frmCfgFilter + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmCfgFilter)); + this.label1 = new System.Windows.Forms.Label(); + this.tabCtrl = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.gbR = new System.Windows.Forms.GroupBox(); + this.txtRCode = new System.Windows.Forms.TextBox(); + this.lblAmpR = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.btnNormR = new System.Windows.Forms.Button(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.gbG = new System.Windows.Forms.GroupBox(); + this.txtGCode = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.lblAmpG = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.btnNormG = new System.Windows.Forms.Button(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.gbB = new System.Windows.Forms.GroupBox(); + this.txtBCode = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.lblAmpB = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.btnNormB = new System.Windows.Forms.Button(); + this.btnCopy = new System.Windows.Forms.Button(); + this.btnClear = new System.Windows.Forms.Button(); + this.tabCtrl.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.gbR.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.gbG.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.gbB.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(397, 112); + this.label1.TabIndex = 0; + this.label1.Text = resources.GetString("label1.Text"); + // + // tabCtrl + // + this.tabCtrl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabCtrl.Controls.Add(this.tabPage1); + this.tabCtrl.Controls.Add(this.tabPage3); + this.tabCtrl.Controls.Add(this.tabPage2); + this.tabCtrl.Location = new System.Drawing.Point(12, 129); + this.tabCtrl.Name = "tabCtrl"; + this.tabCtrl.SelectedIndex = 0; + this.tabCtrl.Size = new System.Drawing.Size(397, 314); + this.tabCtrl.TabIndex = 2; + this.tabCtrl.Leave += new System.EventHandler(this.txtCode_Leave); + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.gbR); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(389, 288); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Red filter"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // gbR + // + this.gbR.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gbR.Controls.Add(this.txtRCode); + this.gbR.Controls.Add(this.lblAmpR); + this.gbR.Controls.Add(this.label8); + this.gbR.Controls.Add(this.label2); + this.gbR.Controls.Add(this.btnNormR); + this.gbR.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gbR.ForeColor = System.Drawing.Color.Red; + this.gbR.Location = new System.Drawing.Point(6, 6); + this.gbR.Name = "gbR"; + this.gbR.Size = new System.Drawing.Size(372, 276); + this.gbR.TabIndex = 2; + this.gbR.TabStop = false; + this.gbR.Text = "Red filter"; + // + // txtRCode + // + this.txtRCode.Location = new System.Drawing.Point(83, 240); + this.txtRCode.Name = "txtRCode"; + this.txtRCode.Size = new System.Drawing.Size(283, 20); + this.txtRCode.TabIndex = 5; + this.txtRCode.Leave += new System.EventHandler(this.txtCode_Leave); + // + // lblAmpR + // + this.lblAmpR.AutoSize = true; + this.lblAmpR.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.lblAmpR.Location = new System.Drawing.Point(247, 206); + this.lblAmpR.Name = "lblAmpR"; + this.lblAmpR.Size = new System.Drawing.Size(16, 15); + this.lblAmpR.TabIndex = 4; + this.lblAmpR.Text = "1"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(6, 243); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(71, 13); + this.label8.TabIndex = 4; + this.label8.Text = "Filter code:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(144, 206); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(97, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Filter amplitude:"; + // + // btnNormR + // + this.btnNormR.Location = new System.Drawing.Point(6, 201); + this.btnNormR.Name = "btnNormR"; + this.btnNormR.Size = new System.Drawing.Size(132, 23); + this.btnNormR.TabIndex = 3; + this.btnNormR.Text = "Normalize filter"; + this.btnNormR.UseVisualStyleBackColor = true; + this.btnNormR.Click += new System.EventHandler(this.btnNorm_Click); + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.gbG); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(389, 288); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Green filter"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // gbG + // + this.gbG.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gbG.Controls.Add(this.txtGCode); + this.gbG.Controls.Add(this.label9); + this.gbG.Controls.Add(this.lblAmpG); + this.gbG.Controls.Add(this.label7); + this.gbG.Controls.Add(this.btnNormG); + this.gbG.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gbG.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0))))); + this.gbG.Location = new System.Drawing.Point(6, 6); + this.gbG.Name = "gbG"; + this.gbG.Size = new System.Drawing.Size(372, 279); + this.gbG.TabIndex = 4; + this.gbG.TabStop = false; + this.gbG.Text = "Green filter"; + // + // txtGCode + // + this.txtGCode.Location = new System.Drawing.Point(83, 240); + this.txtGCode.Name = "txtGCode"; + this.txtGCode.Size = new System.Drawing.Size(283, 20); + this.txtGCode.TabIndex = 7; + this.txtGCode.Leave += new System.EventHandler(this.txtCode_Leave); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(6, 243); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(71, 13); + this.label9.TabIndex = 6; + this.label9.Text = "Filter code:"; + // + // lblAmpG + // + this.lblAmpG.AutoSize = true; + this.lblAmpG.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.lblAmpG.Location = new System.Drawing.Point(247, 206); + this.lblAmpG.Name = "lblAmpG"; + this.lblAmpG.Size = new System.Drawing.Size(16, 15); + this.lblAmpG.TabIndex = 4; + this.lblAmpG.Text = "1"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(144, 206); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(97, 13); + this.label7.TabIndex = 4; + this.label7.Text = "Filter amplitude:"; + // + // btnNormG + // + this.btnNormG.Location = new System.Drawing.Point(6, 201); + this.btnNormG.Name = "btnNormG"; + this.btnNormG.Size = new System.Drawing.Size(132, 23); + this.btnNormG.TabIndex = 3; + this.btnNormG.Text = "Normalize filter"; + this.btnNormG.UseVisualStyleBackColor = true; + this.btnNormG.Click += new System.EventHandler(this.btnNorm_Click); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.gbB); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(389, 288); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Blue filter"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // gbB + // + this.gbB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gbB.Controls.Add(this.txtBCode); + this.gbB.Controls.Add(this.label10); + this.gbB.Controls.Add(this.lblAmpB); + this.gbB.Controls.Add(this.label5); + this.gbB.Controls.Add(this.btnNormB); + this.gbB.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gbB.ForeColor = System.Drawing.Color.Blue; + this.gbB.Location = new System.Drawing.Point(6, 6); + this.gbB.Name = "gbB"; + this.gbB.Size = new System.Drawing.Size(377, 276); + this.gbB.TabIndex = 3; + this.gbB.TabStop = false; + this.gbB.Text = "Blue filter"; + // + // txtBCode + // + this.txtBCode.Location = new System.Drawing.Point(83, 240); + this.txtBCode.Name = "txtBCode"; + this.txtBCode.Size = new System.Drawing.Size(283, 20); + this.txtBCode.TabIndex = 7; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(6, 243); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(71, 13); + this.label10.TabIndex = 6; + this.label10.Text = "Filter code:"; + // + // lblAmpB + // + this.lblAmpB.AutoSize = true; + this.lblAmpB.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.lblAmpB.Location = new System.Drawing.Point(247, 206); + this.lblAmpB.Name = "lblAmpB"; + this.lblAmpB.Size = new System.Drawing.Size(16, 15); + this.lblAmpB.TabIndex = 4; + this.lblAmpB.Text = "1"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(144, 206); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(97, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Filter amplitude:"; + // + // btnNormB + // + this.btnNormB.Location = new System.Drawing.Point(6, 201); + this.btnNormB.Name = "btnNormB"; + this.btnNormB.Size = new System.Drawing.Size(132, 23); + this.btnNormB.TabIndex = 3; + this.btnNormB.Text = "Normalize filter"; + this.btnNormB.UseVisualStyleBackColor = true; + this.btnNormB.Click += new System.EventHandler(this.btnNorm_Click); + // + // btnCopy + // + this.btnCopy.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnCopy.Location = new System.Drawing.Point(12, 449); + this.btnCopy.Name = "btnCopy"; + this.btnCopy.Size = new System.Drawing.Size(203, 40); + this.btnCopy.TabIndex = 3; + this.btnCopy.Text = "Copy red filter to green and blue filters"; + this.btnCopy.UseVisualStyleBackColor = true; + this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click); + // + // btnClear + // + this.btnClear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnClear.Location = new System.Drawing.Point(221, 449); + this.btnClear.Name = "btnClear"; + this.btnClear.Size = new System.Drawing.Size(188, 40); + this.btnClear.TabIndex = 3; + this.btnClear.Text = "Clear all"; + this.btnClear.UseVisualStyleBackColor = true; + this.btnClear.Click += new System.EventHandler(this.btnClear_Click); + // + // frmCfgFilter + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(421, 492); + this.Controls.Add(this.btnClear); + this.Controls.Add(this.btnCopy); + this.Controls.Add(this.tabCtrl); + this.Controls.Add(this.label1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "frmCfgFilter"; + this.Text = "Filter Configuration"; + this.Load += new System.EventHandler(this.frmCfgFilter_Load); + this.tabCtrl.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.gbR.ResumeLayout(false); + this.gbR.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.gbG.ResumeLayout(false); + this.gbG.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.gbB.ResumeLayout(false); + this.gbB.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TabControl tabCtrl; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.GroupBox gbR; + private System.Windows.Forms.Label lblAmpR; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button btnNormR; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.GroupBox gbB; + private System.Windows.Forms.Label lblAmpB; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Button btnNormB; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.GroupBox gbG; + private System.Windows.Forms.Label lblAmpG; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button btnNormG; + private System.Windows.Forms.Button btnCopy; + private System.Windows.Forms.Button btnClear; + private System.Windows.Forms.TextBox txtRCode; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox txtGCode; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox txtBCode; + private System.Windows.Forms.Label label10; + } +} \ No newline at end of file diff --git a/OpenCLFilter/frmCfgFilter.cs b/OpenCLFilter/frmCfgFilter.cs new file mode 100644 index 0000000..9a74b18 --- /dev/null +++ b/OpenCLFilter/frmCfgFilter.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace OpenCLFilter +{ + public partial class frmCfgFilter : Form + { + public frmCfgFilter() + { + InitializeComponent(); + } + + int FilterSize = 7; + TextBox[] txtR, txtG, txtB; + + /// Returns red, green and blue filters. + public float[] GetFilters() + { + float[] Filters = new float[3 * FilterSize * FilterSize]; + + for (int i = 0; i < FilterSize; i++) + { + for (int j = 0; j < FilterSize; j++) + { + float r, g, b; + float.TryParse(txtR[i * FilterSize + j].Text, out r); + float.TryParse(txtG[i * FilterSize + j].Text, out g); + float.TryParse(txtB[i * FilterSize + j].Text, out b); + + Filters[3*(i * FilterSize + j)] = r; //red component + Filters[3*(i * FilterSize + j)+1] = g; //green + Filters[3*(i * FilterSize + j)+2] = b; //blue + } + } + + return Filters; + } + + #region Textboxes management + private void frmCfgFilter_Load(object sender, EventArgs e) + { + txtR = new TextBox[FilterSize * FilterSize]; + txtG = new TextBox[FilterSize * FilterSize]; + txtB = new TextBox[FilterSize * FilterSize]; + + float[] gaussian = new float[] + { + 0,0, 0, 0, 0,0,0, + 0,2, 4, 5, 4,2,0, + 0,4, 9,12, 9,4,0, + 0,5,12,15,12,5,0, + 0,4, 9,12, 9,4,0, + 0,2, 4, 5, 4,2,0, + 0,0, 0, 0, 0,0,0 + }; + for (int i = 0; i < gaussian.Length; i++) gaussian[i] /= 159; + + for (int i = 0; i < FilterSize; i++) + { + for (int j = 0; j < FilterSize; j++) + { + txtR[i * FilterSize + j] = new TextBox(); + txtR[i * FilterSize + j].Width = 45; txtR[i * FilterSize + j].Top = 19 + 26 * i; + txtR[i * FilterSize + j].Left = 6 + 50 * j; + txtR[i * FilterSize + j].Text = gaussian[i * FilterSize + j].ToString(); + txtR[i * FilterSize + j].Font = new Font("Arial", 9, FontStyle.Regular); + txtR[i * FilterSize + j].Leave += new EventHandler(frmCfgFilter_Leave); + gbR.Controls.Add(txtR[i * FilterSize + j]); + + txtG[i * FilterSize + j] = new TextBox(); + txtG[i * FilterSize + j].Width = 45; txtG[i * FilterSize + j].Top = 19 + 26 * i; + txtG[i * FilterSize + j].Left = 6 + 50 * j; + txtG[i * FilterSize + j].Text = gaussian[i * FilterSize + j].ToString(); + txtG[i * FilterSize + j].Font = new Font("Arial", 9, FontStyle.Regular); + txtG[i * FilterSize + j].Leave += new EventHandler(frmCfgFilter_Leave); + gbG.Controls.Add(txtG[i * FilterSize + j]); + + txtB[i * FilterSize + j] = new TextBox(); + txtB[i * FilterSize + j].Width = 45; txtB[i * FilterSize + j].Top = 19 + 26 * i; + txtB[i * FilterSize + j].Left = 6 + 50 * j; + txtB[i * FilterSize + j].Text = gaussian[i * FilterSize + j].ToString(); + txtB[i * FilterSize + j].Font = new Font("Arial", 9, FontStyle.Regular); + txtB[i * FilterSize + j].Leave += new EventHandler(frmCfgFilter_Leave); + gbB.Controls.Add(txtB[i * FilterSize + j]); + + } + } + + WriteCodes(); + } + + void frmCfgFilter_Leave(object sender, EventArgs e) + { + TextBox t = (TextBox)sender; + float x; + float.TryParse(t.Text, out x); + t.Text = x.ToString(); + WriteCodes(); + } + + /// Writes filter codes to textbox to make them easier to retrieve + void WriteCodes() + { + string sR = "", sG = "", sB = ""; + for (int i = 0; i < FilterSize; i++) + { + for (int j = 0; j < FilterSize; j++) + { + sR += txtR[i * FilterSize + j].Text; + sG += txtG[i * FilterSize + j].Text; + sB += txtB[i * FilterSize + j].Text; + if (j != FilterSize - 1) + { + sR += " "; + sG += " "; + sB += " "; + } + } + if (i != FilterSize - 1) + { + sR += ";"; + sG += ";"; + sB += ";"; + } + } + txtRCode.Text = sR; + txtGCode.Text = sG; + txtBCode.Text = sB; + + CalcMagnitudes(); + } + + /// Reads filter codes from textbox + void ReadCodes() + { + string[] sR = txtRCode.Text.Split(';'); + string[] sG = txtRCode.Text.Split(';'); + string[] sB = txtRCode.Text.Split(';'); + if (sR.Length != FilterSize && sG.Length != FilterSize || sB.Length != FilterSize) + { + MessageBox.Show("Filter should have "+FilterSize.ToString() +" rows"); + WriteCodes(); + return; + } + + //Check columns + for (int i = 0; i < FilterSize; i++) + { + string[] sR2 = sR[i].Split(); + string[] sG2 = sG[i].Split(); + string[] sB2 = sB[i].Split(); + if (sR2.Length != FilterSize && sG2.Length != FilterSize || sB2.Length != FilterSize) + { + MessageBox.Show("Filter should have " + FilterSize.ToString() + " columns in each row"); + WriteCodes(); + return; + } + } + + //Parse filter + for (int i = 0; i < FilterSize; i++) + { + string[] sR2 = sR[i].Split(); + string[] sG2 = sR[i].Split(); + string[] sB2 = sR[i].Split(); + for (int j = 0; j < FilterSize; j++) + { + float r, g, b; + float.TryParse(sR2[j], out r); + float.TryParse(sG2[j], out g); + float.TryParse(sB2[j], out b); + txtR[i * FilterSize + j].Text = r.ToString(); + txtG[i * FilterSize + j].Text = g.ToString(); + txtB[i * FilterSize + j].Text = b.ToString(); + } + } + + CalcMagnitudes(); + } + + /// Returns magnitudes of the filters + private float[] CalcMagnitudes() + { + float[] resp = new float[3]; + + for (int i = 0; i < FilterSize; i++) + { + for (int j = 0; j < FilterSize; j++) + { + float r, g, b; + float.TryParse(txtR[i * FilterSize + j].Text, out r); + float.TryParse(txtG[i * FilterSize + j].Text, out g); + float.TryParse(txtB[i * FilterSize + j].Text, out b); + + resp[0] += r; resp[1] += g; resp[2] += b; + } + } + + lblAmpR.Text = resp[0].ToString(); + lblAmpG.Text = resp[1].ToString(); + lblAmpB.Text = resp[2].ToString(); + + return resp; + } + + private void txtCode_Leave(object sender, EventArgs e) + { + ReadCodes(); + } + + private void btnCopy_Click(object sender, EventArgs e) + { + txtGCode.Text = txtRCode.Text; + txtBCode.Text = txtRCode.Text; + ReadCodes(); + } + + private void btnClear_Click(object sender, EventArgs e) + { + string s = "0 0 0 0 0 0 0;0 0 0 0 0 0 0;0 0 0 0 0 0 0;0 0 0 1 0 0 0;0 0 0 0 0 0 0;0 0 0 0 0 0 0;0 0 0 0 0 0 0"; + txtRCode.Text = s; + txtGCode.Text = txtRCode.Text; + txtBCode.Text = txtRCode.Text; + ReadCodes(); + } + + private void btnNorm_Click(object sender, EventArgs e) + { + Button btn = (Button)sender; + + float[] Mags = CalcMagnitudes(); + Mags[0] = 1 / Mags[0]; + Mags[1] = 1 / Mags[1]; + Mags[2] = 1 / Mags[2]; + for (int i = 0; i < FilterSize; i++) + { + for (int j = 0; j < FilterSize; j++) + { + float r, g, b; + float.TryParse(txtR[i * FilterSize + j].Text, out r); + float.TryParse(txtG[i * FilterSize + j].Text, out g); + float.TryParse(txtB[i * FilterSize + j].Text, out b); + + if (btn.Name == "btnNormR") txtR[i * FilterSize + j].Text = (r * Mags[0]).ToString(); + if (btn.Name == "btnNormG") txtG[i * FilterSize + j].Text = (g * Mags[1]).ToString(); + if (btn.Name == "btnNormB") txtB[i * FilterSize + j].Text = (b * Mags[2]).ToString(); + } + } + CalcMagnitudes(); + WriteCodes(); + } + #endregion + + } +} diff --git a/OpenCLFilter/frmCfgFilter.resx b/OpenCLFilter/frmCfgFilter.resx new file mode 100644 index 0000000..92bb5ce --- /dev/null +++ b/OpenCLFilter/frmCfgFilter.resx @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + CMSoft image filtering case study (www.cmsoft.com.br) + +This implementation intends to create an image filtering application which is compatible with most GPUs. +Currently, not many GPUs and drivers support OpenCL images or other resources that would make the code faster. + +by Douglas Andrade (douglas@cmsoft.com.br) + + + + + AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/39/f/6Ojo/9fX1//Q0ND/2dnZ/+rq6v/39/f/+/v7//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz//Pz8//z8/P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//r6+v/s6+v/0tHR/7++vv+ysrH/tLSz/8nJ + yf/k5OT/8/Pz//n5+f/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i4uH/y8rK/7m4 + uP+qqqn/nJyb/6mpqf/Jycn/4eHh//Hx8f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//n5 + +f/e3t3/zs3M/83My/++vbz/nJua/5qZmf+0tLT/zMzM/+Li4v/y8vL/+fn5//r6+v/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//T09P/X19b/zMrK/8/OzP/Av73/nZya/5eWlv+rq6v/vLy8/8/Pz//k5OT/8vLy//j4 + +P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7/+/v7//R0ND/yMbF/9LRz//BwL7/nJuZ/5qZmP+xsbH/vb29/8jI + yP/Y2Nj/5+fn//Hx8f/29vb/+Pj4//r6+v/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+fn5//Ix8f/xMLB/9PR0P/Av73/m5mX/5yb + mv+5ubn/yMjI/8rKyv/S0tL/29vb/+Tk5P/r6+v/8PDw//T09P/39/f/+Pj4//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/+Li4v/CwL//wL68/9XT + 0v/BwL7/mZiV/52cm//CwsH/1tbW/9fX1//Y2Nj/3Nzc/+Dg4P/k5OT/6enp/+7u7v/y8vL/9vb2//j4 + +P/5+fn/+vr6//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/9vb + 2v+4trX/uri2/9TT0f/Av7z/lZSR/5ybmf/Gxsb/4uLi/+Pj4//j4+P/4+Pj/+Tk5P/l5eX/5+fn/+rq + 6v/t7e3/8fHx//T09P/29vb/9/f3//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/9/f3/9TT0/+xr67/trSy/9TS0P/Avrz/lJKP/5qZl//JyMj/6+vr/+7u7v/u7u7/7u7u/+7u + 7v/u7u7/7u7u/+/v7//w8PD/8fHx//Pz8//19fX/9vb2//f39//4+Pj/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/8vLy/8zMy/+pp6X/tLGv/9TS0P+/vrv/k5GO/5iWlP/IyMf/7u7u//X1 + 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/29vb/9/f3//j4+P/4+Pj/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/7u7u/8XFxP+lo6H/tbKw/9TS0P/Avrz/lpSR/5eV + k//GxcT/7Ozs//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/6enp/728vP+fnJr/tLGv/9TT + 0f/Avrz/lpSR/5SSkP/BwMD/6urq//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/5OTk/7a1 + tf+bmJb/tLKv/9TS0P/Av7z/mJaU/5OSkP+9vbz/5ubm//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/4eHh/6+urf+Vk5H/tLGv/9XU0v/BwL3/mZeU/5KQjv+6urn/5OTk//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/29vb/6mop/+SkI3/tLKv/9XU0v/Cwb//nJqY/5KQjv+4t7b/4eHh//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/2dnY/6Ojof+PjYr/t7Sy/9rZ1//Kycf/oqCe/5OR + j/+2tbX/4eHh//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/1NTU/5+enP+IhYL/pqOg/8XD + wP+7ubf/npuY/5CNiv+ysK//3t3d//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//39/f/z87N/5iW + lP96d3T/i4eE/56bmP+WlJD/h4N//4J+ev+ppqP/2djX//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/s7Ov/wcC+/5OQjf95dnL/fXp2/4J+ev98eHT/cm5p/3hzbf+emZT/y8jG//Dw8P/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//b29v/a2df/tLKv/4+MiP+IhYH/jYmG/46Khv9+e3f/b2tm/3Vwav+OiIL/vLiz/+Hf + 3v/4+Pj/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+Pj4/+jn5v/GxML/pKGe/5ORjv+XlJH/n5yZ/56bl/+LiIT/dXJt/3Ju + aP+CfXb/pJ+Z/8vIxP/t7Ov/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/8/Pz/9bV0/+4trP/n5yZ/5yZl/+joJ7/rqun/6uo + pP+Vko7/fHl0/3BsaP98d3D/k42F/7q1r//a2db/9vb2//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/39/f/4+Lh/8XDwf+qp6T/op+c/6Gg + nv+tq6n/uLWy/7KvrP+cmZX/gX56/29saP9zb2n/h4F5/6KclP/Fwb3/5+bl//j4+P/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/u7u3/0c/O/7i1 + s/+opaP/pqSi/6qopv+4trT/wL68/7i2sv+ioJz/iIWB/3Fva/9tamT/f3py/5ONhP+yrqf/0c/M//Hx + 8P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//X0 + 9P/c29r/w8G//66rqf+rqaj/qaim/7OysP/CwL//ycfE/768uP+ppqL/jouH/3Rybv9pZmL/dHBq/4qE + fP+emJD/vbm0/9/e3P/29vb/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5/+np6P/OzMr/uLaz/7CurP+vr63/sK+u/7+9vP/Ny8r/0c/N/8XDwP+xr6v/l5SR/3x6 + dv9raWX/bmtm/4R/eP+Wj4f/rKeg/8nGw//t7Oz/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/8/Ly/9fW1P/Bv73/s7Gv/7Szsv+xsbD/uLi3/8nIx//X1dT/2NbU/8zK + x/+5trP/npyY/4KAff9ua2j/aGZh/3l1b/+QiYH/nZeO/7ezrv/Y1tT/9fX1//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/49/f/4+Lh/8nHxf+3tLL/trSz/7a1tP+1tbX/wcHB/9PS + 0v/f3tz/3NvZ/9HQzf/Avrv/p6Si/4uIhv90cW7/aWdj/3Juaf+KhHz/mZKJ/6ehmf/Cvrv/5+bl//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//v7u7/0M/N/7u5tv+zsq//uLe2/7a2 + tf+7urr/ysrK/93d3P/m5uX/4eDf/9fW1P/HxsP/r62q/5KQjf95d3T/amhk/2poY/9/enT/lo+G/56W + jv+xrKb/z83L//Ly8v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//X19f/a2dj/wb68/7Cu + q/+0srH/tbW0/7e3t//AwMD/09PT/+Tl5P/q6un/5eTi/9zb2f/NzMr/t7Wz/5uZlv+Afnz/bmxp/2ln + Y/91cmz/j4mB/52WjP+hm5P/uray/9/e3P/39/f/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+vr6/+jn + 5//GxML/sK2q/6yqp/+ysbD/s7Oy/7m5uf/Hx8f/3Nzc/+3t7f/v7+7/6eno/+Hg3//U09H/v767/6Oh + n/+HhYP/cnBu/2lnY/9tamb/hH94/5qTi/+el43/qKOd/8bDwP/u7e3/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6 + +v/6+vr/8vHx/8/OzP+zsK7/o6Gd/6qopv+srKr/sbGx/7q6uv/Nzc3/5OTk//Ly8v/x8fH/7Ovr/+Xk + 4//a2Nf/x8XD/6yqqP+Pjoz/eXd1/2xqZ/9raGT/enZx/5SNhv+hmZD/nZaO/7Ouqv/W1NP/9vb1//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//4+Pj/3t3c/7q3tf+fnJj/npuY/6SioP+op6b/sLCv/7y9vP/U1NT/7Ozs//f3 + 9//19fT/8PDv/+rp6P/g393/zs3L/7SysP+XlZP/fn16/25tav9pZ2T/cW5p/4mEff+fmI//oJiP/6Kc + lf++urf/6Ofm//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/+vr6//r6 + +v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/r6+r/w8G+/6Kem/+TkIz/mZeU/5ybmf+ko6L/rq6t/7/A + v//Z2tn/8PDw//j4+P/29vb/8vHx/+zs6//j4+H/1NPR/7y6uf+fnZz/hYSC/3RycP9ramf/bWpm/396 + df+Ykor/pZ2U/5uUi/+rpqH/zcvJ//Ly8v/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//X19f/T0tD/qqik/42Khf+Niob/kY+M/5eW + lP+hoJ//ra2s/8PEw//f4N//9PT0//r6+v/4+Pj/9fX1//Dw7//p6ef/29rZ/8TCwf+npaT/jIqI/3h3 + df9ubGr/bGlm/3Zybf+PiYL/pJ2U/6Oakf+clo7/trOv/+Dg3v/5+fn/+/v7//v7+//7+/v/+/v7//v7 + +//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+Pj4/+Pi4f+1s7D/j4uG/4F+ + ef+Gg3//ioiE/5ORj/+fnpz/sK+u/8rKyv/l5eT/9PT0//j4+P/4+Pj/9vb2//Ly8f/r6+r/397d/8nI + x/+sq6r/kY+O/317ev9xb23/bWpo/3Btaf+Ef3n/nJaN/6mhl/+ak4r/o56Y/8PBvv/u7u3/+fn5//n5 + +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/8fHw/8bF + w/+ZlpL/e3dx/3p2cv98enb/g4F+/4+Niv+enJr/tLOy/9HQ0P/m5+b/7u7u//Dw8P/x8fH/8fHx/+/v + 7//r6+r/4uHg/9DPzv+4trb/n56d/4yKif9+fHv/dXRx/3Nwbf99eXT/lI+H/6mhl/+lnZL/l5GJ/66r + pv/Y19b/9/f3//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/29vb/2NfV/6Win/96dnH/b2xm/3Nxbf94dnP/gYB9/42Miv+bmpn/sK+u/8XExP/Q0ND/0tLR/9DQ + 0P/S0tL/09PT/9TU1P/T09P/0NDP/8fHxv+6ubn/rKuq/5+enf+Uk5L/i4qI/4WEgv+FgoD/ko6J/5+Z + kv+jnJP/kIqC/5WQi/+4trP/6Ojn//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//f39//m5eX/t7a1/4mGg/9wbWr/dnRx/359e/+Ih4X/kZGP/5iYl/+enZ3/pKOj/6mp + qf+pqan/pKSk/6Ghof+hoaH/o6Oj/6Wlpf+oqKj/qqqq/6qqqv+oqKj/pKSk/6Cfn/+ampr/lZWU/5GR + kP+Pjo3/kZCO/5aUkP+Wk47/iYWB/397d/+bmZb/xcTD/+vr6//29vb/+fn5//n5+f/5+fn/+fn5//n5 + +f/5+fn/+fn5//n5+f/4+Pj/8PDw/9ra2v+9vLz/oqGg/4yLif+Mi4n/lZST/52dnP+kpKT/qamp/6io + p/+hoaH/mJiY/46Ojv+FhYX/fX19/3l5ef93d3f/eHh4/3t7e/+AgID/hYWF/4mJif+MjIz/jY2N/42N + jf+MjIz/jIyM/46Ojv+QkJD/kJCQ/4+Pj/+OjYz/iYiG/358e/+Af37/mZmY/7e3t//V1dX/7u7u//j4 + +P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/09PT/2NjY/7e3t/+oqKj/qqqq/7Kxsf+5ubn/u7u7/7y8 + vP+9vb3/urq6/7Kysv+kpKT/lJSU/4SEhP93d3f/bm5u/2lpaf9oaGj/aWlp/21tbf9ycnL/eHh4/35+ + fv+BgYH/goKC/4KCgv+BgYH/goKC/4aGhv+Li4v/kJCQ/5OTk/+Tk5P/kJCQ/4aGhv98fHz/eXl5/4OD + g/+lpaX/0NDQ//Pz8//5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/w8PD/ycnJ/6Wlpf+np6f/yMjI/9bW + 1v/U1NT/z8/P/8nJyf/ExMT/vr6+/7a2tv+pqan/mpqa/4yMjP+BgYH/enp6/3h4eP94eHj/e3t7/4CA + gP+FhYX/ioqK/46Ojv+QkJD/kJCQ/4+Pj/+Ojo7/j4+P/5KSkv+Wlpb/mJiY/5iYmP+Wlpb/kpKS/4uL + i/+AgID/cnJy/2ZmZv+BgYH/v7+//+3t7f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/y8vL/0NDQ/7m5 + uf+4uLj/zs7O/9bW1v/W1tb/0dHR/8rKyv/FxcX/v7+//7i4uP+wsLD/pqam/52dnf+Wlpb/lJSU/5WV + lf+ZmZn/n5+f/6enp/+tra3/srKy/7a2tv+3t7f/tbW1/7Kysv+urq7/rKys/6qqqv+oqKj/pKSk/5+f + n/+YmJj/kJCQ/4eHh/+AgID/eXl5/3l5ef+YmJj/x8fH//Dw8P/5+fn/+fn5//n5+f/7+/v/+/v7//v7 + +//5+fn/7Ozs/9XV1f/Pz8//0NDQ/87Ozv/Jycn/xcXF/8DAwP+9vb3/urq6/7a2tv+ysrL/ra2t/6io + qP+mpqb/pqam/6urq/+ysrL/vLy8/8fHx//R0dH/2dnZ/9/f3//g4OD/3Nzc/9XV1f/Ozs7/xsbG/76+ + vv+1tbX/qqqq/6CgoP+Xl5f/kpKS/5GRkf+VlZX/nZ2d/6ysrP/Gxsb/6Ojo//j4+P/7+/v/+/v7//v7 + +//5+fn/+fn5//n5+f/6+vr/+Pj4//Ly8v/n5+f/3d3d/9fX1//Q0ND/ysrK/8XFxf/BwcH/vb29/7q6 + uv+2trb/srKy/6+vr/+urq7/sLCw/7W1tf+8vLz/xsbG/9LS0v/d3d3/5ubm/+3t7f/u7u7/6enp/+Hh + 4f/Y2Nj/z8/P/8fHx/++vr7/tra2/7Gxsf+vr6//sbGx/7e3t//CwsL/z8/P/+Dg4P/w8PD/+Pj4//n5 + +f/5+fn/+fn5//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/9vb2/+7u7v/m5ub/4uLi/97e + 3v/a2tr/1tbW/9LS0v/Q0ND/zc3N/8vLy//Kysr/y8vL/8/Pz//U1NT/2tra/+Dg4P/n5+f/7Ozs/+/v + 7//v7+//7Ozs/+fn5//i4uL/3d3d/9nZ2f/V1dX/1NTU/9XV1f/Y2Nj/3Nzc/+Pj4//t7e3/9vb2//r6 + +v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8 + /P/8/Pz/+/v7//n5+f/29vb/8vLy//Dw8P/u7u7/7e3t/+zs7P/s7Oz/7Ozs/+3t7f/u7u7/8PDw//Ly + 8v/09PT/9fX1//b29v/19fX/9PT0//Pz8//x8fH/8PDw//Dw8P/w8PD/8vLy//X19f/5+fn/+/v7//z8 + /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P8AAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAA + AAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA8QQAAAAAAADxBAAAAAAAAPEEAAAAAAAA + 8QQ= + + + \ No newline at end of file diff --git a/OpenCLTemplate.dll b/OpenCLTemplate.dll new file mode 100644 index 0000000..2ee55af Binary files /dev/null and b/OpenCLTemplate.dll differ diff --git a/OpenCLTemplate.xml b/OpenCLTemplate.xml new file mode 100644 index 0000000..a9d7b14 --- /dev/null +++ b/OpenCLTemplate.xml @@ -0,0 +1,1334 @@ + + + + OpenCLTemplate + + + + Class to help editing OpenCL code + + + Constructor. Takes care of a Rich Text Box KeyUp event to paint things + RichTextBox to control + + + Help indentation? + + + Regular text color + + + Regular text font + + + Comments color + + + Comments font + + + List of string structures to mark + + + KeyUp event handler + + + Forces OpenCL RichTextBox to be updated + + + Stops updating text box while coloring text + Rich text box to lock + + + Restarts updating text box + Rich text box to unlock + + + Defines a structure of strings to mark + + + Description of string type + + + Color to use for this string type + + + Font to be used in this list of strings + + + List of strings of this type + + + Displays OpenCL related information + + + Constructor. + + + + Required designer variable. + + + + + Clean up any resources being used. + + true if managed resources should be disposed; otherwise, false. + + + + Required method for Designer support - do not modify + the contents of this method with the code editor. + + + + + The main entry point for the application. + + + + OpenCL Helper Editor + + + + Required designer variable. + + + + + Clean up any resources being used. + + true if managed resources should be disposed; otherwise, false. + + + + Required method for Designer support - do not modify + the contents of this method with the code editor. + + + + Constructor. + + + Button to test code + + + OpenCL calculations class + + + String to include to enable Double Precision calculations + + + Currently used acceleration + + + Initialization error + + + Sets CLCalc status to NotUsingCL + + + Initializes OpenCL and reads devices + + + Initializes OpenCL from an existing Context and reads devices + Existing context pointer + Existing command queue pointer + + + Tries to execute actual code in device to check its availability. + Command queue number to check + + + Releases OpenCL resources + + + Last found error + + + List of available platforms + + + List of available devices + + + Gets string to include to enable Double Precision calculations + + + Gets acceleration type being used + + + Gets initialization error description + + + Last error. Throws exception if not set to success. + + + OpenCL accelerations + + + Has not tested what type of acceleration is going to be used. + + + OpenCL used to accelerate calculations + + + No OpenCL used/supported + + + Class to hold OpenCL devices + + + Device ID + + + Device type string + + + Device name string + + + Device vendor string + + + OpenCL version string + + + Execution capabilities of the device + + + Is device available? + + + Is device compiler available? + + + Maximum memory allocation size in bytes + + + Memory size in bytes + + + Maximum number of work-items + that can be specified in each dimension of the work-group + to clEnqueueNDRangeKernel. + + + Maximum number of work-items in a + work-group executing a kernel using the data parallel execution model. + + + Constructor + Device ID + + + Class to hold OpenCL Platforms + + + Platform ID + + + OpenCL profile string. Profile name supported by the implementation. + + + OpenCL version string. + + + OpenCL name string. + + + OpenCL vendor string. + + + OpenCL extensions string. + + + Constructor. + Sets this platform's ID + + + Program related stuff + + + Local event + + + OpenCL context using all devices + + + Synchronous command queues that are executed in call order + + + Asynchronous command queues + + + Default synchronous command queue set as the first GPU, for ease of use. + + + Compiled program + + + Ends all commands being executed + + + Compiles program contained in a single string. + Source code to compile + + + Compiles program contained in a single string. Returns build logs for each device. + Source code to compile + Build logs for each device + + + Compiles the program. + Source code to compile + + + Compiles the program. Returns the build logs for each device. + Source code array to compile + Build logs for each device + + + Variables class + + + Data to be stored + + + Original variable length + + + Memory buffer + + + Constructor. Creates from an existing OpenCL variable + OpenCL variable pointer + Original array length + sizeOf(array datatype) + + + Constructor. + Variable whose size will be allocated in device memory. + + + Constructor. + Variable whose size will be allocated in device memory. + + + Constructor. + Variable whose size will be allocated in device memory. + + + Constructor. + Variable whose size will be allocated in device memory. + + + Constructor. + Variable whose size will be allocated in device memory. + + + Constructor. + Variable whose size will be allocated in device memory. + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Writes variable to device + Values to write to device + Command queue to use + TRUE to return only after completed writing. + OpenCL Event associated to this operation + OpenCL Events that need to finish before this one can start + + + Writes variable to device + Values to write to device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Reads variable from device. + Values to store data coming from device + Command queue to use + TRUE to return only after completed reading. + OpenCL Event associated with this operation + OpenCL Events that need to finish before this one can start + + + Reads variable from device. Does not return until data has been copied. + Values to store data coming from device + + + Sets this variable as an argument for a kernel + Index of kernel argument + Kernel to receive argument + + + Releases variable from memory. + + + Destructor + + + Returns the size of the stored variable + + + Kernels class + + + Local kernel storage + + + Number of arguments + + + Creates a new Kernel + + + + "Remember" variables + + + Sets kernel arguments + Variables to be set as arguments + + + Execute this kernel + Command queue to use + Arguments of the kernel function + Array of maximum index arrays. Total work-items = product(max[i],i+0..n-1), n=max.Length + Events to wait before executing this + Event of this command + + + Execute this kernel + Command queue to use + Arguments of the kernel function + Array of maximum index arrays. Total work-items = product(max[i],i+0..n-1), n=max.Length + Local work sizes + Events to wait before executing this + Event of this command + + + Execute this kernel + Array of maximum index arrays. Total work-items = product(max[i],i+0..n-1), n=max.Length + Arguments of the kernel function + + + Execute this kernel using work_dim = 1 + Global work size in one-dimension. global_work_size = new int[1] {GlobalWorkSize} + Arguments of the kernel function + + + Execute this kernel + Array of maximum index arrays. Total work-items = product(max[i],i+0..n-1), n=max.Length + Local work sizes + Arguments of the kernel function + + + Releases kernel from memory + + + Destructor + + + Gets how many arguments this kernel has + + + OpenCL programs + + + Basic linear algebra functions + + + Float vector sum kernel + + + float matrix multiplication kernel + + + float Gauss Seidel method + + + LU factorizaton method + + + Constructor. Builds OpenCL program. + + + Converts vector to matrix + Vector + Matrix first dimension + Matrix second dimension + + + Converts matrix to vector + Matrix + Matrix first dimension + Matrix second dimension + + + Returns the sum of two matrices + Matrix 1 + Matrix 2 + + + Matrix multiplication + Matrix 1 + Matrix 2 + + + Gauss Seidel method for iterative linear system solving. Returns unknown x + Matrix M so that Mx=b + Initial estimate + Known vector b + Gauss-Seidel iterations per step + Maximum number of times Gauss-Seidel iterations + Desired sqrt(Sum(error[i]^2))*number of equations + Estimated absolute error per component + + + Gauss Seidel method for iterative linear system solving. Returns unknown x + Matrix M so that Mx=b + Initial estimate + Known vector b + Estimated error per equation + + + Solves linear system Mx = b by LU decomposition. Returns x + Matrix M + Vector b + Maximum acceptable absolute error + Maximum iterations + + + Calculates LU decomposition of M matrix + Matrix to decompose + Matrix dimension + Swap index + + + Gauss Seidel method. Make sure to send x = b. Replaces x. + + + Matrix multiplication. Dimensions { p, r }. + + + + Basic linear algebra functions + + + Float vector sum kernel + + + double matrix multiplication kernel + + + double Gauss Seidel method + + + LU factorizaton method + + + Constructor. Builds OpenCL program. + + + Converts vector to matrix + Vector + Matrix first dimension + Matrix second dimension + + + Converts matrix to vector + Matrix + Matrix first dimension + Matrix second dimension + + + Returns the sum of two matrices + Matrix 1 + Matrix 2 + + + Matrix multiplication + Matrix 1 + Matrix 2 + + + Gauss Seidel method for iterative linear system solving. Returns unknown x + Matrix M so that Mx=b + Initial estimate + Known vector b + Gauss-Seidel iterations per step + Maximum number of times Gauss-Seidel iterations + Desired sqrt(Sum(error[i]^2))*number of equations + Estimated absolute error per component + + + Gauss Seidel method for iterative linear system solving. Returns unknown x + Matrix M so that Mx=b + Initial estimate + Known vector b + Estimated error per equation + + + Solves linear system Mx = b by LU decomposition. Returns x + Matrix M + Vector b + Maximum acceptable absolute error + Maximum iterations + + + Calculates LU decomposition of M matrix + Matrix to decompose + Matrix dimension + Swap index + + + Gauss Seidel method. Make sure to send x = b. Replaces x. + + + Matrix multiplication. Dimensions { p, r }. + + + + Float differential equation integrator + + + Writes final Y values and estimated absolute errors + + + Updates X to current time + + + Independent variable current value in OpenCL memory + + + Dynamic system current state in OpenCL memory + + + Derivative calculator + + + Constructor. + Initial state of system + Desired step per integration pass + Initial independent variable value + Function to calculate derivatives vector + + + Integrates equation set to a final value using current stepsize. Ideally, final value + and currentX should multiples of stepsize. + Final value to reach. + + + Sets current state + New independent variable value + New state values + + + Takes an integration step. Saves and returns stepsize back to what it was. + Step size to use + + + Takes an integration step + + + Sets step size. + Step size to use + + + Gets current values of space-state variables (from Device). + + + Gets current absolute error sum + + + Gets current independent variable value (from Device). + + + Function to calculate derivatives vector + IN: Scalar. Independent variable. + IN: State-space vector. + OUT: Derivatives + + + OpenCL source + + + double differential equation integrator + + + Writes final Y values and estimated absolute errors + + + Updates X to current time + + + Independent variable current value in OpenCL memory + + + Dynamic system current state in OpenCL memory + + + Derivative calculator + + + Constructor. + Initial state of system + Desired step per integration pass + Initial independent variable value + Function to calculate derivatives vector + + + Integrates equation set to a final value using current stepsize. Ideally, final value + and currentX should multiples of stepsize. + Final value to reach. + + + Sets current state + New independent variable value + New state values + + + Takes an integration step. Saves and returns stepsize back to what it was. + Step size to use + + + Takes an integration step + + + Sets step size. + Step size to use + + + Gets current values of space-state variables (from Device). + + + Gets current absolute error sum + + + Gets current independent variable value (from Device). + + + Function to calculate derivatives vector + IN: Scalar. Independent variable. + IN: State-space vector. + OUT: Derivatives + + + OpenCL source + + + Discrete element modeling. Calculates derivatives of n particle-spring model into a 6n space-state + system (positions, velocities, x,y,z each). + + + Mass values (n) + + + Original positions (3n) + + + Origins (L) origs[i] connects to dests[i] + + + Destinations (L) + + + Spring constants (L) + + + Spring constants to ground (n) + + + Damping (L) + + + Damping to ground (n) + + + Number of Connections (1) + + + Initial distances (L) + + + Actuating forces (3*n) + + + Connection forces (L) + + + Nodes connections (int, 20*n) + + + Initial lengths kernel. work_dim = 1, globalsize = n + + + Initial length arguments + + + Reset forces kernel. work_dim = 1, globalsize = 3n + + + Reset forces arguments + + + Calculate forces kernel. work_dim = 1, globalsize = L + + + Calculate forces arguments + + + Calculate forces kernel. work_dim = 1, globalsize = n + + + Calculate forces arguments + + + Calculate forces kernel. work_dim = 1, globalsize = L + + + Calculate forces arguments + + + Calculate nodes connections. work_dim = 1, globalsize = n + + + Calculate nodes connections arguments + + + Constructor. + Number of masses in the system + Number of connections + Mass of each vertex + Position and velocity of vertexes + [2*3*i] - posx, [2*(3*i+1)] - posy, [2*(3*i+2)] - posz, + [1+2*3*i] - velx, [1+2*(3*i+1)] - vely, [1+2*(3*i+2)] - velz + Origin vertex of connections. Spring connects Origin[i] to Dests[i] + Destination vertex of connections. Spring connects Origin[i] to Dests[i] + Spring constant for each connection + Spring constant for each mass, connecting to ground (nMass) + Structural damping (relative-speed dependant) (nConnections) + Absolute damping proportional to speed relative to Earth (nMass) + + + Calculates derivatives of deformable body space-state vector dydx[6n]. dydx[2i] - i-th position deriv, + dydx[2i+1] - ith velocity deriv + + + Reset forces. Work_dim = 1, nmax = { nMasses } + + + Derivatives sketch. Work_dim = 1, nmax = { 3 * nMasses } + Forces + Masses + Independent variable + State space vector + Derivatives + + + Initial L0 calculation. work_dim = 1, global_work_size[0]=nConnections + + + Forces calculation. Returns forces. Work_dim = 1, nmax = { nConnections } + + + Calculates forces to ground. w_dim=1, global_work_size = nMasses + + + Calculates forces to ground. w_dim=1, global_work_size = nMasses + + + Vector sum - sums two vectors + + + Integer vector sum. work_dim = 1 + + + Float vector sum. work_dim=1 + + + Long vector sum. work_dim=1 + + + Double vector sum. work_dim=1 + + + Minimum differences - makes matrix of shifted differences of vectors + + + Differences convolution. work_dim=2 + + + Floating point particle system physics + + + Motion Newton-law 1D solver. Kernel: rk46 + + + Force applier to particles. Kernels: ResetForces, ApplyGravity, FloorCollision + + + Collision applier to particles. Kernels: ResetForces, ApplyGravity, FloorCollision + + + Initializes physics program. Components indexes: [i] - x, [i+1] - y, [i+2] - z + Number of particles + + + Sets particles parameters + Positions (3*numParticles) + Speeds (3*numParticles) + Masses (numParticles) + Collision sizes (numParticles) + + + Gets particles positions + + + Gets how many close neighbors a particle has. Use this to avoid drawing unnecessary particles + + + Gets simulation time + + + Stepsize + + + Executes an integration step + + + Motion step arguments + + + Takes an integration step + Step size + + + Applies gravity + + + Apply gravity arguments + + + Applies gravity force. + Gravity force. Remember to use negative for down direction. + + + Clear forces + + + Apply gravity arguments + + + Clears forces + + + Floor collision + + + Apply floor collision arguments + + + Applies floor collision? + + + Wall collision + + + Apply floor collision arguments + + + Applies floor collision? + + + Self collision + + + Apply self collision arguments + + + Applies self collision? + + + Reset close neighbors + + + Apply self collision arguments + + + + An useful class to read/write/delete/count registry keys + + + + + To read a registry key. + input: KeyName (string) + output: value (string) + + + + + To write into a registry key. + input: KeyName (string) , Value (object) + output: true or false + + + + + To delete a registry key. + input: KeyName (string) + output: true or false + + + + + To delete a sub key and any child. + input: void + output: true or false + + + + + Retrive the count of subkeys at the current key. + input: void + output: number of subkeys + + + + + Retrive the count of values in the key. + input: void + output: number of keys + + + + + A property to show or hide error messages + (default = false) + + + + + A property to set the SubKey value + (default = "SOFTWARE\\" + Application.ProductName.ToUpper()) + + + + + A property to set the BaseRegistryKey value. + (default = Registry.LocalMachine) + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + Creates a Matrix of real numbers. + + + Matrix items + + + Linear Solve parameter. Maximum mean error allowable to linear solve method. + + + Linear Solve parameter. Limit linear solution correction iterations. + + + Linear Solve parameter. Should the solution method halt if a hard singulariry is found in matrix? + + + Linear Solve parameter. Should the method ignore if the matrix has a close-to-zero determinant and keep solving? + + + Constructor. Initializes a [0,0] matrix. + + + Constructor. Creates matrix from existing items. + Matrix items to create matrix from. + + + Copy constructor. + Matrix to copy from. + + + Constructor. Creates empty matrix with specified dimensions. + Number of rows in matrix. + Number of columns in matrix. + + + Sums two matrixes. + First matrix to sum. + Second matrix to sum. + + + Subtracts two matrixes. + Matrix to subtract from. + Matrix to be subtracted. + + + Matrix multiplication. Notice that m1 rows should be the same as m2 lines for compatibility. + First matrix to multiply. + Second matrix to multiply. + + + Matrix scalar multiplication. + Matrix to multiply. + Scalar to multiply. + + + Matrix scalar multiplication. + Matrix to multiply. + Scalar to multiply. + + + Matrix post-vector multiplication. Notice that a vector is a [1,Cols] matrix which means + vector length should be equal matrix number of columns. + Matrix to multiply. + vector to multiply. + + + Matrix pre-vector multiplication. Notice that a vector is a [1,Cols] matrix which means + vector length should be equal matrix number of lines. + Matrix to multiply. + vector to multiply. + + + Matrix scalar division. + Matrix to multiply. + Scalar to divide each element of matrix. + + + Compares matrixes and returns true if they are identical. + Matrix to compare to. + + + Returns matrix transpose. + + + Element-wise product. This is not regular matrix product. It multiplies elements + at corresponding positions. + Matrix to multiply element-wise. + + + Returns Euclidean norm of the matrix. + + + Dot product of two matrixes. + Matrix to dot product with/ + + + Element-wise inversion. Returns the matrix with each element (x) inverted (1/x). + + + Creates internal LU factorization of this matrix. + + + Returns the solution x to the linear system Ax=b, A being this matrix. + Right-hand side known values. + + + Returns the determinant of this matrix. + + + Returns the inverse of this matrix. + + + Returns the solution x to the linear system A'Ax=A'b, A being this matrix. + Right-hand side known values. + + + Returns the weighted solution x to the linear system A'WAx=A'Wb, + A being this matrix. TO DO: Correct quality check + Right-hand side known values. + Weight matrix. + + + Returns the weighted solution x to the linear system A'DAx=A'Db, + A being this matrix. D is a diagonal weight matrix. + Right-hand side known values. + Main diagonal elements of diagonal weight matrix D. + + + Calculates R², corrected R² and Quadratic Error for the trySolution x to the linear system A'Ax=A'b, + A being this matrix. + Right-hand side known values. + Solution to use to evaluate quality indexers. + + + Applies the Gram-Schmidt orthonormalization method to this matrix, replacing + it by the orthonormalized matrix. + + + Applies the Gram-Schmidt orthonormalization method to this matrix, replacing + it by the orthonormalized matrix and also correcting right-hand Y values for a linear system solve. + Right-hand side known values. + + + Applies the Gram-Schmidt orthonormalization method to this matrix using + a pre-set order of normalization. Replaces current matrix + by the orthonormalized matrix and also correcting + right-hand Y values for a linear system solve. + Right-hand side known values. + Line order to apply the orthonormalization method. + Starts orthonormalization from line lineOrder[indStart]. Assumes previous lines are already + normalized. + + + Returns a string representing this matrix. + + + Accesses items in current matrix. + Row of element to access. + Column of element to access. + + + Gets the number of rows in this matrix. + + + Gets the number of columns in this matrix. + + + Returns the R² index of last fit. + + + Returns corrected R² index of last fit. + + + Returns the sum of quadratic errors of last fit. + + +