//---------------------------------------------------------------------------- // Copyright (C) 2004-2023 by EMGU Corporation. All rights reserved. //---------------------------------------------------------------------------- using System; using System.Text; using System.Xml; using System.Xml.Linq; using System.Xml.Serialization; using System.IO; using System.Runtime.InteropServices; using System.Diagnostics; using System.Collections.Generic; using System.Reflection; namespace Emgu.Util { /// /// utilities functions for Emgu /// public static class Toolbox { #region xml serilization and deserialization /// /// Convert an object to an xml document /// /// The type of the object to be converted /// The object to be serialized /// An xml document that represents the object public static XDocument XmlSerialize(T sourceObject) { StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter(sb)) (new XmlSerializer(typeof(T))).Serialize(sw, sourceObject); return XDocument.Parse(sb.ToString()); } /// /// Convert an object to an xml document /// /// The type of the object to be converted /// The object to be serialized /// Other types that it must known ahead to serialize the object /// An xml document that represents the object public static XDocument XmlSerialize(T sourceObject, Type[] knownTypes) { StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter(sb)) (new XmlSerializer(typeof(T), knownTypes)).Serialize(sw, sourceObject); return XDocument.Parse(sb.ToString()); } /// /// Convert an xml document to an object /// /// The type of the object to be converted to /// The xml document /// The object representation as a result of the deserialization of the xml document public static T XmlDeserialize(XDocument document) { using (XmlReader reader = document.Root.CreateReader()) { if (reader.CanReadBinaryContent) return (T)(new XmlSerializer(typeof(T))).Deserialize(reader); else { return XmlStringDeserialize(document.ToString()); } } } /// /// Convert an xml document to an object /// /// The type of the object to be converted to /// The xml document /// Other types that it must known ahead to deserialize the object /// The object representation as a result of the deserialization of the xml document public static T XmlDeserialize(XDocument xDoc, Type[] knownTypes) { using (XmlReader reader = xDoc.Root.CreateReader()) { if (reader.CanReadBinaryContent) return (T)(new XmlSerializer(typeof(T), knownTypes)).Deserialize(reader); else { using (StringReader stringReader = new StringReader(xDoc.ToString())) { return (T)(new XmlSerializer(typeof(T), knownTypes)).Deserialize(stringReader); } } } } /// /// Convert an xml string to an object /// /// The type of the object to be converted to /// The xml document as a string /// The object representation as a result of the deserialization of the xml string public static T XmlStringDeserialize(String xmlString) { using (StringReader stringReader = new StringReader(xmlString)) return (T)(new XmlSerializer(typeof(T))).Deserialize(stringReader); } #endregion /// /// Similar to Marshal.SizeOf function /// /// The type /// The size of T in bytes public static int SizeOf() { return Marshal.SizeOf(); } /* /// /// Read a text file to an array of string, each row are separated using by the input separator /// /// The text file to read from /// The row separator /// public static string FileToString(string fileName, char separator) { StringBuilder res = new StringBuilder(); string input; using (StreamReader sr = File.OpenText(fileName)) while ((input = sr.ReadLine()) != null) res.AppendFormat("{0}{1}", input, separator); return res.ToString(); }*/ /// /// Merges two byte vector into one /// /// the first byte vector to be merged /// the second byte vector to be merged /// The bytes that is a concatenation of a and b public static Byte[] MergeBytes(Byte[] a, Byte[] b) { Byte[] c = new byte[a.Length + b.Length]; // just one array allocation Buffer.BlockCopy(a, 0, c, 0, a.Length); Buffer.BlockCopy(b, 0, c, a.Length, b.Length); return c; } /// /// Call a command from command line /// /// The name of the executable /// The arguments to the executable /// The standard output public static string ExecuteCmd(string execFileName, string arguments) { using (Process processor = new Process()) { processor.StartInfo.FileName = execFileName; processor.StartInfo.Arguments = arguments; processor.StartInfo.UseShellExecute = false; processor.StartInfo.RedirectStandardOutput = true; processor.StartInfo.RedirectStandardError = true; //string error = string.Empty; try { processor.Start(); } catch (Exception) { //error = e.Message; } //processor.BeginErrorReadLine(); //String error2 = processor.StandardError.ReadToEnd(); string output = processor.StandardOutput.ReadToEnd(); processor.WaitForExit(); processor.Close(); return output; } } /// /// Use reflection to find the base type. If such type do not exist, null is returned /// /// The type to search from /// The name of the base class to search /// The base type public static Type GetBaseType(Type currentType, String baseClassName) { if (currentType.Name.Equals(baseClassName)) return currentType; Type baseType = currentType.BaseType; return (baseType == null) ? null : GetBaseType(baseType, baseClassName); } #region memory copy /// /// Convert some generic vector to vector of Bytes /// /// type of the input vector /// array of data /// the byte vector public static Byte[] ToBytes(TData[] data) { int size = Marshal.SizeOf() * data.Length; Byte[] res = new Byte[size]; GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); Marshal.Copy(handle.AddrOfPinnedObject(), res, 0, size); handle.Free(); return res; } /// /// Perform first degree interpolation give the sorted data and the interpolation /// /// The sorted data that will be interpolated from /// The indexes of the interpolate result /// The type of the data to be interpolated /// The interpolated data public static IEnumerable LinearInterpolate(IEnumerable src, IEnumerable indexes) where T : IInterpolatable, new() { using (IEnumerator sampleEnumerator = src.GetEnumerator()) { if (!sampleEnumerator.MoveNext()) yield break; T old = sampleEnumerator.Current; if (!sampleEnumerator.MoveNext()) yield break; T current = sampleEnumerator.Current; foreach (double index in indexes) { while (index > current.InterpolationIndex && sampleEnumerator.MoveNext()) { old = current; current = sampleEnumerator.Current; } //yield return LinearInterpolate(old, current, index); yield return old.LinearInterpolate(current, index); } } } /// /// Get subsamples with the specific rate /// /// The source which the subsamples will be derived from /// The subsample rate /// subsampled with the specific rate /// The type of the object public static IEnumerable LinearSubsample(IEnumerable src, double subsampleRate) where T : IInterpolatable, new() { using (IEnumerator sampleEnumerator = src.GetEnumerator()) { if (!sampleEnumerator.MoveNext()) yield break; T old = sampleEnumerator.Current; yield return old; if (!sampleEnumerator.MoveNext()) yield break; T current = sampleEnumerator.Current; double currentIndex = old.InterpolationIndex + subsampleRate; bool endOfSubsample = false; while (!endOfSubsample) { while (currentIndex > current.InterpolationIndex) { if (endOfSubsample = !sampleEnumerator.MoveNext()) break; old = current; current = sampleEnumerator.Current; } if (!endOfSubsample) { yield return old.LinearInterpolate(current, currentIndex); //yield return LinearInterpolate(old, current, currentIndex); currentIndex += subsampleRate; } } } } /// /// Joining multiple index ascending IInterpolatables together as a single index ascending IInterpolatable. /// /// The type of objects that will be joined /// The enumerables, each should be stored in index ascending order /// A single enumerable sorted in index ascending order public static IEnumerable JoinInterpolatables(params IEnumerable[] enums) where T : IInterpolatable, new() { if (enums.Length == 0) yield break; else if (enums.Length == 1) { foreach (T sample in enums[0]) yield return sample; } else if (enums.Length == 2) { foreach (T sample in JoinTwoInterpolatables(enums[0], enums[1])) yield return sample; } else { int middle = enums.Length / 2; IEnumerable[] lower = new IEnumerable[middle]; IEnumerable[] upper = new IEnumerable[enums.Length - middle]; Array.Copy(enums, lower, middle); Array.Copy(enums, middle, upper, 0, enums.Length - middle); foreach (T sample in JoinTwoInterpolatables(JoinInterpolatables(lower), JoinInterpolatables(upper))) yield return sample; } } private static IEnumerable JoinTwoInterpolatables(IEnumerable enum1, IEnumerable enum2) where T : IInterpolatable, new() { IEnumerator l1 = enum1.GetEnumerator(); IEnumerator l2 = enum2.GetEnumerator(); if (!l1.MoveNext()) { while (l2.MoveNext()) yield return l2.Current; yield break; } else if (!l2.MoveNext()) { while (l1.MoveNext()) yield return l1.Current; yield break; } T s1 = l1.Current; T s2 = l2.Current; while (true) { if (s1.InterpolationIndex < s2.InterpolationIndex) { yield return s1; if (l1.MoveNext()) s1 = l1.Current; else { while (l2.MoveNext()) yield return l2.Current; yield break; } } else { yield return s2; if (l2.MoveNext()) s2 = l2.Current; else { while (l1.MoveNext()) yield return l1.Current; yield break; } } } } /* /// /// Use the two IInterpolatable and the index to perform first degree interpolation /// /// The first element to interpolate from /// The second eleemnt to interpolate from /// The interpolation index /// The interpolatation result private static T LinearInterpolate(T i1, T i2, double index) where T : IInterpolatable, new() { double f = (i2.InterpolationIndex - index) / (i2.InterpolationIndex - i1.InterpolationIndex); //compute result = i1 * f + i2 * (1.0 - f) T a = new T(); a.Add(i1); a.Mul(f); T b = new T(); b.Add(i2); b.Mul(1.0 - f); a.Add(b); return a; }*/ #endregion private static System.Collections.Generic.Dictionary _assemblyNameDict = new Dictionary(); /// /// Load all the assemblies. /// /// All the assemblies loaded. public static System.Reflection.Assembly[] LoadAllDependentAssemblies() { try { lock (_assemblyNameDict) { System.Reflection.Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); bool dirty = false; foreach (Assembly assembly in assemblies) { AssemblyName name = assembly.GetName(); if (!_assemblyNameDict.ContainsKey(name.ToString())) _assemblyNameDict.Add(name.ToString(), name); } foreach (Assembly assembly in assemblies) { AssemblyName[] referencedAssemblyNames = assembly.GetReferencedAssemblies(); foreach (AssemblyName name in referencedAssemblyNames) { if (!_assemblyNameDict.ContainsKey(name.ToString())) { try { Assembly.Load(name); _assemblyNameDict.Add(name.ToString(), name); dirty = true; } catch (Exception e) { //if failed to load, it is ok, we will continue. Debug.WriteLine(e); } } } } if (dirty) return AppDomain.CurrentDomain.GetAssemblies(); else { return assemblies; } } } catch (Exception e) { Debug.WriteLine(e); } return null; } /// /// Get the interface implementation from assemblies /// /// The interface /// The types that implement the specific interface public static Type[] GetInterfaceImplementationFromAssembly() { System.Reflection.Assembly[] assemblies = LoadAllDependentAssemblies(); List types = new List(); if (assemblies != null) { foreach (Assembly assembly in assemblies) { foreach (Type t in assembly.GetTypes()) { if (typeof(T).IsAssignableFrom(t) && typeof(T) != t) { types.Add(t); } } } } return types.ToArray(); } /// /// Find the loaded assembly with the specific assembly name /// /// The name of the assembly /// The assembly. public static System.Reflection.Assembly FindAssembly(String assembleName) { try { System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies(); foreach (System.Reflection.Assembly asm in asms) { if (asm.ManifestModule.Name.Equals(assembleName)) return asm; } } catch (Exception exception) { Trace.WriteLine(String.Format("FindAssembly({0}) failed: {1}", assembleName, exception.Message)); } return null; } private static IntPtr LoadLibraryExWindows(String dllname, int flags) { IntPtr handler = LoadLibraryEx(dllname, IntPtr.Zero, flags); if (handler == IntPtr.Zero) { int error = Marshal.GetLastWin32Error(); System.ComponentModel.Win32Exception ex = new System.ComponentModel.Win32Exception(error); System.Diagnostics.Trace.WriteLine(String.Format( "LoadLibraryEx(\"{0}\", 0, {3}) failed with error code {1}: {2}", dllname, (uint) error, ex.Message, flags)); if (error == 5) { System.Diagnostics.Trace.WriteLine(String.Format( "Please check if the current user has execute permission for file: {0} ", dllname)); } } else { System.Diagnostics.Trace.WriteLine(String.Format("LoadLibraryEx(\"{0}\", 0, {1}) successfully loaded library.", dllname, flags)); } return handler; } private static IntPtr LoadLibraryWindows(String dllname) { const int loadLibrarySearchDllLoadDir = 0x00000100; const int loadLibrarySearchDefaultDirs = 0x00001000; int flags; if (System.IO.Path.IsPathRooted(dllname)) { flags = loadLibrarySearchDllLoadDir | loadLibrarySearchDefaultDirs; } else { flags = loadLibrarySearchDefaultDirs; } IntPtr handler = LoadLibraryExWindows(dllname, flags); if (handler == IntPtr.Zero) { //Try again with the '0' flags. //The first attempt above may fail, if the native dll is within a folder in the PATH environment variable. //The call below will also search for folders in PATH environment variable. handler = LoadLibraryExWindows(dllname, 0); } // LoadPackagedLibrary() is supported from Windows 8 (6.2) onwards if (handler == IntPtr.Zero && Environment.OSVersion.Version >= new Version(6, 2)) { //Also try loadPackagedLibrary IntPtr packagedLibraryHandler = LoadPackagedLibrary(dllname, 0); if (packagedLibraryHandler == IntPtr.Zero) { int error = Marshal.GetLastWin32Error(); var ex = new System.ComponentModel.Win32Exception(error); System.Diagnostics.Debug.WriteLine(String.Format( "LoadPackagedLibrary {0} failed with error code {1}: {2}", dllname, (uint)error, ex.Message)); } else { System.Diagnostics.Trace.WriteLine(String.Format("LoadPackagedLibrary loaded: {0}", dllname)); return packagedLibraryHandler; } } return handler; } /// /// Maps the specified executable module into the address space of the calling process. /// /// The name of the dll /// The handle to the library public static IntPtr LoadLibrary(String dllname) { #if UNITY_EDITOR_WIN return LoadLibraryWindows(dllname); #else if (Platform.OperationSystem == Emgu.Util.Platform.OS.Windows) { return LoadLibraryWindows(dllname); } else { IntPtr handler; try { handler = Dlopen(dllname, 0x00102); // 0x00002 == RTLD_NOW, 0x00100 = RTL_GLOBAL if (handler == IntPtr.Zero) { System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen to load {0}", dllname)); } } catch { System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen from libdl.so to load {0}, will try using libdl.so.2 instead", dllname)); handler = Dlopen2(dllname, 0x00102); // 0x00002 == RTLD_NOW, 0x00100 = RTL_GLOBAL if (handler == IntPtr.Zero) { System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen from libdl.so.2 to load {0}", dllname)); } } return handler; } #endif } /* [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern UIntPtr GetProcAddress(IntPtr hModule, string procName); private static bool? _kernel32HasLoadPackagedLibrary = null; private static IntPtr LoadPackagedLibrarySafe(String fileName, int dwFlags) { if (_kernel32HasLoadPackagedLibrary == null) { UIntPtr = GetProcAddress("") } }*/ [DllImport("Kernel32.dll", SetLastError = true)] private static extern IntPtr LoadPackagedLibrary( [MarshalAs(UnmanagedType.LPStr)] String fileName, int dwFlags); [DllImport("Kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibraryEx( [MarshalAs(UnmanagedType.LPStr)] String fileName, IntPtr hFile, int dwFlags); [DllImport("dl", EntryPoint = "dlopen")] private static extern IntPtr Dlopen( [MarshalAs(UnmanagedType.LPStr)] String dllname, int mode); [DllImport("libdl.so.2", EntryPoint = "dlopen")] private static extern IntPtr Dlopen2( [MarshalAs(UnmanagedType.LPStr)] String dllname, int mode); /* /// /// Decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid /// /// The handle to the library /// If the function succeeds, the return value is true. If the function fails, the return value is false. [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FreeLibrary(IntPtr handle); */ /// /// Set the directory to the search path used to locate DLLs for the application /// /// The directory to be searched for DLLs /// True if success [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetDllDirectory(String path); /// /// Get the search path used to locate DLLs for the application /// /// /// If the function succeeds, the return value is the search path used to locate DLLs for the application /// If the function fails, the return value is null.To get extended error information, call GetLastError. /// public static String GetDllDirectory() { int maxSize = 2048; IntPtr buffer = Marshal.AllocHGlobal(maxSize); try { bool success = GetDllDirectory((uint) maxSize, buffer); if (!success) return null; return Marshal.PtrToStringUni(buffer); } catch (Exception e) { Trace.WriteLine("Failed to call into GetDllDirectory:" + Environment.NewLine + e.StackTrace); return null; } finally { Marshal.FreeHGlobal(buffer); } } [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetDllDirectory(uint nBufferLength, IntPtr lpBuffer); /// /// Adds a directory to the search path used to locate DLLs for the application /// /// The directory to be searched for DLLs /// True if success [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddDllDirectory(String path); } }