More cap conversions.

This commit is contained in:
soukoku
2014-09-17 08:07:00 -04:00
parent 782f96827e
commit 8508bbb764
6 changed files with 255 additions and 296 deletions

View File

@@ -51,9 +51,6 @@
<Compile Include="..\NTwain\CapabilityReader.cs">
<Link>CapabilityReader.cs</Link>
</Compile>
<Compile Include="..\NTwain\CapRoutines.cs">
<Link>CapRoutines.cs</Link>
</Compile>
<Compile Include="..\NTwain\DataSource.Caps.cs">
<Link>DataSource.Caps.cs</Link>
</Compile>

View File

@@ -1,74 +0,0 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain
{
/// <summary>
/// Contains re-usable routines for cap use.
/// </summary>
public static class CapRoutines
{
#region handy conversions
/// <summary>
/// Routine that does nothing.
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public static object NoConvertRoutine(object value)
{
return value;
}
/// <summary>
/// Predefined routine for <see cref="BoolType"/>
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public static TEnum EnumRoutine<TEnum>(object value) where TEnum : struct, IConvertible
{
if (value != null)
{
return value.ConvertToEnum<TEnum>();
}
return default(TEnum);
}
/// <summary>
/// Predefined routine for <see cref="TWFix32"/>
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public static TWFix32 TWFix32Routine(object value)
{
if (value != null)
{
if (value is TWFix32)
{
return (TWFix32)value;
}
return Convert.ToSingle(value);
}
return default(TWFix32);
}
/// <summary>
/// Predefined routine for <see cref="string"/>
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public static string StringRoutine(object value)
{
if (value != null)
{
return value.ToString();
}
return default(string);
}
#endregion
}
}

View File

@@ -51,38 +51,42 @@ namespace NTwain.Data
/// <returns></returns>
public static TEnum ConvertToEnum<TEnum>(this object value, bool tryUpperWord) where TEnum : struct,IConvertible
{
var returnType = typeof(TEnum);
// standard int values
if (returnType.IsEnum)
if (value != null)
{
if (tryUpperWord)
var returnType = typeof(TEnum);
// standard int values
if (returnType.IsEnum)
{
// small routine to work with bad sources that may put
// 16bit value in the upper word instead of lower word (as per the twain spec).
var rawType = Enum.GetUnderlyingType(returnType);
if (typeof(ushort).IsAssignableFrom(rawType))
if (tryUpperWord)
{
var intVal = Convert.ToUInt32(value, CultureInfo.InvariantCulture);
var enumVal = GetLowerWord(intVal);
if (!Enum.IsDefined(returnType, enumVal))
// small routine to work with bad sources that may put
// 16bit value in the upper word instead of lower word (as per the twain spec).
var rawType = Enum.GetUnderlyingType(returnType);
if (typeof(ushort).IsAssignableFrom(rawType))
{
return (TEnum)Enum.ToObject(returnType, GetUpperWord(intVal));
var intVal = Convert.ToUInt32(value, CultureInfo.InvariantCulture);
var enumVal = GetLowerWord(intVal);
if (!Enum.IsDefined(returnType, enumVal))
{
return (TEnum)Enum.ToObject(returnType, GetUpperWord(intVal));
}
}
}
// this may work better?
return (TEnum)Enum.ToObject(returnType, value);
//// cast to underlying type first then to the enum
//return (T)Convert.ChangeType(value, rawType);
}
// this may work better?
return (TEnum)Enum.ToObject(returnType, value);
//// cast to underlying type first then to the enum
//return (T)Convert.ChangeType(value, rawType);
else if (typeof(IConvertible).IsAssignableFrom(returnType))
{
// for regular integers and whatnot
return (TEnum)Convert.ChangeType(value, returnType, CultureInfo.InvariantCulture);
}
// return as-is from cap. if caller made a mistake then there should be exceptions
return (TEnum)value;
}
else if (typeof(IConvertible).IsAssignableFrom(returnType))
{
// for regular integers and whatnot
return (TEnum)Convert.ChangeType(value, returnType, CultureInfo.InvariantCulture);
}
// return as-is from cap. if caller made a mistake then there should be exceptions
return (TEnum)value;
return default(TEnum);
}
static ushort GetLowerWord(uint value)
@@ -101,11 +105,40 @@ namespace NTwain.Data
/// <returns></returns>
public static TWFix32 ConvertToFix32(this object value)
{
if (value is TWFix32)
if (value != null)
{
return (TWFix32)value;
if (value is TWFix32)
{
return (TWFix32)value;
}
return (TWFix32)Convert.ToSingle(value, CultureInfo.InvariantCulture);
}
return (TWFix32)Convert.ToSingle(value, CultureInfo.InvariantCulture);
return default(TWFix32);
}
///// <summary>
///// Routine that does nothing.
///// </summary>
///// <param name="value">The value.</param>
///// <returns></returns>
//public static object NoConvertRoutine(object value)
//{
// return value;
//}
///// <summary>
///// Predefined routine for <see cref="string"/>
///// </summary>
///// <param name="value">The value.</param>
///// <returns></returns>
//public static string ConvertToString(object value)
//{
// if (value != null)
// {
// return value.ToString();
// }
// return default(string);
//}
}
}

View File

@@ -172,31 +172,7 @@ namespace NTwain
#region high-level caps
private CapabilityControl<XferMech> _imgXferMech;
/// <summary>
/// Gets the property to work with image <see cref="XferMech"/> for the current source.
/// </summary>
/// <value>
/// The image xfer mech.
/// </value>
public CapabilityControl<XferMech> CapImageXferMech
{
get
{
if (_imgXferMech == null)
{
_imgXferMech = new CapabilityControl<XferMech>(this, CapabilityId.ICapXferMech, CapRoutines.EnumRoutine<XferMech>,
value => new TWCapability(CapabilityId.ICapXferMech, new TWOneValue
{
Item = (uint)value,
ItemType = ItemType.UInt16
}));
}
return _imgXferMech;
}
}
#region audio caps
private CapabilityControl<XferMech> _audXferMech;
@@ -212,7 +188,7 @@ namespace NTwain
{
if (_audXferMech == null)
{
_audXferMech = new CapabilityControl<XferMech>(this, CapabilityId.ACapXferMech, CapRoutines.EnumRoutine<XferMech>,
_audXferMech = new CapabilityControl<XferMech>(this, CapabilityId.ACapXferMech, ValueExtensions.ConvertToEnum<XferMech>,
value => new TWCapability(CapabilityId.ACapXferMech, new TWOneValue
{
Item = (uint)value,
@@ -223,6 +199,35 @@ namespace NTwain
}
}
#endregion
#region img caps
private CapabilityControl<XferMech> _imgXferMech;
/// <summary>
/// Gets the property to work with image <see cref="XferMech"/> for the current source.
/// </summary>
/// <value>
/// The image xfer mech.
/// </value>
public CapabilityControl<XferMech> CapImageXferMech
{
get
{
if (_imgXferMech == null)
{
_imgXferMech = new CapabilityControl<XferMech>(this, CapabilityId.ICapXferMech, ValueExtensions.ConvertToEnum<XferMech>,
value => new TWCapability(CapabilityId.ICapXferMech, new TWOneValue
{
Item = (uint)value,
ItemType = ItemType.UInt16
}));
}
return _imgXferMech;
}
}
private CapabilityControl<CompressionType> _compression;
@@ -238,7 +243,7 @@ namespace NTwain
{
if (_compression == null)
{
_compression = new CapabilityControl<CompressionType>(this, CapabilityId.ICapCompression, CapRoutines.EnumRoutine<CompressionType>,
_compression = new CapabilityControl<CompressionType>(this, CapabilityId.ICapCompression, ValueExtensions.ConvertToEnum<CompressionType>,
value => new TWCapability(CapabilityId.ICapCompression, new TWOneValue
{
Item = (uint)value,
@@ -264,7 +269,7 @@ namespace NTwain
{
if (_fileFormat == null)
{
_fileFormat = new CapabilityControl<FileFormat>(this, CapabilityId.ICapImageFileFormat, CapRoutines.EnumRoutine<FileFormat>,
_fileFormat = new CapabilityControl<FileFormat>(this, CapabilityId.ICapImageFileFormat, ValueExtensions.ConvertToEnum<FileFormat>,
value => new TWCapability(CapabilityId.ICapImageFileFormat, new TWOneValue
{
Item = (uint)value,
@@ -290,7 +295,7 @@ namespace NTwain
{
if (_pixelType == null)
{
_pixelType = new CapabilityControl<PixelType>(this, CapabilityId.ICapPixelType, CapRoutines.EnumRoutine<PixelType>,
_pixelType = new CapabilityControl<PixelType>(this, CapabilityId.ICapPixelType, ValueExtensions.ConvertToEnum<PixelType>,
value => new TWCapability(CapabilityId.ICapPixelType, new TWOneValue
{
Item = (uint)value,
@@ -316,7 +321,7 @@ namespace NTwain
{
if (_supportSize == null)
{
_supportSize = new CapabilityControl<SupportedSize>(this, CapabilityId.ICapSupportedSizes, CapRoutines.EnumRoutine<SupportedSize>,
_supportSize = new CapabilityControl<SupportedSize>(this, CapabilityId.ICapSupportedSizes, ValueExtensions.ConvertToEnum<SupportedSize>,
value => new TWCapability(CapabilityId.ICapSupportedSizes, new TWOneValue
{
Item = (uint)value,
@@ -334,7 +339,7 @@ namespace NTwain
/// Gets the property to work with image auto deskew flag for the current source.
/// </summary>
/// <value>
/// The image supported size.
/// The image auto deskew flag.
/// </value>
public CapabilityControl<BoolType> CapImageAutoDeskew
{
@@ -342,143 +347,172 @@ namespace NTwain
{
if (_autoDeskew == null)
{
_autoDeskew = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticDeskew, CapRoutines.EnumRoutine<BoolType>, null);
_autoDeskew = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticDeskew, ValueExtensions.ConvertToEnum<BoolType>, value =>
{
if (Identity.ProtocolMajor >= 2)
{
// if using twain 2.0 will need to use enum instead of onevalue (yuck)
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)value };
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticDeskew, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticDeskew, one);
}
});
}
return _autoDeskew;
}
}
#endregion
#region dpi
private CapabilityControl<BoolType> _autoRotate;
/// <summary>
/// Gets the supported DPI values for the current source.
/// Only call this at state 4 or higher.
/// Gets the property to work with image auto rotate flag for the current source.
/// </summary>
/// <returns></returns>
public IList<TWFix32> CapGetDPIs()
/// <value>
/// The image auto rotate flag.
/// </value>
public CapabilityControl<BoolType> CapImageAutoRotate
{
var list = CapGet(CapabilityId.ICapXResolution);
return list.Select(o => o.ConvertToFix32()).ToList();
}
/// <summary>
/// Change the DPI value for the current source.
/// </summary>
/// <param name="dpi">The DPI.</param>
/// <returns></returns>
public ReturnCode CapSetDPI(TWFix32 dpi)
{
return CapSetDPI(dpi, dpi);
}
/// <summary>
/// Change the DPI value for the current source.
/// </summary>
/// <param name="xDPI">The x DPI.</param>
/// <param name="yDPI">The y DPI.</param>
/// <returns></returns>
public ReturnCode CapSetDPI(TWFix32 xDPI, TWFix32 yDPI)
{
TWOneValue one = new TWOneValue();
one.Item = (uint)xDPI;// ((uint)dpi) << 16;
one.ItemType = ItemType.Fix32;
using (TWCapability xres = new TWCapability(CapabilityId.ICapXResolution, one))
get
{
var rc = _session.DGControl.Capability.Set(xres);
if (rc == ReturnCode.Success)
if (_autoRotate == null)
{
one.Item = (uint)yDPI;
using (TWCapability yres = new TWCapability(CapabilityId.ICapYResolution, one))
_autoRotate = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticRotate, ValueExtensions.ConvertToEnum<BoolType>, value =>
{
rc = _session.DGControl.Capability.Set(yres);
}
if (Identity.ProtocolMajor >= 2)
{
// if using twain 2.0 will need to use enum instead of onevalue (yuck)
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)value };
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticRotate, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticRotate, one);
}
});
}
return rc;
return _autoRotate;
}
}
private CapabilityControl<TWFix32> _xResolution;
/// <summary>
/// Gets the property to work with image horizontal resolution for the current source.
/// </summary>
/// <value>
/// The image horizontal resolution.
/// </value>
public CapabilityControl<TWFix32> CapImageXResolution
{
get
{
if (_xResolution == null)
{
_xResolution = new CapabilityControl<TWFix32>(this, CapabilityId.ICapXResolution, ValueExtensions.ConvertToFix32,
value => new TWCapability(CapabilityId.ICapXResolution, new TWOneValue
{
Item = (uint)value,// ((uint)dpi) << 16;
ItemType = ItemType.Fix32
}));
}
return _xResolution;
}
}
private CapabilityControl<TWFix32> _yResolution;
/// <summary>
/// Gets the property to work with image vertical resolution for the current source.
/// </summary>
/// <value>
/// The image vertical resolution.
/// </value>
public CapabilityControl<TWFix32> CapImageYResolution
{
get
{
if (_yResolution == null)
{
_yResolution = new CapabilityControl<TWFix32>(this, CapabilityId.ICapYResolution, ValueExtensions.ConvertToFix32,
value => new TWCapability(CapabilityId.ICapYResolution, new TWOneValue
{
Item = (uint)value,// ((uint)dpi) << 16;
ItemType = ItemType.Fix32
}));
}
return _yResolution;
}
}
#endregion
#region other caps
private CapabilityControl<BoolType> _duplexEnabled;
/// <summary>
/// Gets the property to work with duplex enabled flag for the current source.
/// </summary>
/// <value>
/// The duplex enabled flag.
/// </value>
public CapabilityControl<BoolType> CapDuplexEnabled
{
get
{
if (_duplexEnabled == null)
{
_duplexEnabled = new CapabilityControl<BoolType>(this, CapabilityId.CapDuplexEnabled, ValueExtensions.ConvertToEnum<BoolType>, value =>
{
if (Identity.ProtocolMajor >= 2)
{
// if using twain 2.0 will need to use enum instead of onevalue (yuck)
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)value };
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.CapDuplexEnabled, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.CapDuplexEnabled, one);
}
});
}
return _duplexEnabled;
}
}
#endregion
#endregion
#region onesie flags
/// <summary>
/// Change the auto deskew flag for the current source.
/// </summary>
/// <param name="useIt">if set to <c>true</c> use it.</param>
/// <returns></returns>
public ReturnCode CapSetAutoDeskew(bool useIt)
{
var rc = ReturnCode.Failure;
if (SupportedCaps.Contains(CapabilityId.ICapAutomaticDeskew))
{
if (Identity.ProtocolMajor >= 2)
{
// if using twain 2.0 will need to use enum instead of onevalue (yuck)
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)(useIt ? 1 : 0) };
en.ItemType = ItemType.Bool;
using (TWCapability dx = new TWCapability(CapabilityId.ICapAutomaticDeskew, en))
{
rc = _session.DGControl.Capability.Set(dx);
}
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)(useIt ? 1 : 0);
one.ItemType = ItemType.Bool;
using (TWCapability capValue = new TWCapability(CapabilityId.ICapAutomaticDeskew, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
}
}
return rc;
}
/// <summary>
/// Change the auto rotate flag for the current source.
/// </summary>
/// <param name="useIt">if set to <c>true</c> use it.</param>
/// <returns></returns>
public ReturnCode CapSetAutoRotate(bool useIt)
{
var rc = ReturnCode.Failure;
if (SupportedCaps.Contains(CapabilityId.ICapAutomaticRotate))
{
if (Identity.ProtocolMajor >= 2)
{
// if using twain 2.0 will need to use enum instead of onevalue (yuck)
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)(useIt ? 1 : 0) };
en.ItemType = ItemType.Bool;
using (TWCapability dx = new TWCapability(CapabilityId.ICapAutomaticRotate, en))
{
rc = _session.DGControl.Capability.Set(dx);
}
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)(useIt ? 1 : 0);
one.ItemType = ItemType.Bool;
using (TWCapability capValue = new TWCapability(CapabilityId.ICapAutomaticRotate, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
}
}
return rc;
}
/// <summary>
/// Change the auto border detection flag for the current source.
@@ -527,39 +561,6 @@ namespace NTwain
return rc;
}
/// <summary>
/// Change the duplex flag for the current source.
/// </summary>
/// <param name="useIt">if set to <c>true</c> to use it.</param>
/// <returns></returns>
public ReturnCode CapSetDuplex(bool useIt)
{
if (Identity.ProtocolMajor >= 2)
{
// twain 2 likes to use enum :(
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (uint)(useIt ? 1 : 0) };
en.ItemType = ItemType.Bool;
using (TWCapability dx = new TWCapability(CapabilityId.CapDuplexEnabled, en))
{
return _session.DGControl.Capability.Set(dx);
}
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)(useIt ? 1 : 0);
one.ItemType = ItemType.Bool;
using (TWCapability dx = new TWCapability(CapabilityId.CapDuplexEnabled, one))
{
return _session.DGControl.Capability.Set(dx);
}
}
}
/// <summary>
/// Change the use feeder flag for the current source.
/// </summary>

View File

@@ -57,7 +57,6 @@
<ItemGroup>
<Compile Include="CapabilityControl.cs" />
<Compile Include="CapabilityReader.cs" />
<Compile Include="CapRoutines.cs" />
<Compile Include="Data\TypeReader.cs" />
<Compile Include="Data\TwainTypesExtended.cs" />
<Compile Include="DeviceEventArgs.cs" />

View File

@@ -280,14 +280,14 @@ namespace Tester.Winform
{
LoadDepth(src.CapImagePixelType);
}
if (groupDPI.Enabled = caps.Contains(CapabilityId.ICapXResolution) && caps.Contains(CapabilityId.ICapYResolution))
if (groupDPI.Enabled = src.CapImageXResolution.IsSupported && src.CapImageYResolution.IsSupported)
{
LoadDPI();
LoadDPI(src.CapImageXResolution);
}
// TODO: find out if this is how duplex works or also needs the other option
if (groupDuplex.Enabled = caps.Contains(CapabilityId.CapDuplexEnabled))
if (groupDuplex.Enabled = src.CapDuplexEnabled.IsSupported)
{
LoadDuplex();
LoadDuplex(src.CapDuplexEnabled);
}
if (groupSize.Enabled = src.CapImageSupportedSize.IsSupported)
{
@@ -313,17 +313,19 @@ namespace Tester.Winform
}
}
private void LoadDuplex()
private void LoadDuplex(CapabilityControl<BoolType> cap)
{
ckDuplex.Checked = _twain.CurrentSource.CapGetCurrent(CapabilityId.CapDuplexEnabled).ConvertToEnum<uint>() != 0;
ckDuplex.Checked = cap.GetCurrent() == BoolType.True;
}
private void LoadDPI()
private void LoadDPI(CapabilityControl<TWFix32> cap)
{
// only allow dpi of certain values for those source that lists everything
var list = _twain.CurrentSource.CapGetDPIs().Where(dpi => (dpi % 50) == 0).ToList();
var list = cap.Get().Where(dpi => (dpi % 50) == 0).ToList();
comboDPI.DataSource = list;
var cur = (TWFix32)_twain.CurrentSource.CapGetCurrent(CapabilityId.ICapXResolution);
var cur = cap.GetCurrent();
if (list.Contains(cur))
{
comboDPI.SelectedItem = cur;
@@ -369,7 +371,8 @@ namespace Tester.Winform
if (!_loadingCaps && _twain.State == 4)
{
var sel = (TWFix32)comboDPI.SelectedItem;
_twain.CurrentSource.CapSetDPI(sel);
_twain.CurrentSource.CapImageXResolution.Set(sel);
_twain.CurrentSource.CapImageYResolution.Set(sel);
}
}
@@ -377,7 +380,7 @@ namespace Tester.Winform
{
if (!_loadingCaps && _twain.State == 4)
{
_twain.CurrentSource.CapSetDuplex(ckDuplex.Checked);
_twain.CurrentSource.CapDuplexEnabled.Set(ckDuplex.Checked ? BoolType.True : BoolType.False);
}
}