Added support for getting ext image info during data transfer event.

This commit is contained in:
soukoku
2014-10-31 18:20:13 -04:00
parent 57d7dbe0ef
commit e19c2ad490
12 changed files with 182 additions and 116 deletions

View File

@@ -208,7 +208,8 @@ namespace NTwain.Data
TW_UINT16 _itemType;
TW_UINT16 _numItems;
TW_UINT16 _returnCode;
TW_UINTPTR _item;
//TW_UINTPTR _item;
TW_HANDLE _item; // easier to work with intptr
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]

View File

@@ -657,7 +657,7 @@ namespace NTwain.Data
ContainerType = ContainerType.OneValue;
SetOneValue(value, memoryManager);
}
/// <summary>
/// Initializes a new instance of the <see cref="TWCapability" /> class.
/// </summary>
@@ -1374,7 +1374,7 @@ namespace NTwain.Data
/// This structure is used to pass specific information between the data source and the application
/// through <see cref="TWExtImageInfo"/>.
/// </summary>
[DebuggerDisplay("Type = {ItemType}")]
[DebuggerDisplay("ID = {InfoID}, Type = {ItemType}")]
public partial struct TWInfo
{
/// <summary>
@@ -1407,7 +1407,101 @@ namespace NTwain.Data
/// If the Item field contains a handle to data, then the Application is
/// responsible for freeing that memory.
/// </summary>
public UIntPtr Item { get { return _item; } internal set { _item = value; } }
public IntPtr Item { get { return _item; } internal set { _item = value; } }
bool ItemIsPointer
{
get
{
return ItemType == Data.ItemType.Handle ||
(TypeReader.GetItemTypeSize(ItemType) * NumItems) > 4;// IntPtr.Size
}
}
/// <summary>
/// Try to reads the values from the <see cref="Item"/> property.
/// </summary>
/// <returns></returns>
public List<object> ReadValues()
{
var values = new List<object>();
if (NumItems > 0)
{
if (ItemIsPointer)
{
if (Item != IntPtr.Zero)
{
IntPtr lockPtr = IntPtr.Zero;
try
{
int offset = 0;
lockPtr = PlatformInfo.Current.MemoryManager.Lock(Item);
for (int i = 0; i < NumItems; i++)
{
values.Add(TypeReader.ReadValue(lockPtr, ref offset, ItemType));
}
}
finally
{
if (lockPtr != IntPtr.Zero)
{
PlatformInfo.Current.MemoryManager.Unlock(lockPtr);
}
}
}
}
else
{
// do the lame and create a ptr to the value so we can reuse TypeReader
IntPtr tempPtr = IntPtr.Zero;
try
{
tempPtr = Marshal.AllocHGlobal(IntPtr.Size);
Marshal.WriteIntPtr(tempPtr, Item);
int offset = 0;
values.Add(TypeReader.ReadValue(tempPtr, ref offset, ItemType));
}
finally
{
if (tempPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(tempPtr);
}
}
}
}
return values;
}
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
//GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing) { }
if (ItemIsPointer && Item != IntPtr.Zero)
{
PlatformInfo.Current.MemoryManager.Free(Item);
}
Item = IntPtr.Zero;
}
//~TWInfo()
//{
// Dispose(false);
//}
#endregion
}
/// <summary>
@@ -1418,7 +1512,7 @@ namespace NTwain.Data
/// using the above operation triplet. The data source then examines each Info, and fills the rest of
/// data with information allocating memory when necessary.
/// </summary>
public sealed partial class TWExtImageInfo : IDisposable
sealed partial class TWExtImageInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="TWExtImageInfo"/> class.
@@ -1440,50 +1534,6 @@ namespace NTwain.Data
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public TWInfo[] Info { get { return _info; } }
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing) { }
// this is iffy & may have to flatten info array as individual fields in this class to work
if (_info != null)
{
for (int i = 0; i < _info.Length; i++)
{
var it = _info[i];
if (it.Item != UIntPtr.Zero)
{
var sz = it.NumItems * TypeReader.GetItemTypeSize(it.ItemType);
if (sz > UIntPtr.Size || it.ItemType == ItemType.Handle)
{
// uintptr to intptr could be bad
var ptr = new IntPtr(BitConverter.ToInt64(BitConverter.GetBytes(it.Item.ToUInt64()), 0));
PlatformInfo.Current.MemoryManager.Free(ptr);
}
}
it.Item = UIntPtr.Zero;
}
}
}
/// <summary>
/// Finalizes an instance of the <see cref="TWExtImageInfo"/> class.
/// </summary>
~TWExtImageInfo()
{
Dispose(false);
}
#endregion
}
/// <summary>

View File

@@ -56,16 +56,10 @@ namespace NTwain.Data
frame.Bottom = (TWFix32)ReadValue(baseAddress, ref offset, ItemType.Fix32);
return frame; // no need to update offset again after reading fix32
case ItemType.String128:
val = ReadString(baseAddress, offset, TwainConst.String128 - 2);
break;
case ItemType.String255:
val = ReadString(baseAddress, offset, TwainConst.String255 - 1);
break;
case ItemType.String32:
val = ReadString(baseAddress, offset, TwainConst.String32 - 2);
break;
case ItemType.String64:
val = ReadString(baseAddress, offset, TwainConst.String64 - 2);
val = Marshal.PtrToStringAnsi(new IntPtr(baseAddress.ToInt64() + offset));
break;
case ItemType.Handle:
val = Marshal.ReadIntPtr(baseAddress, offset);
@@ -75,25 +69,6 @@ namespace NTwain.Data
return val;
}
static string ReadString(IntPtr baseAddr, int offset, int maxLength)
{
// does this work cross-platform?
var val = Marshal.PtrToStringAnsi(new IntPtr(baseAddr.ToInt64() + offset));
if (val.Length > maxLength)
{
// bad source, whatever
}
return val;
//var sb = new StringBuilder(maxLength);
//byte bt;
//while (sb.Length < maxLength &&
// (bt = Marshal.ReadByte(baseAddr, offset++)) != 0)
//{
// sb.Append((char)bt);
//}
//return sb.ToString();
}
static readonly Dictionary<ItemType, int> __sizes = GenerateSizes();
private static Dictionary<ItemType, int> GenerateSizes()
@@ -112,6 +87,7 @@ namespace NTwain.Data
sizes[ItemType.String64] = TwainConst.String64;
sizes[ItemType.String128] = TwainConst.String128;
sizes[ItemType.String255] = TwainConst.String255;
// TODO: find out if it should be fixed 4 bytes or intptr size
sizes[ItemType.Handle] = IntPtr.Size;
return sizes;

View File

@@ -1,5 +1,7 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
namespace NTwain
{
@@ -9,32 +11,38 @@ namespace NTwain
public class DataTransferredEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="DataTransferredEventArgs"/> class.
/// Initializes a new instance of the <see cref="DataTransferredEventArgs" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="nativeData">The native data.</param>
/// <param name="imageInfo">The image information.</param>
public DataTransferredEventArgs(IntPtr nativeData, TWImageInfo imageInfo)
public DataTransferredEventArgs(DataSource source, IntPtr nativeData, TWImageInfo imageInfo)
{
DataSource = source;
NativeData = nativeData;
ImageInfo = imageInfo;
}
/// <summary>
/// Initializes a new instance of the <see cref="DataTransferredEventArgs"/> class.
/// Initializes a new instance of the <see cref="DataTransferredEventArgs" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="fileDataPath">The file data path.</param>
/// <param name="imageInfo">The image information.</param>
public DataTransferredEventArgs(string fileDataPath, TWImageInfo imageInfo)
public DataTransferredEventArgs(DataSource source, string fileDataPath, TWImageInfo imageInfo)
{
DataSource = source;
FileDataPath = fileDataPath;
ImageInfo = imageInfo;
}
/// <summary>
/// Initializes a new instance of the <see cref="DataTransferredEventArgs"/> class.
/// Initializes a new instance of the <see cref="DataTransferredEventArgs" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="memoryData">The memory data.</param>
/// <param name="imageInfo">The image information.</param>
public DataTransferredEventArgs(byte[] memoryData, TWImageInfo imageInfo)
public DataTransferredEventArgs(DataSource source, byte[] memoryData, TWImageInfo imageInfo)
{
DataSource = source;
MemoryData = memoryData;
ImageInfo = imageInfo;
}
@@ -76,12 +84,41 @@ namespace NTwain
/// </value>
public TWImageInfo ImageInfo { get; private set; }
///// <summary>
///// Gets the extended image information if applicable.
///// </summary>
///// <value>
///// The extended image information.
///// </value>
//public TWExtImageInfo ExImageInfo { get; internal set; }
/// <summary>
/// Gets the data source.
/// </summary>
/// <value>
/// The data source.
/// </value>
public DataSource DataSource { get; private set; }
/// <summary>
/// Gets the extended image information if applicable.
/// </summary>
/// <param name="infoIds">The information ids.</param>
/// <returns></returns>
/// <exception cref="System.InvalidOperationException"></exception>
public IEnumerable<TWInfo> GetExtImageInfo(params ExtendedImageInfo[] infoIds)
{
if (infoIds != null && infoIds.Length > 0 && DataSource.SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
{
var request = new TWExtImageInfo { NumInfos = (uint)infoIds.Length };
if (infoIds.Length > request.Info.Length)
{
throw new InvalidOperationException(string.Format("Info ID array excdd maximum length of {0}.", request.Info.Length));
}
for (int i = 0; i < infoIds.Length; i++)
{
request.Info[i].InfoID = infoIds[i];
}
if (DataSource.DGImage.ExtImageInfo.Get(request) == ReturnCode.Success)
{
return request.Info.Where(it => it.InfoID != ExtendedImageInfo.Invalid);
}
}
return Enumerable.Empty<TWInfo>();
}
}
}

View File

@@ -137,7 +137,7 @@ namespace NTwain.Internals
lockedPtr = PlatformInfo.Current.MemoryManager.Lock(dataPtr);
}
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(lockedPtr, null));
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, lockedPtr, null));
}
else
{
@@ -177,7 +177,7 @@ namespace NTwain.Internals
var xrc = session.DGAudio.AudioFileXfer.Get();
if (xrc == ReturnCode.XferDone)
{
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(filePath, null));
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, filePath, null));
}
else
{
@@ -420,32 +420,24 @@ namespace NTwain.Internals
{
DataTransferredEventArgs args = null;
TWImageInfo imgInfo;
//TWExtImageInfo extInfo = null;
//if (session.CurrentSource.SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
//{
// if (session.DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
// {
// extInfo = null;
// }
//}
if (session.DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
imgInfo = null;
}
if (dataPtr != IntPtr.Zero)
{
args = new DataTransferredEventArgs(dataPtr, imgInfo);
args = new DataTransferredEventArgs(session.CurrentSource, dataPtr, imgInfo);
}
else if (dataArray != null)
{
args = new DataTransferredEventArgs(dataArray, imgInfo);
args = new DataTransferredEventArgs(session.CurrentSource, dataArray, imgInfo);
}
else
{
args = new DataTransferredEventArgs(filePath, imgInfo);
args = new DataTransferredEventArgs(session.CurrentSource, filePath, imgInfo);
}
session.SafeSyncableRaiseEvent(args);
//if (extInfo != null) { extInfo.Dispose(); }
}
#endregion

View File

@@ -26,7 +26,7 @@
<RunCodeAnalysis>false</RunCodeAnalysis>
<DocumentationFile>
</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -37,7 +37,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\NTwain.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>

View File

@@ -6,7 +6,7 @@ namespace NTwain.Triplets
/// <summary>
/// Represents <see cref="DataArgumentType.ExtImageInfo"/>.
/// </summary>
public sealed class ExtImageInfo : TripletBase
sealed class ExtImageInfo : TripletBase
{
internal ExtImageInfo(ITwainSessionInternal session) : base(session) { }

View File

@@ -34,7 +34,7 @@ namespace NTwain.Triplets
/// <summary>
/// Gets the operations defined for DAT_EXTIMAGEINFO.
/// </summary>
public ExtImageInfo ExtImageInfo
internal ExtImageInfo ExtImageInfo
{
get
{

View File

@@ -8,7 +8,7 @@
<Style TargetType="{x:Type Rectangle}" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ModernWPF;component/Themes/ModernBase.xaml" />
<ResourceDictionary Source="/ModernWPF;component/Themes/ModernBaseDesktop.xaml" />
<ResourceDictionary Source="/ModernWPF;component/Themes/ModernLight.xaml" />
<ResourceDictionary Source="/ModernWPF;component/Themes/ModernStyles.xaml" />

View File

@@ -47,13 +47,13 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\CommonWin32.2.0.5.4\lib\net35-Client\CommonWin32.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight, Version=4.4.32.16316, Culture=neutral, PublicKeyToken=6bdae7d54059775e, processorArchitecture=MSIL">
<Reference Include="GalaSoft.MvvmLight, Version=5.0.2.32240, Culture=neutral, PublicKeyToken=0e453835af4ee6ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\MvvmLightLibs.4.4.32.5\lib\net40\GalaSoft.MvvmLight.dll</HintPath>
<HintPath>..\..\packages\MvvmLightLibs.5.0.2.0\lib\net40\GalaSoft.MvvmLight.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight.Extras, Version=4.4.32.16316, Culture=neutral, PublicKeyToken=e607f4f44c21a743, processorArchitecture=MSIL">
<Reference Include="GalaSoft.MvvmLight.Extras, Version=5.0.2.32240, Culture=neutral, PublicKeyToken=f46ff315b1088208, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\MvvmLightLibs.4.4.32.5\lib\net40\GalaSoft.MvvmLight.Extras.dll</HintPath>
<HintPath>..\..\packages\MvvmLightLibs.5.0.2.0\lib\net40\GalaSoft.MvvmLight.Extras.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -61,13 +61,13 @@
</Reference>
<Reference Include="ModernWPF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c99d0cfbea7491ef, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\ModernWPF.1.2.5\lib\net40-Client\ModernWPF.dll</HintPath>
<HintPath>..\..\packages\ModernWPF.1.2.8\lib\net40-Client\ModernWPF.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\MvvmLightLibs.4.4.32.5\lib\net40\System.Windows.Interactivity.dll</HintPath>
<HintPath>..\..\packages\MvvmLightLibs.5.0.2.0\lib\net40\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />

View File

@@ -2,6 +2,6 @@
<packages>
<package id="CommonServiceLocator" version="1.3" targetFramework="net40-Client" />
<package id="CommonWin32" version="2.0.5.4" targetFramework="net40-Client" />
<package id="ModernWPF" version="1.2.5" targetFramework="net40-Client" />
<package id="MvvmLightLibs" version="4.4.32.5" targetFramework="net40-Client" />
<package id="ModernWPF" version="1.2.8" targetFramework="net40-Client" />
<package id="MvvmLightLibs" version="5.0.2.0" targetFramework="net40-Client" />
</packages>

View File

@@ -68,6 +68,16 @@ namespace Tester.Winform
};
_twain.DataTransferred += (s, e) =>
{
// example on getting ext image info
var infos = e.GetExtImageInfo(ExtendedImageInfo.Camera).Where(it => it.ReturnCode == ReturnCode.Success);
foreach (var it in infos)
{
var values = it.ReadValues();
Debug.WriteLine(string.Format("{0} = {1}", it.InfoID, values.FirstOrDefault()));
break;
}
// handle image data
Bitmap img = null;
if (e.NativeData != IntPtr.Zero)
{
@@ -312,7 +322,7 @@ namespace Tester.Winform
groupSize.Text = labelTest;
}
}
private void LoadDuplex(CapWrapper<BoolType> cap)
{