#74 expose memory transfer data as-is.

This commit is contained in:
Eugene Wang 2017-02-02 19:48:01 -05:00
parent 7a8b0d0772
commit 0852092e11
8 changed files with 91 additions and 65 deletions

1
.gitignore vendored
View File

@ -156,3 +156,4 @@ $RECYCLE.BIN/
.DS_Store
/packages
*.nupkg
/.vs

View File

@ -71,8 +71,7 @@
<Private>True</Private>
</Reference>
<Reference Include="ModernWpf.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c99d0cfbea7491ef, processorArchitecture=MSIL">
<HintPath>..\..\packages\ModernWpf.Core.2.0.0-alpha94\lib\net40-Client\ModernWpf.Core.dll</HintPath>
<Private>True</Private>
<HintPath>..\..\packages\ModernWpf.Core.2.0.0-alpha96\lib\net40-Client\ModernWpf.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />

View File

@ -274,7 +274,8 @@ namespace Sample.WPF
void _session_TransferReady(object sender, TransferReadyEventArgs e)
{
if (_session.CurrentSource.Capabilities.ICapXferMech.GetCurrent() == XferMech.File)
var mech = _session.CurrentSource.Capabilities.ICapXferMech.GetCurrent();
if (mech == XferMech.File)
{
var formats = _session.CurrentSource.Capabilities.ICapImageFileFormat.GetValues();
var wantFormat = formats.Contains(FileFormat.Tiff) ? FileFormat.Tiff : FileFormat.Bmp;
@ -286,6 +287,11 @@ namespace Sample.WPF
};
var rc = _session.CurrentSource.DGControl.SetupFileXfer.Set(fileSetup);
}
else if (mech == XferMech.Memory)
{
// ?
}
}
string GetUniqueName(string dir, string name, string ext)
@ -315,19 +321,28 @@ namespace Sample.WPF
ImageSource GenerateThumbnail(DataTransferredEventArgs e)
{
BitmapSource img = null;
if (e.NativeData != IntPtr.Zero)
switch (e.TransferType)
{
using (var stream = e.GetNativeImageStream())
{
if (stream != null)
case XferMech.Native:
using (var stream = e.GetNativeImageStream())
{
img = stream.ConvertToWpfBitmap(300, 0);
if (stream != null)
{
img = stream.ConvertToWpfBitmap(300, 0);
}
}
}
}
else if (!string.IsNullOrEmpty(e.FileDataPath))
{
img = new BitmapImage(new Uri(e.FileDataPath));
break;
case XferMech.File:
img = new BitmapImage(new Uri(e.FileDataPath));
if (img.CanFreeze)
{
img.Freeze();
}
break;
case XferMech.Memory:
// TODO: build current image from multiple data-xferred event
break;
}
//if (img != null)

View File

@ -4,6 +4,6 @@
<package id="Microsoft.WindowsAPICodePack-Core" version="1.1.0.2" targetFramework="net4-client" />
<package id="Microsoft.WindowsAPICodePack-Shell" version="1.1.0.0" targetFramework="net4-client" />
<package id="ModernWpf" version="2.0.0-alpha94" targetFramework="net40-client" />
<package id="ModernWpf.Core" version="2.0.0-alpha94" targetFramework="net40-client" />
<package id="ModernWpf.Core" version="2.0.0-alpha96" targetFramework="net40-client" />
<package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net40-client" />
</packages>

View File

@ -1921,9 +1921,9 @@ namespace NTwain.Data
}
/// <summary>
/// Describes the form of the acquired data being passed from the Source to the application.
/// Describes the form of the acquired data being passed from the Source to the application in memory transfer mode.
/// </summary>
partial class TWImageMemXfer
public partial class TWImageMemXfer
{
/// <summary>
/// The compression method used to process the data being transferred.
@ -1965,7 +1965,7 @@ namespace NTwain.Data
/// buffer, the actual size of the buffer, in bytes, and where the buffer is
/// located in memory.
/// </summary>
public TWMemory Memory { get { return _memory; } internal set { _memory = value; } }
internal TWMemory Memory { get { return _memory; } set { _memory = value; } }
}
/// <summary>

View File

@ -25,17 +25,19 @@ namespace NTwain
/// <param name="nativeData">The native data.</param>
public DataTransferredEventArgs(DataSource source, IntPtr nativeData)
{
TransferType = XferMech.Native;
DataSource = source;
NativeData = nativeData;
}
/// <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="imageFileFormat">The image file format.</param>
public DataTransferredEventArgs(DataSource source, string fileDataPath, FileFormat imageFileFormat)
{
TransferType = XferMech.File;
DataSource = source;
FileDataPath = fileDataPath;
ImageFileFormat = imageFileFormat;
@ -44,15 +46,26 @@ namespace NTwain
/// Initializes a new instance of the <see cref="DataTransferredEventArgs" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="memoryInfo">The memory information.</param>
/// <param name="memoryData">The memory data.</param>
public DataTransferredEventArgs(DataSource source, byte[] memoryData)
public DataTransferredEventArgs(DataSource source, TWImageMemXfer memoryInfo, byte[] memoryData)
{
TransferType = XferMech.Memory;
DataSource = source;
MemoryInfo = memoryInfo;
MemoryData = memoryData;
}
/// <summary>
/// Gets pointer to the complete data if the transfer was native.
/// Gets the type of the transfer mode.
/// </summary>
/// <value>
/// The type of the transfer.
/// </value>
public XferMech TransferType { get; private set; }
/// <summary>
/// Gets the raw pointer to the complete data if <see cref="TransferType"/> is <see cref="XferMech.Native"/>.
/// The data will be freed once the event handler ends
/// so consumers must complete whatever processing before then.
/// For image type this data is DIB (Windows) or TIFF (Linux).
@ -63,6 +76,7 @@ namespace NTwain
/// <summary>
/// Gets the file path to the complete data if the transfer was file or memory-file.
/// This is only available if <see cref="TransferType"/> is <see cref="XferMech.File"/>.
/// </summary>
/// <value>
/// The file path.
@ -71,12 +85,22 @@ namespace NTwain
/// <summary>
/// Gets the file format if applicable.
/// This is only available if <see cref="TransferType"/> is <see cref="XferMech.Memory"/>.
/// </summary>
/// <value>
/// The file format.
/// </value>
public FileFormat ImageFileFormat { get; private set; }
/// <summary>
/// Gets the info object if the transfer was memory.
/// This is only available if <see cref="TransferType"/> is <see cref="XferMech.Memory"/>.
/// </summary>
/// <value>
/// The memory information.
/// </value>
public TWImageMemXfer MemoryInfo { get; private set; }
/// <summary>
/// Gets the raw memory data if the transfer was memory.
/// Consumer application will need to do the parsing based on the values
@ -166,7 +190,7 @@ namespace NTwain
{
retVal = ImageTools.GetTiffStream(NativeData);
}
}
return retVal; ;
}

View File

@ -99,7 +99,7 @@ namespace NTwain.Internals
}
}
}
if (rc != ReturnCode.Success && session.StopOnTransferError)
{
// end xfer without setting rc to exit (good/bad?)
@ -234,7 +234,7 @@ namespace NTwain.Internals
{
lockedPtr = PlatformInfo.Current.MemoryManager.Lock(dataPtr);
}
DoImageXferredEventRoutine(session, lockedPtr, null, null, (FileFormat)0);
DoImageXferredEventRoutine(session, lockedPtr, null, null, null, (FileFormat)0);
}
else
{
@ -276,7 +276,7 @@ namespace NTwain.Internals
var xrc = session.DGImage.ImageFileXfer.Get();
if (xrc == ReturnCode.XferDone)
{
DoImageXferredEventRoutine(session, IntPtr.Zero, null, filePath, setupInfo.Format);
DoImageXferredEventRoutine(session, IntPtr.Zero, null, null, filePath, setupInfo.Format);
}
else
{
@ -304,50 +304,37 @@ namespace NTwain.Internals
TheMem = PlatformInfo.Current.MemoryManager.Allocate(memInfo.Preferred)
};
// do the unthinkable and keep all xferred batches in memory,
// possibly defeating the purpose of mem xfer
// unless compression is used.
// todo: use array instead of memory stream?
using (MemoryStream xferredData = new MemoryStream())
do
{
do
xrc = session.DGImage.ImageMemXfer.Get(xferInfo);
if (xrc == ReturnCode.Success ||
xrc == ReturnCode.XferDone)
{
xrc = session.DGImage.ImageMemXfer.Get(xferInfo);
if (session.State != 7) { session.ChangeState(7, true); }
if (xrc == ReturnCode.Success ||
xrc == ReturnCode.XferDone)
// optimize and allocate buffer only once instead of inside the loop?
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
IntPtr lockPtr = IntPtr.Zero;
try
{
session.ChangeState(7, true);
// optimize and allocate buffer only once instead of inside the loop?
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
IntPtr lockPtr = IntPtr.Zero;
try
lockPtr = PlatformInfo.Current.MemoryManager.Lock(xferInfo.Memory.TheMem);
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
}
finally
{
if (lockPtr != IntPtr.Zero)
{
lockPtr = PlatformInfo.Current.MemoryManager.Lock(xferInfo.Memory.TheMem);
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
xferredData.Write(buffer, 0, buffer.Length);
}
finally
{
if (lockPtr != IntPtr.Zero)
{
PlatformInfo.Current.MemoryManager.Unlock(xferInfo.Memory.TheMem);
//PlatformInfo.Current.MemoryManager.Unlock(lockPtr);
}
PlatformInfo.Current.MemoryManager.Unlock(xferInfo.Memory.TheMem);
}
}
} while (xrc == ReturnCode.Success);
DoImageXferredEventRoutine(session, IntPtr.Zero, xferInfo, buffer, null, (FileFormat)0);
}
} while (xrc == ReturnCode.Success);
if (xrc == ReturnCode.XferDone)
{
DoImageXferredEventRoutine(session, IntPtr.Zero, xferredData.ToArray(), null, (FileFormat)0);
}
else
{
HandleReturnCode(session, xrc);
}
}
HandleReturnCode(session, xrc);
}
catch (Exception ex)
{
@ -449,13 +436,13 @@ namespace NTwain.Internals
if (File.Exists(finalFile))
{
DoImageXferredEventRoutine(session, IntPtr.Zero, null, finalFile, fileInfo.Format);
DoImageXferredEventRoutine(session, IntPtr.Zero, null, null, finalFile, fileInfo.Format);
}
}
return xrc;
}
static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, byte[] dataArray, string filePath, FileFormat format)
static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, TWImageMemXfer memInfo, byte[] memData, string filePath, FileFormat format)
{
DataTransferredEventArgs args = null;
@ -463,9 +450,9 @@ namespace NTwain.Internals
{
args = new DataTransferredEventArgs(session.CurrentSource, dataPtr);
}
else if (dataArray != null)
else if (memData != null)
{
args = new DataTransferredEventArgs(session.CurrentSource, dataArray);
args = new DataTransferredEventArgs(session.CurrentSource, memInfo, memData);
}
else
{

View File

@ -23,7 +23,7 @@ namespace NTwain
/// <summary>
/// The build release version number.
/// </summary>
public const string Build = "3.3.9.5"; // change this for each nuget release
public const string Build = "3.4.0"; // change this for each nuget release
}