From 91de52b22219b2a90c914165e0354ed95587f26a Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sun, 15 Nov 2015 18:29:27 +0000 Subject: [PATCH] =?UTF-8?q?openclfilter=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AForge.Video.DirectShow.dll | Bin 0 -> 31232 bytes AForge.Video.dll | Bin 0 -> 14336 bytes AForge.dll | Bin 0 -> 11264 bytes OpenCL.NET.dll | Bin 0 -> 36864 bytes OpenCL.NET.xml | 143 ++ OpenCLFilter.sln | 20 + OpenCLFilter/CLFilter.cs | 309 ++++ OpenCLFilter/Form1.Designer.cs | 276 ++++ OpenCLFilter/Form1.cs | 226 +++ OpenCLFilter/Form1.resx | 719 +++++++++ OpenCLFilter/ImageData.cs | 120 ++ OpenCLFilter/OpenCLFilter.csproj | 165 ++ OpenCLFilter/OpenCLFilter.csproj.user | 13 + OpenCLFilter/Program.cs | 21 + OpenCLFilter/Properties/AssemblyInfo.cs | 36 + OpenCLFilter/Properties/Resources.Designer.cs | 63 + OpenCLFilter/Properties/Resources.resx | 117 ++ OpenCLFilter/Properties/Settings.Designer.cs | 26 + OpenCLFilter/Properties/Settings.settings | 7 + OpenCLFilter/filter.ico | Bin 0 -> 9662 bytes OpenCLFilter/frmCfgFilter.Designer.cs | 392 +++++ OpenCLFilter/frmCfgFilter.cs | 261 ++++ OpenCLFilter/frmCfgFilter.resx | 295 ++++ OpenCLTemplate.dll | Bin 0 -> 287232 bytes OpenCLTemplate.xml | 1334 +++++++++++++++++ 25 files changed, 4543 insertions(+) create mode 100644 AForge.Video.DirectShow.dll create mode 100644 AForge.Video.dll create mode 100644 AForge.dll create mode 100644 OpenCL.NET.dll create mode 100644 OpenCL.NET.xml create mode 100644 OpenCLFilter.sln create mode 100644 OpenCLFilter/CLFilter.cs create mode 100644 OpenCLFilter/Form1.Designer.cs create mode 100644 OpenCLFilter/Form1.cs create mode 100644 OpenCLFilter/Form1.resx create mode 100644 OpenCLFilter/ImageData.cs create mode 100644 OpenCLFilter/OpenCLFilter.csproj create mode 100644 OpenCLFilter/OpenCLFilter.csproj.user create mode 100644 OpenCLFilter/Program.cs create mode 100644 OpenCLFilter/Properties/AssemblyInfo.cs create mode 100644 OpenCLFilter/Properties/Resources.Designer.cs create mode 100644 OpenCLFilter/Properties/Resources.resx create mode 100644 OpenCLFilter/Properties/Settings.Designer.cs create mode 100644 OpenCLFilter/Properties/Settings.settings create mode 100644 OpenCLFilter/filter.ico create mode 100644 OpenCLFilter/frmCfgFilter.Designer.cs create mode 100644 OpenCLFilter/frmCfgFilter.cs create mode 100644 OpenCLFilter/frmCfgFilter.resx create mode 100644 OpenCLTemplate.dll create mode 100644 OpenCLTemplate.xml diff --git a/AForge.Video.DirectShow.dll b/AForge.Video.DirectShow.dll new file mode 100644 index 0000000000000000000000000000000000000000..d8d48b497e6ca9b413781032fa289119d415da17 GIT binary patch literal 31232 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 Bfhzz2 literal 0 HcmV?d00001 diff --git a/AForge.Video.dll b/AForge.Video.dll new file mode 100644 index 0000000000000000000000000000000000000000..fc5e5c6e75e663a8383213ea702aa74cf283e70a GIT binary patch literal 14336 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 Mtp0y8|4k447df`S(EtDd literal 0 HcmV?d00001 diff --git a/OpenCL.NET.dll b/OpenCL.NET.dll new file mode 100644 index 0000000000000000000000000000000000000000..1cb7ace997a5d1ce014c86cc7a6ca265cc665fa0 GIT binary patch literal 36864 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 literal 0 HcmV?d00001 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= + + + + + 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 + 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 0000000000000000000000000000000000000000..14a594a17b4465afb8da14f918bd5919880fa686 GIT binary patch literal 9662 zcmeHNS5sWc6~$@Z>UK!5;&$cPL>7{Uz93=BD^85nZTAac$KL7e&4Vd77j<=Y=;`Uf+}xbP z5_!0*9-L+8iu;R;3oMAuJ{}tt8<@l3K%dCpBJww*si_IQy}fw+_%YVk*Ku-kqOkP- z{d>g+ZQ{0e;cEGlrpM#s7#SMG(!#uwf4;?}Fx1)Esc4@R-7GFHVry$l>EXH9`>R*4 zK;6+t-9{&_kh$|3#P-lYKL+}Gu(GtMe11W z!V+V|%a<<|rlKuXrOB@7@9*n|AxjT)u2HZ*uIMIR*A2?vS^l@NiLccG zWjZ=Kf{L;dv^p9;%Rg7}W6CjLOy0eC@xmo>OQTV<4_91igT3P4i^Sh6`4j(wAJT8k z&JQuh+uKPI8cZJ-wH5iX-s;h+7bR~b%KQ!16Yo1xr z-_hO%@~D09imNj(cfH@(SVx)IZbo_v+QolvZmeN)VjQK#h2n!U6t+nJUH5UG?+O`c zYb-A>qo~k|poUH8-G--UN=F5@JzPM?{PmMr**LAovx`jkXOg$LvQJ$D58c|o5X zi=K{V?CtKT98;Trm#fCd*IpUdPfw09HZp|r656RACW%)?R*T@rgw*7C1O@nr4m=PW z`4Htr7SX{7UW&fHc2DPdcj29LnP;u8EJ@DUtZ24Mo>nIQ##UE_y6SS|Wa|+T8VEmc z4@3m}!H}MSu2#F~YgOepcirEam)qXcW)I}7J~}*z+NyGt7Fkguv^Uh%prh3RhrJ$F zOAcbhcJB-Q5AJ&+DJB%9RwG6SdvS7nbgQ$t%_&FkR@A( zsuBx^s_mK^^GdrxZKa z_J&%OlZHxO;pOq2jBmw`0|i5gD9qKPslF0(GgGSea9etAqX+7EQ*z8fIa4*->LlJa ziQHSz-rkM@Ia@8s+5Pb7P|jFqI6B-{I+zg~X&3*LZ^=b;R0MpzJ(UiE0=$ty4CSVw zB;SB8@m16tee!Mea8rKC=c&}D7-t(rp7pg=a0up`1^cW^jZ4jn^&HkeE-ubN`=$<9 zL*W^|tfUA@32_MU`-CAMuTOTIXGle%DIL{i1sIcj^<3uPlqP<6Q~AG)%Jn9+T_=BH@%i&-5~uo5T9^+*W|}(BvL;(zRtlS(cl#w?ZES9+yqLT)AEmyS zQy(1cDGc?<*|(^`iiG%BiDiDcCpsX89)$(LoSlM-0weN`si>6D&^nHmx(!uuQB}JtD)yBp>n- z`Fp_6$5Y~QsL-8`ni3Q83@IopG%I~Gzxon=eD@{(m|KmB?OAfO5gzO>_7(u<0dX-= z>Wp5)@w3zcc`zEXkt$fCJtV|NBU`US zktG{tRs%9qVv&=Xs&cE-)01m;aFqx8kYlN7w@X~rCB})4z3@dMZ;t)B^73+&l$5AZCeJG>Do|ZrEj_$iHF(c&ii?VnmzRf}9HXq2DSkB_ zSyJEPSwGjHhfebCM{@3D%o`QkV$GWJyh`WQzlmGwe{*wF)iFy;ijkJ8QzOS{K!NxV z?oV2)rA|d!&1N(7dOZ>n5)c^~iO|qc1P2ErBqRjk;o*pmj#lqo}TdV@K9GDA36611SnpjqM{HJ6NA{;ST(f! z#Kc6Trlu$;lC&TTmnzrwkez8kDZcFZIeio4T{vY^blV|2Mnf9P&W<;u;$Oal<|Q*4%TpKXOt0n)bPmuFxTRhx*8f9 zQs1ygNxA=;?K<<~d{18Jv$!YsXJ2$@XGi%a;)%3TKg>I)rlu6OcqL7=7y2;nOF2-d zjAb0W=QFNH-l!YugL8P*`l{?tl4sIDTAXQfzW?~~X1|}|9O{YdQ9qOidE*|WNgJA+ t`JUg=r!g1eJYM-XeF)<-ztIN2<$Dd&H>K;-?}A?c@&8v!;P;oqzX0A$OTYjC literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2ee55af05383a940d19521e1eb10edd174586d30 GIT binary patch literal 287232 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 literal 0 HcmV?d00001 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. + + +