using NTwain.Properties; using NTwain.Values; using System; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Text; namespace NTwain.Data { //// This file contains custom logic added to the twain types. //// Separating the field definitions out makes finding all the //// custom code logic easier. Mostly this is just making the fields //// into .net friendly properties. //// potentially unit tests for the twain types only need to target //// code in this file since everything else is just interop and //// field definitions (pretty much have to hope it's correct). /// /// Stores a fixed point number. This can be implicitly converted /// to a float in dotnet. /// public partial struct TWFix32 : IEquatable, IConvertible { // the conversion logic is found in the spec. float ToFloat() { return (float)_whole + _frac / 65536f; } TWFix32(float value) { //int temp = (int)(value * 65536.0 + 0.5); //_whole = (short)(temp >> 16); //_frac = (ushort)(temp & 0x0000ffff); // different version from twain faq bool sign = value < 0; int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5)); _whole = (short)(temp >> 16); _frac = (ushort)(temp & 0x0000ffff); } /// /// The Whole part of the floating point number. This number is signed. /// public short Whole { get { return _whole; } set { _whole = value; } } /// /// The Fractional part of the floating point number. This number is unsigned. /// public ushort Fraction { get { return _frac; } set { _frac = value; } } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return ToFloat().ToString(CultureInfo.InvariantCulture); } #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWFix32)) return false; return Equals((TWFix32)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWFix32 other) { return _whole == other._whole && _frac == other._frac; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _whole ^ _frac; } #endregion #region static stuff /// /// Performs an implicit conversion from to . /// /// The value. /// The result of the conversion. public static implicit operator float(TWFix32 value) { return value.ToFloat(); } /// /// Performs an implicit conversion from to . /// /// The value. /// The result of the conversion. public static implicit operator TWFix32(float value) { return new TWFix32(value); } /// /// Implements the operator ==. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator ==(TWFix32 value1, TWFix32 value2) { return value1.Equals(value2); } /// /// Implements the operator !=. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator !=(TWFix32 value1, TWFix32 value2) { return !value1.Equals(value2); } #endregion #region IConvertable TypeCode IConvertible.GetTypeCode() { return TypeCode.Single; } bool IConvertible.ToBoolean(IFormatProvider provider) { return this != 0; } byte IConvertible.ToByte(IFormatProvider provider) { return Convert.ToByte((float)this); } char IConvertible.ToChar(IFormatProvider provider) { return Convert.ToChar((float)this); } DateTime IConvertible.ToDateTime(IFormatProvider provider) { return Convert.ToDateTime((float)this); } decimal IConvertible.ToDecimal(IFormatProvider provider) { return Convert.ToDecimal((float)this); } double IConvertible.ToDouble(IFormatProvider provider) { return Convert.ToDouble((float)this); } short IConvertible.ToInt16(IFormatProvider provider) { return Convert.ToInt16((float)this); } int IConvertible.ToInt32(IFormatProvider provider) { return Convert.ToInt32((float)this); } long IConvertible.ToInt64(IFormatProvider provider) { return Convert.ToInt64((float)this); } sbyte IConvertible.ToSByte(IFormatProvider provider) { return Convert.ToSByte((float)this); } float IConvertible.ToSingle(IFormatProvider provider) { return Convert.ToSingle((float)this); } string IConvertible.ToString(IFormatProvider provider) { return this.ToString(); } object IConvertible.ToType(Type conversionType, IFormatProvider provider) { return Convert.ChangeType((float)this, conversionType); } ushort IConvertible.ToUInt16(IFormatProvider provider) { return Convert.ToUInt16((float)this); } uint IConvertible.ToUInt32(IFormatProvider provider) { return Convert.ToUInt32((float)this); } ulong IConvertible.ToUInt64(IFormatProvider provider) { return Convert.ToUInt64((float)this); } #endregion } /// /// Embedded in the structure. /// Defines a frame rectangle in ICapUnits coordinates. /// public partial struct TWFrame : IEquatable { #region properties /// /// Value of the left-most edge of the rectangle. /// public float Left { get { return _left; } set { _left = value; } } /// /// Value of the top-most edge of the rectangle. /// public float Top { get { return _top; } set { _top = value; } } /// /// Value of the right-most edge of the rectangle. /// public float Right { get { return _right; } set { _right = value; } } /// /// Value of the bottom-most edge of the rectangle. /// public float Bottom { get { return _bottom; } set { _bottom = value; } } #endregion /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "L={0}, T={1}, R={2}, B={3}", Left, Top, Right, Bottom); } #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWFrame)) return false; return Equals((TWFrame)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWFrame other) { return _left == other._left && _top == other._top && _right == other._right && _bottom == other._bottom; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _left.GetHashCode() ^ _top.GetHashCode() ^ _right.GetHashCode() ^ _bottom.GetHashCode(); } #endregion #region static stuff /// /// Implements the operator ==. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator ==(TWFrame value1, TWFrame value2) { return value1.Equals(value2); } /// /// Implements the operator !=. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator !=(TWFrame value1, TWFrame value2) { return !value1.Equals(value2); } #endregion } /// /// Embedded in the structure that is embedded in the /// structure. Defines the parameters used for channel-specific transformation. The transform can be /// described either as an extended form of the gamma function or as a table look-up with linear /// interpolation. /// public partial struct TWDecodeFunction : IEquatable { #region properties /// /// Starting input value of the extended gamma function. Defines the /// minimum input value of channel data. /// public float StartIn { get { return _startIn; } set { _startIn = value; } } /// /// Ending input value of the extended gamma function. Defines the maximum /// input value of channel data. /// public float BreakIn { get { return _breakIn; } set { _breakIn = value; } } /// /// The input value at which the transform switches from linear /// transformation/interpolation to gamma transformation. /// public float EndIn { get { return _endIn; } set { _endIn = value; } } /// /// Starting output value of the extended gamma function. Defines the /// minimum output value of channel data. /// public float StartOut { get { return _startOut; } set { _startOut = value; } } /// /// Ending output value of the extended gamma function. Defines the /// maximum output value of channel data. /// public float BreakOut { get { return _breakOut; } set { _breakOut = value; } } /// /// The output value at which the transform switches from linear /// transformation/interpolation to gamma transformation. /// public float EndOut { get { return _endOut; } set { _endOut = value; } } /// /// Constant value. The exponential used in the gamma function. /// public float Gamma { get { return _gamma; } set { _gamma = value; } } /// /// The number of samples in the look-up table. Includes the values of StartIn /// and EndIn. Zero-based index (actually, number of samples - 1). If zero, use /// extended gamma, otherwise use table look-up. /// public float SampleCount { get { return _sampleCount; } set { _sampleCount = value; } } #endregion #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWDecodeFunction)) return false; return Equals((TWDecodeFunction)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWDecodeFunction other) { return _startIn == other._startIn && _startOut == other._startOut && _breakIn == other._breakIn && _breakOut == other._breakOut && _endIn == other._endIn && _endOut == other._endOut && _gamma == other._gamma && _sampleCount == other._sampleCount; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _startIn.GetHashCode() ^ _startOut.GetHashCode() ^ _breakIn.GetHashCode() ^ _breakOut.GetHashCode() ^ _endIn.GetHashCode() ^ _endOut.GetHashCode() ^ _gamma.GetHashCode() ^ _sampleCount.GetHashCode(); } #endregion #region static stuff /// /// Implements the operator ==. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator ==(TWDecodeFunction value1, TWDecodeFunction value2) { return value1.Equals(value2); } /// /// Implements the operator !=. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator !=(TWDecodeFunction value1, TWDecodeFunction value2) { return !value1.Equals(value2); } #endregion } /// /// Specifies the parametrics used for either the ABC or LMN transform stages. /// public partial struct TWTransformStage { /// /// Channel-specific transform parameters. /// public TWDecodeFunction[] Decode { get { return _decode; } set { _decode = value; } } /// /// Flattened 3x3 matrix that specifies how channels are mixed in. /// public TWFix32[] Mix { get { return _mix; } set { _mix = value; } } /// /// Gets the value as matrix. /// /// public TWFix32[,] GetMixMatrix() { // from http://stackoverflow.com/questions/3845235/convert-array-to-matrix, haven't tested it TWFix32[,] mat = new TWFix32[3, 3]; Buffer.BlockCopy(_mix, 0, mat, 0, _mix.Length * 4); return mat; } } /// /// Stores a group of associated individual values for a capability. /// The values need have no relationship to one another aside from /// being used to describe the same "value" of the capability /// public partial class TWArray { /// /// The type of items in the array. All items in the array have the same size. /// public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } } ///// ///// How many items are in the array. ///// //public int Count { get { return (int)_numItems; } set { _numItems = (uint)value; } } /// /// Array of ItemType values starts here. /// public object[] ItemList { get { return _itemList; } set { _itemList = value; if (value != null) { _numItems = (uint)value.Length; } else { _numItems = 0; } } } } /// /// Used to get audio info. /// public partial class TWAudioInfo { /// /// Name of audio data. /// public string Name { get { return _name; } } } /// /// Used in Callback mechanism for sending messages from the Source to the Application. /// Applications version 2.2 or higher must use . /// partial class TWCallback { /// /// Initializes a new instance of the class. /// /// The callback function’s entry point. public TWCallback(CallbackDelegate callback) { _callBackProc = callback; } /// /// An application defined reference constant. /// /// /// The reference constant. /// public uint RefCon { get { return _refCon; } set { _refCon = value; } } /// /// Initialized to any valid DG_CONTROL / DAT_NULL message. /// /// /// The message. /// public short Message { get { return _message; } set { _message = value; } } } /// /// Used in the Callback mechanism for sending messages from the Source to the Application. /// partial class TWCallback2 { /// /// Initializes a new instance of the class. /// /// The callback function’s entry point. public TWCallback2(CallbackDelegate callback) { _callBackProc = callback; } /// /// An application defined reference constant. It has a different size on different /// platforms. /// /// /// The reference constant. /// public UIntPtr RefCon { get { return _refCon; } set { _refCon = value; } } /// /// Initialized to any valid DG_CONTROL / DAT_NULL message. /// /// /// The message. /// public short Message { get { return _message; } set { _message = value; } } } /// /// Used by an application either to get information about, or control the setting of a capability. /// public sealed partial class TWCapability : IDisposable { #region ctors /// /// Initializes a new instance of the class. /// /// The capability. public TWCapability(CapabilityId capability) { Capability = capability; ContainerType = Values.ContainerType.DontCare; } /// /// Initializes a new instance of the class. /// /// The capability. /// The value. [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] public TWCapability(CapabilityId capability, TWOneValue value) { Capability = capability; ContainerType = Values.ContainerType.OneValue; SetOneValue(value); } /// /// Initializes a new instance of the class. /// /// The capability. /// The value. [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] public TWCapability(CapabilityId capability, TWEnumeration value) { Capability = capability; ContainerType = Values.ContainerType.Enum; SetEnumValue(value); } /// /// Initializes a new instance of the class. /// /// The capability. /// The value. [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] public TWCapability(CapabilityId capability, TWRange value) { Capability = capability; ContainerType = Values.ContainerType.Range; SetRangeValue(value); } #endregion #region properties /// /// Id of capability to set or get. /// public CapabilityId Capability { get { return (CapabilityId)_cap; } set { _cap = (ushort)value; } } /// /// The type of the container structure referenced by the pointer internally. The container /// will be one of four types: , , /// , or . /// public ContainerType ContainerType { get { return (Values.ContainerType)_conType; } set { _conType = (ushort)value; } } #endregion #region value functions /// /// Gets the stored in this capability. /// /// /// public TWOneValue GetOneValue() { if (ContainerType != Values.ContainerType.OneValue) { throw new ArgumentException(Resources.BadContainerType, "value"); } var value = new TWOneValue(); if (_hContainer != IntPtr.Zero) { IntPtr baseAddr = MemoryManager.Instance.Lock(_hContainer); try { int offset = 0; value.ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; value.Item = (uint)ReadValue(baseAddr, ref offset, ItemType.UInt32); } catch { } MemoryManager.Instance.Unlock(_hContainer); } return value; } [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] void SetOneValue(TWOneValue value) { if (value == null) { throw new ArgumentNullException("value"); } if (ContainerType != Values.ContainerType.OneValue) { throw new ArgumentException(Resources.BadContainerType, "value"); } // since one value can only house UInt32 we will not allow type size > 4 if (GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException("Invalid one value type"); } _hContainer = MemoryManager.Instance.Allocate((uint)Marshal.SizeOf(value)); if (_hContainer != IntPtr.Zero) { Marshal.StructureToPtr(value, _hContainer, false); } } /// /// Gets the stored in this capability. /// /// /// public TWArray GetArrayValue() { if (ContainerType != Values.ContainerType.Array) { throw new ArgumentException(Resources.BadContainerType, "value"); } var value = new TWArray(); if (_hContainer != IntPtr.Zero) { IntPtr baseAddr = MemoryManager.Instance.Lock(_hContainer); int offset = 0; value.ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; var count = Marshal.ReadInt32(baseAddr, offset); offset += 4; if (count > 0) { value.ItemList = new object[count]; for (int i = 0; i < count; i++) { value.ItemList[i] = ReadValue(baseAddr, ref offset, value.ItemType); } } MemoryManager.Instance.Unlock(_hContainer); } return value; } /// /// Gets the stored in this capability. /// /// /// public TWEnumeration GetEnumValue() { if (ContainerType != Values.ContainerType.Enum) { throw new ArgumentException(Resources.BadContainerType, "value"); } var value = new TWEnumeration(); if (_hContainer != IntPtr.Zero) { IntPtr baseAddr = MemoryManager.Instance.Lock(_hContainer); int offset = 0; value.ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; int count = Marshal.ReadInt32(baseAddr, offset); offset += 4; value.CurrentIndex = Marshal.ReadInt32(baseAddr, offset); offset += 4; value.DefaultIndex = Marshal.ReadInt32(baseAddr, offset); offset += 4; if (count > 0) { value.ItemList = new object[count]; for (int i = 0; i < count; i++) { value.ItemList[i] = ReadValue(baseAddr, ref offset, value.ItemType); } } MemoryManager.Instance.Unlock(_hContainer); } return value; } [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] void SetEnumValue(TWEnumeration value) { if (value == null) { throw new ArgumentNullException("value"); } if (ContainerType != Values.ContainerType.Enum) { throw new ArgumentException(Resources.BadContainerType, "value"); } Int32 valueSize = value.ItemOffset + value.ItemList.Length * GetItemTypeSize(value.ItemType); int offset = 0; _hContainer = MemoryManager.Instance.Allocate((uint)valueSize); IntPtr baseAddr = MemoryManager.Instance.Lock(_hContainer); // can't safely use StructureToPtr here so write it our own WriteValue(baseAddr, ref offset, ItemType.UInt16, value.ItemType); WriteValue(baseAddr, ref offset, ItemType.UInt32, (uint)value.ItemList.Length); WriteValue(baseAddr, ref offset, ItemType.UInt32, value.CurrentIndex); WriteValue(baseAddr, ref offset, ItemType.UInt32, value.DefaultIndex); foreach (var item in value.ItemList) { WriteValue(baseAddr, ref offset, value.ItemType, item); } MemoryManager.Instance.Unlock(_hContainer); } /// /// Gets the stored in this capability. /// /// /// public TWRange GetRangeValue() { if (ContainerType != Values.ContainerType.Range) { throw new ArgumentException(Resources.BadContainerType, "value"); } var value = new TWRange(); if (_hContainer != IntPtr.Zero) { IntPtr baseAddr = MemoryManager.Instance.Lock(_hContainer); int offset = 0; value.ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; value.MinValue = (uint)Marshal.ReadInt32(baseAddr, offset); offset += 4; value.MaxValue = (uint)Marshal.ReadInt32(baseAddr, offset); offset += 4; value.StepSize = (uint)Marshal.ReadInt32(baseAddr, offset); offset += 4; value.DefaultValue = (uint)Marshal.ReadInt32(baseAddr, offset); offset += 4; value.CurrentValue = (uint)Marshal.ReadInt32(baseAddr, offset); MemoryManager.Instance.Unlock(_hContainer); } return value; } [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] void SetRangeValue(TWRange value) { if (value == null) { throw new ArgumentNullException("value"); } if (ContainerType != Values.ContainerType.Range) { throw new ArgumentException(Resources.BadContainerType, "value"); } // since range value can only house UInt32 we will not allow type size > 4 if (GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException("Invalid range value type"); } _hContainer = MemoryManager.Instance.Allocate((uint)Marshal.SizeOf(value)); if (_hContainer != IntPtr.Zero) { Marshal.StructureToPtr(value, _hContainer, false); } } #endregion #region readwrites /// /// Gets the byte size of the item type. /// /// /// private int GetItemTypeSize(ItemType type) { switch (type) { case ItemType.Int8: case ItemType.UInt8: return 1; case ItemType.UInt16: case ItemType.Int16: case ItemType.Bool: return 2; case ItemType.Int32: case ItemType.UInt32: case ItemType.Fix32: return 4; case ItemType.Frame: return 16; case ItemType.String32: return TwainConst.String32; case ItemType.String64: return TwainConst.String64; case ItemType.String128: return TwainConst.String128; case ItemType.String255: return TwainConst.String255; // deprecated //case ItemType.String1024: // return TwainConst.String1024; //case ItemType.Unicode512: // return TwainConst.String1024; } return 0; } /// /// Entry call for writing values to a pointer. /// /// /// /// /// [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] void WriteValue(IntPtr baseAddr, ref int offset, ItemType type, object value) { switch (type) { case ItemType.Int8: case ItemType.UInt8: Marshal.WriteByte(baseAddr, offset, Convert.ToByte(value));// (byte)value); break; case ItemType.Bool: case ItemType.Int16: case ItemType.UInt16: Marshal.WriteInt16(baseAddr, offset, Convert.ToInt16(value));//(short)value); break; case ItemType.UInt32: case ItemType.Int32: Marshal.WriteInt32(baseAddr, offset, Convert.ToInt32(value));//(int)value); break; case ItemType.Fix32: TWFix32 f32 = (TWFix32)value; Marshal.WriteInt16(baseAddr, offset, f32.Whole); if (f32.Fraction > Int16.MaxValue) { Marshal.WriteInt16(baseAddr, offset + 2, (Int16)(f32.Fraction - 32768)); } else { Marshal.WriteInt16(baseAddr, offset + 2, (Int16)f32.Fraction); } break; case ItemType.Frame: TWFrame frame = (TWFrame)value; WriteValue(baseAddr, ref offset, ItemType.Fix32, frame.Left); WriteValue(baseAddr, ref offset, ItemType.Fix32, frame.Top); WriteValue(baseAddr, ref offset, ItemType.Fix32, frame.Right); WriteValue(baseAddr, ref offset, ItemType.Fix32, frame.Bottom); return; // no need to update offset for this //case ItemType.String1024: // WriteString(baseAddr, offset, value as string, 1024); // break; case ItemType.String128: WriteString(baseAddr, offset, value as string, 128); break; case ItemType.String255: WriteString(baseAddr, offset, value as string, 255); break; case ItemType.String32: WriteString(baseAddr, offset, value as string, 32); break; case ItemType.String64: WriteString(baseAddr, offset, value as string, 64); break; //case ItemType.Unicode512: // WriteUString(baseAddr, offset, value as string, 512); // break; } offset += GetItemTypeSize(type); } /// /// Writes string value. /// /// /// /// /// private void WriteString(IntPtr baseAddr, int offset, string item, int maxLength) { if (string.IsNullOrEmpty(item)) { // write zero Marshal.WriteByte(baseAddr, offset, 0); } else { for (int i = 0; i < maxLength; i++) { if (i == item.Length) { // string end reached, so write \0 and quit Marshal.WriteByte(baseAddr, offset, 0); return; } else { Marshal.WriteByte(baseAddr, offset, (byte)item[i]); offset++; } } // when ended normally also write \0 Marshal.WriteByte(baseAddr, offset, 0); } } ///// ///// Writes unicode string value. ///// ///// ///// ///// ///// //[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] //private void WriteUString(IntPtr baseAddr, int offset, string item, int maxLength) //{ // if (string.IsNullOrEmpty(item)) // { // // write zero // Marshal.WriteInt16(baseAddr, offset, (char)0); // } // else // { // // use 2 bytes per char // for (int i = 0; i < maxLength; i++) // { // if (i == item.Length) // { // // string end reached, so write \0 and quit // Marshal.WriteInt16(baseAddr, offset, (char)0); // return; // } // else // { // Marshal.WriteInt16(baseAddr, offset, item[i]); // offset += 2; // } // } // // when ended normally also write \0 // Marshal.WriteByte(baseAddr, offset, 0); // } //} /// /// Entry call for reading values. /// /// /// /// /// private object ReadValue(IntPtr baseAddr, ref int offset, ItemType type) { object val = null; switch (type) { case ItemType.Int8: case ItemType.UInt8: val = Marshal.ReadByte(baseAddr, offset); break; case ItemType.Bool: case ItemType.UInt16: val = (ushort)Marshal.ReadInt16(baseAddr, offset); break; case ItemType.Int16: val = Marshal.ReadInt16(baseAddr, offset); break; case ItemType.UInt32: val = (uint)Marshal.ReadInt32(baseAddr, offset); break; case ItemType.Int32: val = Marshal.ReadInt32(baseAddr, offset); break; case ItemType.Fix32: TWFix32 f32 = new TWFix32(); f32.Whole = Marshal.ReadInt16(baseAddr, offset); f32.Fraction = (ushort)Marshal.ReadInt16(baseAddr, offset + 2); val = f32; break; case ItemType.Frame: TWFrame frame = new TWFrame(); frame.Left = (TWFix32)ReadValue(baseAddr, ref offset, ItemType.Fix32); frame.Top = (TWFix32)ReadValue(baseAddr, ref offset, ItemType.Fix32); frame.Right = (TWFix32)ReadValue(baseAddr, ref offset, ItemType.Fix32); frame.Bottom = (TWFix32)ReadValue(baseAddr, ref offset, ItemType.Fix32); return frame; // no need to update offset for this //case ItemType.String1024: // val = ReadString(baseAddr, offset, 1024); // break; case ItemType.String128: val = ReadString(baseAddr, offset, 128); break; case ItemType.String255: val = ReadString(baseAddr, offset, 255); break; case ItemType.String32: val = ReadString(baseAddr, offset, 32); break; case ItemType.String64: val = ReadString(baseAddr, offset, 64); break; //case ItemType.Unicode512: // val = ReadUString(baseAddr, offset, 512); // break; } offset += GetItemTypeSize(type); return val; } /// /// Read string value. /// /// /// /// /// private object ReadString(IntPtr baseAddr, int offset, int maxLength) { StringBuilder sb = new StringBuilder(maxLength); for (int i = 0; i < maxLength; i++) { byte b; while ((b = Marshal.ReadByte(baseAddr, offset)) != 0) { sb.Append((char)b); offset++; } } return sb.ToString(); } /// /// Read unicode string value. /// /// /// /// /// private object ReadUString(IntPtr baseAddr, int offset, int maxLength) { StringBuilder sb = new StringBuilder(maxLength); for (int i = 0; i < maxLength; i++) { char c; while ((c = (char)Marshal.ReadInt16(baseAddr, offset)) != 0) { sb.Append(c); offset += 2; } } return sb.ToString(); } #endregion #region IDisposable Members /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { if (_hContainer != IntPtr.Zero) { MemoryManager.Instance.Free(_hContainer); _hContainer = IntPtr.Zero; } GC.SuppressFinalize(this); } /// /// Finalizes an instance of the class. /// ~TWCapability() { if (_hContainer != IntPtr.Zero) { MemoryManager.Instance.Free(_hContainer); _hContainer = IntPtr.Zero; } } #endregion } /// /// Embedded in the structure; /// defines a CIE XYZ space tri-stimulus value. /// public partial struct TWCiePoint : IEquatable { #region properties /// /// First tri-stimulus value of the CIE space representation. /// public float X { get { return _z; } } /// /// Second tri-stimulus value of the CIE space representation. /// public float Y { get { return _z; } } /// /// Third tri-stimulus value of the CIE space representation. /// public float Z { get { return _z; } } #endregion #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWCiePoint)) return false; return Equals((TWCiePoint)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWCiePoint other) { return _x == other._x && _y == other._y && _z == other._z; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode(); } #endregion #region static stuff /// /// Implements the operator ==. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator ==(TWCiePoint value1, TWCiePoint value2) { return value1.Equals(value2); } /// /// Implements the operator !=. /// /// The value1. /// The value2. /// The result of the operator. public static bool operator !=(TWCiePoint value1, TWCiePoint value2) { return !value1.Equals(value2); } #endregion } /// /// Defines the mapping from an RGB color space device into CIE 1931 (XYZ) color space. /// public partial class TWCieColor { /// /// Defines the original color space that was transformed into CIE XYZ. /// This value is not set-able by the application. /// Application should write into this on a set. /// public ushort ColorSpace { get { return _colorSpace; } set { _colorSpace = value; } } /// /// Used to indicate which data byte is taken first. If zero, then high byte is /// first. If non-zero, then low byte is first. /// public short LowEndian { get { return _lowEndian; } set { _lowEndian = value; } } /// /// If non-zero then color data is device-dependent and only ColorSpace is /// valid in this structure. /// public short DeviceDependent { get { return _deviceDependent; } set { _deviceDependent = value; } } /// /// Version of the color space descriptor specification used to define the /// transform data. The current version is zero. /// public int VersionNumber { get { return _versionNumber; } set { _versionNumber = value; } } /// /// Describes parametrics for the first stage transformation of the Postscript /// Level 2 CIE color space transform process. /// public TWTransformStage StageABC { get { return _stageABC; } set { _stageABC = value; } } /// /// Describes parametrics for the first stage transformation of the Postscript /// Level 2 CIE color space transform process. /// public TWTransformStage StageLMN { get { return _stageLMN; } set { _stageLMN = value; } } /// /// Values that specify the CIE 1931 (XYZ space) tri-stimulus value of the /// diffused white point. /// public TWCiePoint WhitePoint { get { return _whitePoint; } set { _whitePoint = value; } } /// /// Values that specify the CIE 1931 (XYZ space) tri-stimulus value of the /// diffused black point. /// public TWCiePoint BlackPoint { get { return _blackPoint; } set { _blackPoint = value; } } /// /// Values that specify the CIE 1931 (XYZ space) tri-stimulus value of inkless /// "paper" from which the image was acquired. /// public TWCiePoint WhitePaper { get { return _whitePaper; } set { _whitePaper = value; } } /// /// Values that specify the CIE 1931 (XYZ space) tri-stimulus value of solid /// black ink on the "paper" from which the image was acquired. /// public TWCiePoint BlackInk { get { return _blackInk; } set { _blackInk = value; } } /// /// Optional table look-up values used by the decode function. Samples /// are ordered sequentially and end-to-end as A, B, C, L, M, and N. /// public TWFix32[] Samples { get { return _samples; } set { _samples = value; } } } /// /// Allows for a data source and application to pass custom data to each other. /// public partial class TWCustomDSData { /// /// Length, in bytes, of data. /// public uint InfoLength { get { return _infoLength; } set { _infoLength = value; } } /// /// Handle to memory containing InfoLength bytes of data. /// public IntPtr hData { get { return _hData; } set { _hData = value; } } } /// /// Provides information about the Event that was raised by the Source. The Source should only fill /// in those fields applicable to the Event. The Application must only read those fields applicable to /// the Event. /// public partial class TWDeviceEvent { /// /// Defines event that has taken place. /// public DeviceEvent Event { get { return (DeviceEvent)_event; } } /// /// The name of the device that generated the event. /// public string DeviceName { get { return _deviceName; } } /// /// Battery minutes remaining. Valid for BatteryCheck event only. /// public int BatteryMinutes { get { return (int)_batteryMinutes; } } /// /// Battery percentage remaining. Valid for BatteryCheck event only. /// public int BatteryPercentage { get { return (int)_batteryPercentage; } } /// /// Current power supply in use. Valid for PowerSupply event only. /// public int PowerSupply { get { return (int)_powerSupply; } } /// /// Current X Resolution. Valid for Resolution event only. /// public float XResolution { get { return _xResolution; } } /// /// Current Y Resolution. Valid for Resolution event only. /// public float YResolution { get { return _yResolution; } } /// /// Current flash setting. Valid for BatteryCheck event only. /// public FlashedUsed FlashUsed2 { get { return (FlashedUsed)_flashUsed2; } } /// /// Number of images camera will capture. Valid for AutomaticCapture event only. /// public int AutomaticCapture { get { return (int)_automaticCapture; } } /// /// Number of seconds before first capture. Valid for AutomaticCapture event only. /// public int TimeBeforeFirstCapture { get { return (int)_timeBeforeFirstCapture; } } /// /// Hundredths of a second between captures. Valid for AutomaticCapture event only. /// public int TimeBetweenCaptures { get { return (int)_timeBetweenCaptures; } } } /// /// Embedded in the , , and structures. /// This structure holds the tri-stimulus color palette information for structures. /// The order of the channels shall match their alphabetic representation. That is, for RGB data, R /// shall be channel 1. For CMY data, C shall be channel 1. This allows the application and Source /// to maintain consistency. Grayscale data will have the same values entered in all three channels. /// public partial struct TWElement8 : IEquatable { /// /// Value used to index into the color table. /// public byte Index { get { return _index; } set { _index = value; } } /// /// First tri-stimulus value (e.g. Red). /// public byte Channel1 { get { return _channel1; } set { _channel1 = value; } } /// /// Second tri-stimulus value (e.g Green). /// public byte Channel2 { get { return _channel2; } set { _channel2 = value; } } /// /// Third tri-stimulus value (e.g Blue). /// public byte Channel3 { get { return _channel3; } set { _channel3 = value; } } #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWElement8)) return false; return Equals((TWElement8)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWElement8 other) { return _channel1 == other._channel1 && _channel2 == other._channel2 && _channel3 == other._channel3 && _index == other._index; } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _channel1.GetHashCode() ^ _channel2.GetHashCode() ^ _channel3.GetHashCode() ^ _index.GetHashCode(); } /// /// Check for value equality. /// /// The v1. /// The v2. /// public static bool operator ==(TWElement8 v1, TWElement8 v2) { return v1.Equals(v2); } /// /// Check for value inequality. /// /// The v1. /// The v2. /// public static bool operator !=(TWElement8 v1, TWElement8 v2) { return !(v1 == v2); } #endregion } /// /// An enumeration stores a list of individual values, with one of the items designated as the current /// value. There is no required order to the values in the list. /// public partial class TWEnumeration { /// /// The type of items in the enumerated list. All items in the array have the same size. /// public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } } ///// ///// How many items are in the enumeration. ///// //public int Count { get { return (int)_numItems; } set { _numItems = (uint)value; } } /// /// The item number, or index (zero-based) into , of the "current" /// value for the capability. /// public int CurrentIndex { get { return (int)_currentIndex; } set { _currentIndex = (uint)value; } } /// /// The item number, or index (zero-based) into , of the "power-on" /// value for the capability. /// public int DefaultIndex { get { return (int)_defaultIndex; } set { _defaultIndex = (uint)value; } } /// /// The enumerated list: one value resides within each array element. /// public object[] ItemList { get { return _itemList; } set { _itemList = value; if (value != null) { _numItems = (uint)value.Length; } else { _numItems = 0; } } } /// /// Gets the byte offset of the item list from a Ptr to the first item. /// internal int ItemOffset { get { return 14; } } } /// /// Used on Windows and Macintosh pre OS X to pass application events/messages from the /// application to the Source. /// public partial class TWEvent { /// /// A pointer to the event/message to be examined by the Source. /// Under Microsoft Windows, pEvent is a pMSG (pointer to a Microsoft /// Windows MSG struct). That is, the message the application received from /// GetMessage(). On the Macintosh, pEvent is a pointer to an EventRecord. /// public IntPtr pEvent { get { return _pEvent; } set { _pEvent = value; } } /// /// Any message the Source needs to send to the application in /// response to processing the event/message. The messages currently defined for /// this purpose are , /// and . /// public Message TWMessage { get { return (Message)_tWMessage; } } } /// /// This structure is used to pass specific information between the data source and the application /// through . /// public partial struct TWInfo { /// /// Tag identifying an information. /// public ushort InfoID { get { return _infoID; } set { _infoID = value; } } /// /// Item data type. /// public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } } /// /// Number of items. /// public ushort NumItems { get { return _numItems; } set { _numItems = value; } } /// /// This is the return code of availability of data for extended image attribute requested. /// /// /// The return code. /// public ReturnCode ReturnCode { get { return (ReturnCode)_returnCode; } set { _returnCode = (ushort)value; } } /// /// Contains either data or a handle to data. The field /// contains data if the total amount of data is less than or equal to four bytes. The /// field contains a handle of the total amount of data is more than four bytes. /// The amount of data is determined by multiplying NumItems times /// the byte size of the data type specified by ItemType. /// If the Item field contains a handle to data, then the Application is /// responsible for freeing that memory. /// public UIntPtr Item { get { return _item; } set { _item = value; } } } /// /// This structure is used to pass extended image information from the data source to application at /// the end of State 7. The application creates this structure at the end of State 7, when it receives /// XFERDONE. Application fills NumInfos for Number information it needs, and array of /// extended information attributes in Info[ ] array. Application, then, sends it down to the source /// using the above operation triplet. The data source then examines each Info, and fills the rest of /// data with information allocating memory when necessary. /// public partial class TWExtImageInfo { /// /// Number of information that application is requesting. This is filled by the /// application. If positive, then the application is requesting specific extended /// image information. The application should allocate memory and fill in the /// attribute tag for image information. /// public uint NumInfos { get { return _numInfos; } set { _numInfos = value; } } /// /// Array of information. /// public TWInfo[] Info { get { return _info; } set { _info = value; } } } /// /// Provides information about the currently selected device. /// public partial class TWFileSystem { /// /// The name of the input or source file. /// public string InputName { get { return _inputName; } set { _inputName = value; } } /// /// The result of an operation or the name of a destination file. /// public string OutputName { get { return _outputName; } set { _outputName = value; } } /// /// A pointer to Source specific data used to remember state /// information, such as the current directory. /// public IntPtr Context { get { return _context; } set { _context = value; } } /// /// When set to TRUE recursively apply the operation. (ex: deletes /// all subdirectories in the directory being deleted; or copies all /// sub-directories in the directory being copied. /// public bool Recursive { get { return _subdirectories == TwainConst.True; } set { _subdirectories = value ? TwainConst.True : TwainConst.False; } } /// /// Gets the type of the file. /// /// /// The type of the file. /// public FileType FileType { get { return (FileType)_fileType; } set { _fileType = (int)value; } } /// /// If , total size of media in bytes. /// If , size of image in bytes. /// /// /// The size. /// public uint Size { get { return _size; } set { _size = value; } } /// /// The create date of the file, in the form "YYYY/MM/DD /// HH:mm:SS:sss" where YYYY is the year, MM is the numerical /// month, DD is the numerical day, HH is the hour, mm is the /// minute, SS is the second, and sss is the millisecond. /// public string CreateTimeDate { get { return _createTimeDate; } set { _createTimeDate = value; } } /// /// Last date the file was modified. Same format as . /// public string ModifiedTimeDate { get { return _modifiedTimeDate; } set { _modifiedTimeDate = value; } } /// /// The bytes of free space left on the current device. /// public uint FreeSpace { get { return _freeSpace; } set { _freeSpace = value; } } /// /// An estimate of the amount of space a new image would take /// up, based on image layout, resolution and compression. /// Dividing this value into the FreeSpace will yield the /// approximate number of images that the Device has room for. /// public int NewImageSize { get { return _newImageSize; } set { _newImageSize = value; } } /// /// If applicable, return the number of files on the file system including those in all sub-directories. /// /// /// The number of files. /// public uint NumberOfFiles { get { return _numberOfFiles; } set { _numberOfFiles = value; } } /// /// The number of audio snippets associated with a file of type . /// /// /// The number of snippets. /// public uint NumberOfSnippets { get { return _numberOfSnippets; } set { _numberOfSnippets = value; } } /// /// Used to group cameras (ex: front/rear bitonal, front/rear grayscale...). /// public uint DeviceGroupMask { get { return _deviceGroupMask; } set { _deviceGroupMask = value; } } } /// /// This structure is used by the application to specify a set of mapping values to be applied to /// grayscale data. /// public partial class TWGrayResponse { /// /// Transfer curve descriptors. All three channels (Channel1, Channel2 /// and Channel3) must contain the same value for every entry. /// public TWElement8[] Response { get { return _response; } set { _response = value; } } } /// /// A general way to describe the version of software that is running. /// public partial struct TWVersion : IEquatable { /// /// This refers to your application or Source’s major revision number. e.g. The /// "2" in "version 2.1". /// public short Major { get { return (short)_majorNum; } set { _majorNum = (ushort)value; } } /// /// The incremental revision number of your application or Source. e.g. The "1" /// in "version 2.1". /// public short Minor { get { return (short)_minorNum; } set { _minorNum = (ushort)value; } } /// /// The primary language for your Source or application. /// public Language Language { get { return (Language)_language; } set { _language = (ushort)value; } } /// /// The primary country where your Source or application is intended to be /// distributed. e.g. Germany. /// public Country Country { get { return (Country)_country; } set { _country = (ushort)value; } } /// /// General information string - fill in as needed. e.g. "1.0b3 Beta release". /// public string Info { get { return _info; } set { _info.VerifyLengthUnder(TwainConst.String32 - 1); _info = value; } } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0}.{1} {2}", Major, Minor, Info); } #region equals /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { if (!(obj is TWVersion)) return false; return Equals((TWVersion)obj); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// public bool Equals(TWVersion other) { return _majorNum == other._majorNum && _minorNum == other._minorNum && _language == other._language && _country == other._country && string.Equals(_info, other._info); } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return _majorNum.GetHashCode() ^ _minorNum.GetHashCode() ^ _language.GetHashCode() ^ _country.GetHashCode() ^ (_info == null ? 0 : _info.GetHashCode()); } /// /// Check for value equality. /// /// The v1. /// The v2. /// public static bool operator ==(TWVersion v1, TWVersion v2) { return v1.Equals(v2); } /// /// Check for value inequality. /// /// The v1. /// The v2. /// public static bool operator !=(TWVersion v1, TWVersion v2) { return !(v1 == v2); } #endregion } /// /// Provides identification information about a TWAIN entity. Used to maintain consistent /// communication between entities. /// public partial class TWIdentity { /// /// A unique, internal identifier for the TWAIN entity. This field is only /// filled by the Source Manager. Neither an application nor a Source /// should fill this field. The Source uses the contents of this field to /// "identify" which application is invoking the operation sent to the /// Source. /// public int Id { get { return (int)_id; } } /// /// Gets the supported data group. The application will normally set this field to specify which Data /// Group(s) it wants the Source Manager to sort Sources by when /// presenting the Select Source dialog, or returning a list of available /// Sources. /// /// The data group. public DataGroups DataGroup { get { return (DataGroups)(_supportedGroups & 0xffff); } set { _supportedGroups |= (uint)value; } } /// /// Major number of latest TWAIN version that this element supports. /// public short ProtocolMajor { get { return (short)_protocolMajor; } set { _protocolMajor = (ushort)value; } } /// /// Minor number of latest TWAIN version that this element supports. /// public short ProtocolMinor { get { return (short)_protocolMinor; } set { _protocolMinor = (ushort)value; } } /// /// A structure identifying the TWAIN entity. /// public TWVersion Version { get { return _version; } set { _version = value; } } /// /// Gets the data functionalities for TWAIN 2 detection. /// /// The data functionalities. public DataFunctionalities DataFunctionalities { get { return (DataFunctionalities)(_supportedGroups & 0xffff0000); } set { _supportedGroups |= (uint)value; } } /// /// String identifying the manufacturer of the application or Source. e.g. "Aldus". /// public string Manufacturer { get { return _manufacturer; } set { value.VerifyLengthUnder(TwainConst.String32 - 1); _manufacturer = value; } } /// /// Tells an application that performs device-specific operations which /// product family the Source supports. This is useful when a new Source /// has been released and the application doesn't know about the /// particular Source but still wants to perform Custom operations with it. /// e.g. "ScanMan". /// public string ProductFamily { get { return _productFamily; } set { value.VerifyLengthUnder(TwainConst.String32 - 1); _productFamily = value; } } /// /// A string uniquely identifying the Source. This is the string that will be /// displayed to the user at Source select-time. This string must uniquely /// identify your Source for the user, and should identify the application /// unambiguously for Sources that care. e.g. "ScanJet IIc". /// public string ProductName { get { return _productName; } set { value.VerifyLengthUnder(TwainConst.String32 - 1); _productName = value; } } /// /// Creates a from assembly values. /// /// The supported groups. /// The assembly. /// /// assembly public static TWIdentity CreateFromAssembly(DataGroups supportedGroups, Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("assembly"); } var info = FileVersionInfo.GetVersionInfo(assembly.Location); return Create(supportedGroups, assembly.GetName().Version, info.CompanyName, info.ProductName, info.ProductName, info.FileDescription); } /// /// Creates a from specified values. /// /// The supported groups. /// The version. /// The manufacturer. /// The product family. /// Name of the product. /// The product description. /// public static TWIdentity Create(DataGroups supportedGroups, Version version, string manufacturer, string productFamily, string productName, string productDescription) { return new TWIdentity { Manufacturer = manufacturer ?? "UNKNOWN", ProtocolMajor = TwainConst.ProtocolMajor, ProtocolMinor = TwainConst.ProtocolMinor, DataGroup = DataGroups.Control | supportedGroups, DataFunctionalities = DataFunctionalities.App2, ProductFamily = productFamily ?? "UNKNOWN", ProductName = productName ?? "UNKNOWN", Version = new TWVersion { Major = (short)version.Major, Minor = (short)version.Minor, Country = Country.Usa, Language = Language.EnglishUSA, Info = productDescription ?? string.Empty, } }; } } /// /// Describes the "real" image data, that is, the complete image being transferred between the /// Source and application. The Source may transfer the data in a different format--the information /// may be transferred in "strips" or "tiles" in either compressed or uncompressed form. /// public partial class TWImageInfo { /// /// The number of pixels per ICapUnits in the horizontal direction. The /// current unit is assumed to be "inches" unless it has been otherwise /// negotiated between the application and Source. /// public float XResolution { get { return _xResolution; } } /// /// The number of pixels per ICapUnits in the vertical direction. /// public float YResolution { get { return _yResolution; } } /// /// How wide, in pixels, the entire image to be transferred is. If the Source /// doesn’t know, set this field to -1 (hand scanners may do this). /// public int ImageWidth { get { return _imageWidth; } } /// /// How tall/long, in pixels, the image to be transferred is. If the Source /// doesn’t know, set this field to -1 (hand scanners may do this). /// public int ImageLength { get { return _imageLength; } } /// /// The number of samples being returned. For R-G-B, this field would be /// set to 3. For C-M-Y-K, 4. For Grayscale or Black and White, 1. /// public short SamplesPerPixel { get { return _samplesPerPixel; } } /// /// For each sample, the number of bits of information. 24-bit R-G-B will /// typically have 8 bits of information in each sample (8+8+8). Some 8-bit /// color is sampled at 3 bits Red, 3 bits Green, and 2 bits Blue. Such a /// scheme would put 3, 3, and 2 into the first 3 elements of this array. The /// supplied array allows up to 8 samples. Samples are not limited to 8 /// bits. However, both the application and Source must simultaneously /// support sample sizes greater than 8 bits per color. /// public short[] BitsPerSample { get { return _bitsPerSample; } } /// /// The number of bits in each image pixel (or bit depth). This value is /// invariant across the image. 24-bit R-G-B has BitsPerPixel = 24. 40-bit /// CMYK has BitsPerPixel=40. 8-bit Grayscale has BitsPerPixel = 8. Black /// and White has BitsPerPixel = 1. /// public short BitsPerPixel { get { return _bitsPerPixel; } } /// /// If SamplesPerPixel > 1, indicates whether the samples follow one /// another on a pixel-by-pixel basis (R-G-B-R-G-B-R-G-B...) as is common /// with a one-pass scanner or all the pixels for each sample are grouped /// together (complete group of R, complete group of G, complete group of /// B) as is common with a three-pass scanner. If the pixel-by-pixel /// method (also known as "chunky") is used, the Source should set Planar /// = FALSE. If the grouped method (also called "planar") is used, the /// Source should set Planar = TRUE. /// public bool Planar { get { return _planar == TwainConst.True; } } /// /// This is the highest categorization for how the data being transferred /// should be interpreted by the application. This is how the application /// can tell if the data is Black and White, Grayscale, or Color. Currently, /// the only color type defined is "tri-stimulus", or color described by three /// characteristics. Most popular color description methods use tristimulus /// descriptors. For simplicity, the constant used to identify tristimulus /// color is called Rgb, for R-G-B color. There is no /// default for this value. /// public PixelType PixelType { get { return (Values.PixelType)_pixelType; } } /// /// The compression method used to process the data being transferred. /// Default is no compression. /// public Compression Compression { get { return (Values.Compression)_compression; } } } /// /// Involves information about the original size of the acquired image and its position on the /// original "page" relative to the "page’s" upper-left corner. Default measurements are in inches /// (units of measure can be changed by negotiating the ICapUnits capability). This information /// may be used by the application to relate the acquired (and perhaps processed image) to the /// original. Further, the application can, using this structure, set the size of the image it wants /// acquired. /// /// Another attribute of this structure is the included frame, page, and document indexing /// information. Most Sources and applications, at least at first, will likely set all these fields to one. /// For Sources that can acquire more than one frame from a page in a single acquisition, the /// FrameNumber field will be handy. Sources that can acquire more than one page from a /// document feeder will use PageNumber and DocumentNumber. These fields will be especially /// useful for forms-processing applications and other applications with similar document tracking /// requirements. /// public partial class TWImageLayout { /// /// Frame coords within larger document. /// public TWFrame Frame { get { return _frame; } set { _frame = value; } } /// /// The document number, assigned by the Source, that the acquired data /// originated on. Useful for grouping pages together. /// Initial value is 1. Increment when a new document is placed into the /// document feeder (usually tell this has happened when the feeder /// empties). Reset when no longer acquiring from the feeder. /// public int DocumentNumber { get { return (int)_documentNumber; } set { _documentNumber = (uint)value; } } /// /// The page which the acquired data was captured from. Useful for /// grouping Frames together that are in some way related. /// Initial value is 1. Increment for each page fed from /// a page feeder. Reset when a new document is placed into the feeder. /// public int PageNumber { get { return (int)_pageNumber; } set { _pageNumber = (uint)value; } } /// /// Usually a chronological index of the acquired frame. These frames /// are related to one another in some way; usually they were acquired /// from the same page. The Source assigns these values. Initial value is /// 1. Reset when a new page is acquired from. /// public int FrameNumber { get { return (int)_frameNumber; } set { _frameNumber = (uint)value; } } } /// /// Provides information for managing memory buffers. Memory for transfer buffers is allocated /// by the application--the Source is asked to fill these buffers. This structure keeps straight which /// entity is responsible for deallocation. /// public partial struct TWMemory { // not a class due to embedded /// /// Encodes which entity releases the buffer and how the buffer is referenced. /// public MemoryFlags Flags { get { return (MemoryFlags)_flags; } set { _flags = (uint)value; } } /// /// The size of the buffer in bytes. Should always be an even number and wordaligned. /// public uint Length { get { return _length; } set { _length = value; } } /// /// Reference to the buffer. May be a Pointer or a Handle (see Flags field to make /// this determination). /// public IntPtr TheMem { get { return _theMem; } set { _theMem = value; } } } /// /// Describes the form of the acquired data being passed from the Source to the application. /// public partial class TWImageMemXfer { /// /// The compression method used to process the data being transferred. /// public Compression Compression { get { return (Compression)_compression; } set { _compression = (ushort)value; } } /// /// The number of uncompressed bytes in each row of the piece of the image /// being described in this buffer. /// public uint BytesPerRow { get { return _bytesPerRow; } set { _bytesPerRow = value; } } /// /// The number of uncompressed columns (in pixels) in this buffer. /// public uint Columns { get { return _columns; } set { _columns = value; } } /// /// The number or uncompressed rows (in pixels) in this buffer. /// public uint Rows { get { return _rows; } set { _rows = value; } } /// /// How far, in pixels, the left edge of the piece of the image being described /// by this structure is inset from the "left" side of the original image. If the /// Source is transferring in "strips", this value will equal zero. If the Source /// is transferring in "tiles", this value will often be non-zero. /// public uint XOffset { get { return _xOffset; } set { _xOffset = value; } } /// /// Same idea as XOffset, but the measure is in pixels from the "top" of the /// original image to the upper edge of this piece. /// public uint YOffset { get { return _yOffset; } set { _yOffset = value; } } /// /// The number of bytes written into the transfer buffer. This field must /// always be filled in correctly, whether compressed or uncompressed data /// is being transferred. /// public uint BytesWritten { get { return _bytesWritten; } set { _bytesWritten = value; } } /// /// A structure of type describing who must dispose of the /// buffer, the actual size of the buffer, in bytes, and where the buffer is /// located in memory. /// public TWMemory Memory { get { return _memory; } set { _memory = value; } } } /// /// Describes the information necessary to transfer a JPEG-compressed image during a buffered /// transfer. Images compressed in this fashion will be compatible with the JPEG File Interchange /// Format, version 1.1. /// public partial class TWJpegCompression { /// /// Defines the color space in which the /// compressed components are stored. /// public PixelType ColorSpace { get { return (PixelType)_colorSpace; } set { _colorSpace = (ushort)value; } } /// /// Encodes the horizontal and vertical subsampling in the form /// ABCDEFGH, where ABCD are the high-order four nibbles which /// represent the horizontal subsampling and EFGH are the low-order four /// nibbles which represent the vertical subsampling. Each nibble may /// have a value of 0, 1, 2, 3, or 4. However, max(A,B,C,D) * max(E,F,G,H) /// must be less than or equal to 10. Subsampling is irrelevant for single /// component images. Therefore, the corresponding nibbles should be set /// to 1. e.g. To indicate subsampling two Y for each U and V in a YUV /// space image, where the same subsampling occurs in both horizontal /// and vertical axes, this field would hold 0x21102110. For a grayscale /// image, this field would hold 0x10001000. A CMYK image could hold /// 0x11111111. /// public uint SubSampling { get { return _subSampling; } set { _subSampling = value; } } /// /// Number of color components in the image to be compressed. /// public ushort NumComponents { get { return _numComponents; } set { _numComponents = value; } } /// /// Number of MDUs (Minimum Data Units) between restart markers. /// Default is 0, indicating that no restart markers are used. An MDU is /// defined for interleaved data (i.e. R-G-B, Y-U-V, etc.) as a minimum /// complete set of 8x8 component blocks. /// public ushort RestartFrequency { get { return _restartFrequency; } set { _restartFrequency = value; } } /// /// Mapping of components to Quantization tables. /// public ushort[] QuantMap { get { return _quantMap; } set { _quantMap = value; } } /// /// Quantization tables. /// public TWMemory[] QuantTable { get { return _quantTable; } set { _quantTable = value; } } /// /// Mapping of components to Huffman tables. Null entries signify /// selection of the default tables. /// public ushort[] HuffmanMap { get { return _huffmanMap; } set { _huffmanMap = value; } } /// /// DC Huffman tables. Null entries signify selection of the default tables. /// public TWMemory[] HuffmanDC { get { return _huffmanDC; } set { _huffmanDC = value; } } /// /// AC Huffman tables. Null entries signify selection of the default tables. /// public TWMemory[] HuffmanAC { get { return _huffmanAC; } set { _huffmanAC = value; } } } /// /// Container for one value. /// public partial class TWOneValue { /// /// The type of the item. /// public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } } /// /// The value. /// public uint Item { get { return _item; } set { _item = value; } } } /// /// This structure holds the color palette information for buffered memory transfers of type /// ICapPixelType = Palette. /// public partial class TWPalette8 { /// /// Number of colors in the color table; maximum index into the color table /// should be one less than this (since color table indexes are zero-based). /// public ushort NumColors { get { return _numColors; } set { _numColors = value; } } /// /// Specifies type of palette. /// public PaletteType PaletteType { get { return (PaletteType)_paletteType; } set { _paletteType = (ushort)value; } } /// /// Array of palette values. /// public TWElement8[] Colors { get { return _colors; } set { _colors = value; } } } /// /// Used to bypass the TWAIN protocol when communicating with a device. All memory must be /// allocated and freed by the Application. /// public partial class TWPassThru { /// /// Pointer to Command buffer. /// public IntPtr pCommand { get { return _pCommand; } set { _pCommand = value; } } /// /// Number of bytes in Command buffer. /// public uint CommandBytes { get { return _commandBytes; } set { _commandBytes = value; } } /// /// Defines the direction of data flow. /// public Direction Direction { get { return (Direction)_direction; } set { _direction = (int)value; } } /// /// Pointer to Data buffer. /// public IntPtr pData { get { return _pData; } set { _pData = value; } } /// /// Number of bytes in Data buffer. /// public uint DataBytes { get { return _dataBytes; } set { _dataBytes = value; } } /// /// Number of bytes successfully transferred. /// public uint DataBytesXfered { get { return _dataBytesXfered; } set { _dataBytesXfered = value; } } } /// /// This structure tells the application how many more complete transfers the Source currently has /// available. /// partial class TWPendingXfers { /// /// Initializes a new instance of the class. /// public TWPendingXfers() { _count = TwainConst.DontCare16; } /// /// The number of complete transfers a Source has available for the application it is /// connected to. If no more transfers are available, set to zero. If an unknown and /// non-zero number of transfers are available, set to -1. /// public int Count { get { return _count == TwainConst.DontCare16 ? -1 : (int)_count; } } /// /// The application should check this field if the CapJobControl is set to other /// than None. If this is not 0, the application should expect more data /// from the driver according to CapJobControl settings. /// public uint EndOfJob { get { return _eOJ; } } } /// /// Container for a range of values. /// public partial class TWRange { /// /// The type of items in the list. /// public ItemType ItemType { get { return (ItemType)_itemType; } set { _itemType = (ushort)value; } } /// /// The least positive/most negative value of the range. /// public uint MinValue { get { return _minValue; } set { _minValue = value; } } /// /// The most positive/least negative value of the range. /// public uint MaxValue { get { return _maxValue; } set { _maxValue = value; } } /// /// The delta between two adjacent values of the range. /// e.g. Item2 - Item1 = StepSize; /// public uint StepSize { get { return _stepSize; } set { _stepSize = value; } } /// /// The device’s "power-on" value for the capability. If the application is /// performing a MSG_SET operation and isn’t sure what the default /// value is, set this field to . /// public uint DefaultValue { get { return _defaultValue; } set { _defaultValue = value; } } /// /// The value to which the device (or its user interface) is currently set to /// for the capability. /// public uint CurrentValue { get { return _currentValue; } set { _currentValue = value; } } } /// /// This structure is used by the application to specify a set of mapping values to be applied to RGB /// color data. Use this structure for RGB data whose bit depth is up to, and including, 8-bits. /// The number of elements in the array is determined by —the number of /// elements is 2 raised to the power of . /// public partial class TWRgbResponse { /// /// Transfer curve descriptors. To minimize color shift problems, writing the /// same values into each channel is desirable. /// public TWElement8[] Response { get { return _response; } set { _response = value; } } } /// /// Describes the file format and file specification information for a transfer through a disk file. /// public partial class TWSetupFileXfer { /// /// A complete file specifier to the target file. On Windows, be sure to include the /// complete pathname. /// public string FileName { get { return _fileName; } set { value.VerifyLengthUnder(TwainConst.String255 - 1); _fileName = value; } } /// /// The format of the file the Source is to fill. /// public FileFormat Format { get { return (FileFormat)_format; } set { _format = (ushort)value; } } /// /// The volume reference number for the file. This applies to Macintosh only. On /// Windows, fill the field with -1. /// public short VRefNum { get { return _vRefNum; } set { _vRefNum = value; } } } /// /// Provides the application information about the Source’s requirements and preferences /// regarding allocation of transfer buffer(s). /// public partial class TWSetupMemXfer { /// /// The size of the smallest transfer buffer, in bytes, that a Source can be /// successful with. This will typically be the number of bytes in an /// uncompressed row in the block to be transferred. An application should /// never allocate a buffer smaller than this. /// public uint MinBufferSize { get { return _minBufSize; } } /// /// The size of the largest transfer buffer, in bytes, that a Source can fill. If a /// Source can fill an arbitrarily large buffer, it might set this field to negative 1 to /// indicate this (a hand-held scanner might do this, depending on how long its /// cord is). Other Sources, such as frame grabbers, cannot fill a buffer larger than /// a certain size. Allocation of a transfer buffer larger than this value is wasteful. /// public uint MaxBufferSize { get { return _maxBufSize; } } /// /// The size of the optimum transfer buffer, in bytes. A smart application will /// allocate transfer buffers of this size, if possible. Buffers of this size will /// optimize the Source’s performance. Sources should be careful to put /// reasonable values in this field. Buffers that are 10’s of kbytes will be easier for /// applications to allocate than buffers that are 100’s or 1000’s of kbytes. /// public uint Preferred { get { return _preferred; } } } /// /// Describes the status of a source. /// public partial class TWStatus { /// /// Condition Code describing the status. /// public ConditionCode ConditionCode { get { return (ConditionCode)_conditionCode; } set { _conditionCode = (ushort)value; } } /// /// Valid for TWAIN 2.1 and later. This field contains additional /// scanner-specific data. If there is no data, then this value must be zero. /// public ushort Data { get { return _data; } set { _data = Data; } } } /// /// Translates the contents of Status into a localized UTF8string, with the total number of bytes /// in the string. /// public partial class TWStatusUtf8 { /// /// data received from a previous call. /// public TWStatus Status { get { return new TWStatus { ConditionCode = (ConditionCode)_conditionCode, Data = _data }; } set { _conditionCode = (ushort)value.ConditionCode; _data = value.Data; } } /// /// Total number of bytes in the UTF8string, plus the terminating NULL byte. /// This is not the same as the total number of characters in the string. /// public uint Size { get { return _size; } set { _size = value; } } /// /// TW_HANDLE to a UTF-8 encoded localized string (based on /// TwIdentity.Language or CapLanguage). The Source allocates /// it, the Application frees it. /// IntPtr UTF8string { get { return _uTF8string; } set { _uTF8string = value; } } } /// /// This structure is used to handle the user interface coordination between an application and a /// Source. /// partial class TWUserInterface { /// /// Set to TRUE by the application if the Source should activate its built-in user /// interface. Otherwise, set to FALSE. Note that not all sources support ShowUI = /// FALSE. /// public bool ShowUI { get { return _showUI > 0; } set { _showUI = value ? TwainConst.True : TwainConst.False; } } /// /// If ShowUI is TRUE, then an application setting this to TRUE requests the Source to /// run Modal. /// public bool ModalUI { get { return _modalUI > 0; } set { _modalUI = value ? TwainConst.True : TwainConst.False; } } /// /// Microsoft Windows only: Application’s window handle. The Source designates /// the hWnd as its parent when creating the Source dialog. /// public IntPtr hParent { get { return _hParent; } set { _hParent = value; } } } /// /// Provides entry points required by TWAIN 2.0 Applications and Sources. /// partial class TWEntryPoint { /// /// Initializes a new instance of the class. /// [EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] public TWEntryPoint() { _size = (uint)Marshal.SizeOf(this); } /// /// The memory allocation function. /// public MemAllocateDelegate AllocateFunction { get { return _dSM_MemAllocate; } } /// /// The memory free function. /// public MemFreeDelegate FreeFunction { get { return _dSM_MemFree; } } /// /// The memory lock function. /// public MemLockDelegate LockFunction { get { return _dSM_MemLock; } } /// /// The memory unlock function. /// public MemUnlockDelegate UnlockFunction { get { return _dSM_MemUnlock; } } } /// /// The range of colors specified by this structure is replaced with Replacement grayscale value in the /// binary image. The color is specified in HSV color space. /// public partial class TWFilterDescriptor { /// /// Initializes a new instance of the struct. /// public TWFilterDescriptor() { _size = (uint)Marshal.SizeOf(this); } /// /// Size of this structure in bytes. /// /// /// The size. /// public uint Size { get { return _size; } set { _size = value; } } /// /// Hue starting number. Valid values 0 to 3600 (0° to 360°). /// public uint HueStart { get { return _hueStart; } set { _hueStart = value; } } /// /// Hue ending number. Valid values 0 to 3600 (0° to 360°). /// public uint HueEnd { get { return _hueEnd; } set { _hueEnd = value; } } /// /// Saturation starting number. Valid values 0 to 1000 (0% to 100%). /// public uint SaturationStart { get { return _saturationStart; } set { _saturationStart = value; } } /// /// Saturation ending number. Valid values 0 to 1000 (0% to 100%). /// public uint SaturationEnd { get { return _saturationEnd; } set { _saturationEnd = value; } } /// /// Luminosity starting number. Valid values 0 to 1000 (0% to 100%). /// public uint ValueStart { get { return _valueStart; } set { _valueStart = value; } } /// /// Luminosity ending number. Valid values 0 to 1000 (0% to 100%). /// public uint ValueEnd { get { return _valueEnd; } set { _valueEnd = value; } } /// /// Replacement grayscale value. Valid values 0 to (2^32)–1 (Maximum value /// depends on grayscale bit depth). /// public uint Replacement { get { return _replacement; } set { _replacement = value; } } } /// /// Specifies the filter to be applied during image acquisition. More than one descriptor can be /// specified. All descriptors are applied with an OR statement. /// public partial class TWFilter { /// /// Initializes a new instance of the class. /// public TWFilter() { _size = (uint)Marshal.SizeOf(this); } /// /// Number of descriptors in hDescriptors array. /// /// /// The descriptor count. /// public uint DescriptorCount { get { return _descriptorCount; } set { _descriptorCount = value; } } /// /// Maximum possible descriptors. Valid only for GET and GETDEFAULT operations. /// /// /// The maximum descriptor count. /// public uint MaxDescriptorCount { get { return _maxDescriptorCount; } set { _maxDescriptorCount = value; } } /// /// If the value is 0 filter will check if current pixel color is inside the area /// specified by the descriptor. If the value is 1 it will check if it is outside /// of this area. /// /// /// The condition. /// public uint Condition { get { return _condition; } set { _condition = value; } } /// /// Handle to array of . /// /// /// The descriptors. /// public IntPtr hDescriptors { get { return _hDescriptors; } set { _hDescriptors = value; } } } }