mirror of https://github.com/emgucv/emgucv.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
530 lines
20 KiB
530 lines
20 KiB
//----------------------------------------------------------------------------
|
|
// Copyright (C) 2004-2017 by EMGU Corporation. All rights reserved.
|
|
//----------------------------------------------------------------------------
|
|
using System;
|
|
using System.Text;
|
|
using System.Xml;
|
|
#if !(UNITY_ANDROID || UNITY_IPHONE || UNITY_STANDALONE || UNITY_METRO || UNITY_EDITOR)
|
|
using System.Xml.Linq;
|
|
#endif
|
|
using System.Xml.Serialization;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Diagnostics;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Emgu.Util
|
|
{
|
|
/// <summary>
|
|
/// utilities functions for Emgu
|
|
/// </summary>
|
|
public static class Toolbox
|
|
{
|
|
#if !(UNITY_ANDROID || UNITY_IPHONE || UNITY_STANDALONE || UNITY_METRO || UNITY_EDITOR || NETSTANDARD1_4)
|
|
#region xml serilization and deserialization
|
|
/// <summary>
|
|
/// Convert an object to an xml document
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to be converted</typeparam>
|
|
/// <param name="sourceObject">The object to be serialized</param>
|
|
/// <returns>An xml document that represents the object</returns>
|
|
public static XDocument XmlSerialize<T>(T sourceObject)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
using (StringWriter sw = new StringWriter(sb))
|
|
(new XmlSerializer(typeof(T))).Serialize(sw, sourceObject);
|
|
|
|
return XDocument.Parse(sb.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an object to an xml document
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to be converted</typeparam>
|
|
/// <param name="sourceObject">The object to be serialized</param>
|
|
/// <param name="knownTypes">Other types that it must known ahead to serialize the object</param>
|
|
/// <returns>An xml document that represents the object</returns>
|
|
public static XDocument XmlSerialize<T>(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());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an xml document to an object
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to be converted to</typeparam>
|
|
/// <param name="document">The xml document</param>
|
|
/// <returns>The object representation as a result of the deserialization of the xml document</returns>
|
|
public static T XmlDeserialize<T>(XDocument document)
|
|
{
|
|
using (XmlReader reader = document.Root.CreateReader())
|
|
{
|
|
if (reader.CanReadBinaryContent)
|
|
return (T)(new XmlSerializer(typeof(T))).Deserialize(reader);
|
|
else
|
|
{
|
|
return XmlStringDeserialize<T>(document.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an xml document to an object
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to be converted to</typeparam>
|
|
/// <param name="xDoc">The xml document</param>
|
|
/// <param name="knownTypes">Other types that it must known ahead to deserialize the object</param>
|
|
/// <returns>The object representation as a result of the deserialization of the xml document</returns>
|
|
public static T XmlDeserialize<T>(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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an xml string to an object
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to be converted to</typeparam>
|
|
/// <param name="xmlString">The xml document as a string</param>
|
|
/// <returns>The object representation as a result of the deserialization of the xml string</returns>
|
|
public static T XmlStringDeserialize<T>(String xmlString)
|
|
{
|
|
using (StringReader stringReader = new StringReader(xmlString))
|
|
return (T) (new XmlSerializer(typeof(T))).Deserialize(stringReader);
|
|
}
|
|
#endregion
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Similar to Marshal.SizeOf function
|
|
/// </summary>
|
|
/// <typeparam name="T">The type</typeparam>
|
|
/// <returns>The size of T in bytes</returns>
|
|
public static int SizeOf<T>()
|
|
{
|
|
#if NETFX_CORE || NETSTANDARD1_4
|
|
return Marshal.SizeOf<T>();
|
|
#else
|
|
return Marshal.SizeOf(typeof(T));
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
/// <summary>
|
|
/// Read a text file to an array of string, each row are separated using by the input separator
|
|
/// </summary>
|
|
/// <param name="fileName">The text file to read from</param>
|
|
/// <param name="seperator">The row separator</param>
|
|
/// <returns></returns>
|
|
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();
|
|
}*/
|
|
|
|
/// <summary>
|
|
/// Merges two byte vector into one
|
|
/// </summary>
|
|
/// <param name="a">the first byte vector to be merged</param>
|
|
/// <param name="b">the second byte vector to be merged</param>
|
|
/// <returns>The bytes that is a concatenation of a and b</returns>
|
|
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;
|
|
}
|
|
|
|
#if WINDOWS_PHONE_APP
|
|
|
|
[DllImport("PhoneAppModelHost.dll", SetLastError = true)]
|
|
private static extern IntPtr LoadPackagedLibrary(
|
|
[MarshalAs(UnmanagedType.LPStr)]
|
|
String fileName,
|
|
int dwFlags);
|
|
#elif NETFX_CORE || NETSTANDARD1_4
|
|
[DllImport("Kernel32.dll", SetLastError = true)]
|
|
private static extern IntPtr LoadPackagedLibrary(
|
|
[MarshalAs(UnmanagedType.LPStr)]
|
|
String fileName,
|
|
int dwFlags);
|
|
|
|
#else
|
|
/// <summary>
|
|
/// Call a command from command line
|
|
/// </summary>
|
|
/// <param name="execFileName">The name of the executable</param>
|
|
/// <param name="arguments">The arguments to the executable</param>
|
|
/// <returns>The standard output</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use reflection to find the base type. If such type do not exist, null is returned
|
|
/// </summary>
|
|
/// <param name="currentType">The type to search from</param>
|
|
/// <param name="baseClassName">The name of the base class to search</param>
|
|
/// <returns>The base type</returns>
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
#region memory copy
|
|
/// <summary>
|
|
/// Convert some generic vector to vector of Bytes
|
|
/// </summary>
|
|
/// <typeparam name="TData">type of the input vector</typeparam>
|
|
/// <param name="data">array of data</param>
|
|
/// <returns>the byte vector</returns>
|
|
public static Byte[] ToBytes<TData>(TData[] data)
|
|
{
|
|
#if NETFX_CORE || NETSTANDARD1_4
|
|
int size = Marshal.SizeOf<TData>() * data.Length;
|
|
#else
|
|
int size = Marshal.SizeOf(typeof(TData)) * data.Length;
|
|
#endif
|
|
Byte[] res = new Byte[size];
|
|
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.Copy(handle.AddrOfPinnedObject(), res, 0, size);
|
|
handle.Free();
|
|
return res;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform first degree interpolation give the sorted data <paramref name="src"/> and the interpolation <paramref name="indexes"/>
|
|
/// </summary>
|
|
/// <param name="src">The sorted data that will be interpolated from</param>
|
|
/// <param name="indexes">The indexes of the interpolate result</param>
|
|
/// <returns></returns>
|
|
public static IEnumerable<T> LinearInterpolate<T>(IEnumerable<T> src, IEnumerable<double> indexes) where T:IInterpolatable<T>, new()
|
|
{
|
|
using (IEnumerator<T> 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get subsamples with the specific rate
|
|
/// </summary>
|
|
/// <param name="src">The source which the subsamples will be derived from</param>
|
|
/// <param name="subsampleRate">The subsample rate</param>
|
|
/// <returns><paramref name="src"/> subsampled with the specific rate </returns>
|
|
public static IEnumerable<T> LinearSubsample<T>(IEnumerable<T> src, double subsampleRate) where T : IInterpolatable<T>, new()
|
|
{
|
|
using (IEnumerator<T> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Joining multiple index ascending IInterpolatables together as a single index ascending IInterpolatable.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of objects that will be joined</typeparam>
|
|
/// <param name="enums">The enumerables, each should be stored in index ascending order</param>
|
|
/// <returns>A single enumerable sorted in index ascending order</returns>
|
|
public static IEnumerable<T> JoinInterpolatables<T>(params IEnumerable<T>[] enums) where T : IInterpolatable<T>, 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<T>[] lower = new IEnumerable<T>[middle];
|
|
IEnumerable<T>[] upper = new IEnumerable<T>[enums.Length - middle];
|
|
Array.Copy(enums, lower, middle);
|
|
Array.Copy(enums, middle, upper, 0, enums.Length - middle);
|
|
|
|
foreach (T sample in JoinTwoInterpolatables<T>(JoinInterpolatables<T>(lower), JoinInterpolatables<T>(upper)))
|
|
yield return sample;
|
|
}
|
|
}
|
|
|
|
private static IEnumerable<T> JoinTwoInterpolatables<T>(IEnumerable<T> enum1, IEnumerable<T> enum2) where T : IInterpolatable<T>, new()
|
|
{
|
|
IEnumerator<T> l1 = enum1.GetEnumerator();
|
|
IEnumerator<T> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
/// <summary>
|
|
/// Use the two IInterpolatable and the index to perform first degree interpolation
|
|
/// </summary>
|
|
/// <param name="i1">The first element to interpolate from</param>
|
|
/// <param name="i2">The second eleemnt to interpolate from</param>
|
|
/// <param name="index">The interpolation index</param>
|
|
/// <returns>The interpolatation result</returns>
|
|
private static T LinearInterpolate<T>(T i1, T i2, double index) where T : IInterpolatable<T>, 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;
|
|
}*/
|
|
|
|
/*
|
|
/// <summary>
|
|
/// memcpy function
|
|
/// </summary>
|
|
/// <param name="dest">the destination of memory copy</param>
|
|
/// <param name="src">the source of memory copy</param>
|
|
/// <param name="len">the number of bytes to be copied</param>
|
|
#if (__IOS__ || __ANDROID__ || UNITY_IPHONE || UNITY_ANDROID || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX) && (!UNITY_EDITOR_WIN)
|
|
[DllImport("c", EntryPoint = "memcpy")]
|
|
public static extern void memcpy(IntPtr dest, IntPtr src, int len);
|
|
#elif WINDOWS_PHONE_APP
|
|
//[DllImport("PhoneAppModelHost.dll", EntryPoint = "CopyMemory")]
|
|
//public static extern void memcpy(IntPtr dest, IntPtr src, int len);
|
|
|
|
public static void memcpy(IntPtr dest, IntPtr src, int len)
|
|
{
|
|
Marshal.Copy()
|
|
}
|
|
#else
|
|
[DllImport("kernel32.dll", EntryPoint = "CopyMemory")]
|
|
public static extern void memcpy(IntPtr dest, IntPtr src, int len);
|
|
#endif
|
|
*/
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Maps the specified executable module into the address space of the calling process.
|
|
/// </summary>
|
|
/// <param name="dllname">The name of the dll</param>
|
|
/// <returns>The handle to the library</returns>
|
|
public static IntPtr LoadLibrary(String dllname)
|
|
{
|
|
#if UNITY_EDITOR_WIN
|
|
const int loadLibrarySearchDllLoadDir = 0x00000100;
|
|
const int loadLibrarySearchDefaultDirs = 0x00001000;
|
|
return LoadLibraryEx(dllname, IntPtr.Zero, loadLibrarySearchDllLoadDir | loadLibrarySearchDefaultDirs);
|
|
#elif NETFX_CORE
|
|
IntPtr handler = LoadPackagedLibrary(dllname, 0);
|
|
|
|
if (handler == IntPtr.Zero)
|
|
{
|
|
int error = Marshal.GetLastWin32Error();
|
|
|
|
System.Diagnostics.Debug.WriteLine(String.Format("Error loading {0}: error code {1}", dllname, (uint)error));
|
|
}
|
|
|
|
return handler;
|
|
#else
|
|
if (Platform.OperationSystem == TypeEnum.OS.Windows)
|
|
{
|
|
//if (Platform.ClrType == TypeEnum.ClrType.NetFxCore)
|
|
{
|
|
const int loadLibrarySearchDllLoadDir = 0x00000100;
|
|
const int loadLibrarySearchDefaultDirs = 0x00001000;
|
|
//const int loadLibrarySearchUserDirs = 0x00000400;
|
|
IntPtr handler = LoadLibraryEx(dllname, IntPtr.Zero, loadLibrarySearchDllLoadDir | loadLibrarySearchDefaultDirs);
|
|
//IntPtr handler = LoadLibraryEx(dllname, IntPtr.Zero, loadLibrarySearchUserDirs);
|
|
if (handler == IntPtr.Zero)
|
|
{
|
|
int error = Marshal.GetLastWin32Error();
|
|
|
|
System.ComponentModel.Win32Exception ex = new System.ComponentModel.Win32Exception(error);
|
|
System.Diagnostics.Debug.WriteLine(String.Format("LoadLibraryEx {0} failed with error code {1}: {2}", dllname, (uint)error, ex.Message));
|
|
if (error == 5)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine(String.Format("Please check if the current user has execute permission for file: {0} ", dllname));
|
|
}
|
|
}
|
|
return handler;
|
|
} //else
|
|
//return WinAPILoadLibrary(dllname);
|
|
} else
|
|
{
|
|
return Dlopen(dllname, 2); // 2 == RTLD_NOW
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if !NETFX_CORE
|
|
[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);
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
/// <param name="handle">The handle to the library</param>
|
|
/// <returns>If the function succeeds, the return value is true. If the function fails, the return value is false.</returns>
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool FreeLibrary(IntPtr handle);
|
|
|
|
/// <summary>
|
|
/// Adds a directory to the search path used to locate DLLs for the application
|
|
/// </summary>
|
|
/// <param name="path">The directory to be searched for DLLs</param>
|
|
/// <returns>True if success</returns>
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool SetDllDirectory(String path);
|
|
#endif
|
|
}
|
|
}
|