A naive and lazy implementation of mem xfer for #1.

This commit is contained in:
soukoku
2014-04-11 19:25:48 -04:00
parent d3a50099a4
commit efe9b469ba
6 changed files with 74 additions and 63 deletions

View File

@@ -3,9 +3,9 @@ using System;
namespace NTwain namespace NTwain
{ {
/// <summary> /// <summary>
/// Contains event data after whatever data from the source has been transferred. /// Contains event data after whatever data from the source has been transferred.
/// </summary> /// </summary>
public class DataTransferredEventArgs : EventArgs public class DataTransferredEventArgs : EventArgs
{ {
/// <summary> /// <summary>
@@ -17,16 +17,18 @@ namespace NTwain
/// <value>The data pointer.</value> /// <value>The data pointer.</value>
public IntPtr NativeData { get; internal set; } public IntPtr NativeData { get; internal set; }
/// <summary> /// <summary>
/// Gets the file path to the complete data if the transfer was file or memory-file. /// Gets the file path to the complete data if the transfer was file or memory-file.
/// </summary> /// </summary>
/// <value> /// <value>
/// The file. /// The file path.
/// </value> /// </value>
public string FilePath { get; internal set; } public string FileDataPath { get; internal set; }
/// <summary> /// <summary>
/// Gets the memory data if the transfer was memory. /// Gets the raw memory data if the transfer was memory.
/// Consumer application will need to do the parsing based on the values
/// from <see cref="ImageInfo"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// The memory data. /// The memory data.
@@ -39,6 +41,6 @@ namespace NTwain
/// <value> /// <value>
/// The final image information. /// The final image information.
/// </value> /// </value>
public TWImageInfo FinalImageInfo { get; internal set; } public TWImageInfo ImageInfo { get; internal set; }
} }
} }

View File

@@ -14,6 +14,6 @@ namespace NTwain
// keep this same in majors releases // keep this same in majors releases
public const string Release = "0.10.0.0"; public const string Release = "0.10.0.0";
// change this for each nuget release // change this for each nuget release
public const string Build = "0.10.0"; public const string Build = "0.10.1";
} }
} }

View File

@@ -810,7 +810,7 @@ namespace NTwain
var xrc = DGAudio.AudioFileXfer.Get(); var xrc = DGAudio.AudioFileXfer.Get();
if (xrc == ReturnCode.XferDone) if (xrc == ReturnCode.XferDone)
{ {
OnDataTransferred(new DataTransferredEventArgs { FilePath = filePath }); OnDataTransferred(new DataTransferredEventArgs { FileDataPath = filePath });
} }
} }
@@ -837,7 +837,7 @@ namespace NTwain
{ {
lockedPtr = MemoryManager.Instance.Lock(dataPtr); lockedPtr = MemoryManager.Instance.Lock(dataPtr);
} }
OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, FinalImageInfo = imgInfo }); OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, ImageInfo = imgInfo });
} }
} }
finally finally
@@ -874,14 +874,12 @@ namespace NTwain
{ {
imgInfo = null; imgInfo = null;
} }
OnDataTransferred(new DataTransferredEventArgs { FilePath = filePath, FinalImageInfo = imgInfo }); OnDataTransferred(new DataTransferredEventArgs { FileDataPath = filePath, ImageInfo = imgInfo });
} }
} }
private void DoImageMemoryXfer() private void DoImageMemoryXfer()
{ {
throw new NotImplementedException();
TWSetupMemXfer memInfo; TWSetupMemXfer memInfo;
if (DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success) if (DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success)
{ {
@@ -890,7 +888,7 @@ namespace NTwain
{ {
// how to tell if going to xfer in strip vs tile? // how to tell if going to xfer in strip vs tile?
// if tile don't allocate memory in app? // if tile don't allocate memory in app?
xferInfo.Memory = new TWMemory xferInfo.Memory = new TWMemory
{ {
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer, Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
@@ -898,54 +896,65 @@ namespace NTwain
TheMem = MemoryManager.Instance.Allocate(memInfo.Preferred) TheMem = MemoryManager.Instance.Allocate(memInfo.Preferred)
}; };
var xrc = ReturnCode.Success; // do the unthinkable and keep all xferred batches in memory,
do // possibly defeating the purpose of mem xfer
// unless compression is used.
// todo: use array instead of memory stream?
using (MemoryStream xferredData = new MemoryStream())
{ {
xrc = DGImage.ImageMemFileXfer.Get(xferInfo); var xrc = ReturnCode.Success;
do
if (xrc == ReturnCode.Success ||
xrc == ReturnCode.XferDone)
{ {
State = 7; xrc = DGImage.ImageMemFileXfer.Get(xferInfo);
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
// todo: need lock before use? if (xrc == ReturnCode.Success ||
IntPtr lockPtr = IntPtr.Zero; xrc == ReturnCode.XferDone)
try
{ {
lockPtr = MemoryManager.Instance.Lock(xferInfo.Memory.TheMem); State = 7;
Marshal.Copy(lockPtr, buffer, 0, buffer.Length); // optimize and allocate buffer only once instead of inside the loop?
} byte[] buffer = new byte[(int)xferInfo.BytesWritten];
finally
{ IntPtr lockPtr = IntPtr.Zero;
if (lockPtr != IntPtr.Zero) try
{ {
MemoryManager.Instance.Unlock(lockPtr); lockPtr = MemoryManager.Instance.Lock(xferInfo.Memory.TheMem);
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
xferredData.Write(buffer, 0, buffer.Length);
}
finally
{
if (lockPtr != IntPtr.Zero)
{
MemoryManager.Instance.Unlock(lockPtr);
}
} }
} }
// now what? } while (xrc == ReturnCode.Success);
} if (xrc == ReturnCode.XferDone)
} while (xrc == ReturnCode.Success);
if (xrc == ReturnCode.XferDone)
{
TWImageInfo imgInfo;
//TWExtImageInfo extInfo;
//if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
//{
// if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
// {
// extInfo = null;
// }
//}
if (DGImage.ImageInfo.Get(out imgInfo) == ReturnCode.Success)
{ {
//OnDataTransferred(new DataTransferredEventArgs(IntPtr.Zero, null)); TWImageInfo imgInfo;
//TWExtImageInfo extInfo;
//if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
//{
// if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
// {
// extInfo = null;
// }
//}
if (DGImage.ImageInfo.Get(out imgInfo) == ReturnCode.Success)
{
OnDataTransferred(new DataTransferredEventArgs { MemData = xferredData.ToArray(), ImageInfo = imgInfo });
}
else
{
throw new TwainException("Failed to get image info after ImageMemXfer.");
}
} }
else else
{ {
Trace.TraceError("Failed to get image info after ImageMemXfer."); // todo: provide better mechanism for failed xfer, like event handler
imgInfo = null; throw new TwainException("Failed to transfer data.");
} }
} }
} }
@@ -994,7 +1003,7 @@ namespace NTwain
{ {
State = 7; State = 7;
byte[] buffer = new byte[(int)xferInfo.BytesWritten]; byte[] buffer = new byte[(int)xferInfo.BytesWritten];
// todo: need lock before use?
IntPtr lockPtr = IntPtr.Zero; IntPtr lockPtr = IntPtr.Zero;
try try
{ {
@@ -1086,7 +1095,7 @@ namespace NTwain
{ {
imgInfo = null; imgInfo = null;
} }
OnDataTransferred(new DataTransferredEventArgs { FilePath = finalFile, FinalImageInfo = imgInfo }); OnDataTransferred(new DataTransferredEventArgs { FileDataPath = finalFile, ImageInfo = imgInfo });
} }
} }
} }

View File

@@ -120,7 +120,7 @@ namespace NTwain
{ {
lockedPtr = MemoryManager.Instance.Lock(dataPtr); lockedPtr = MemoryManager.Instance.Lock(dataPtr);
} }
OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, FilePath = file }); OnDataTransferred(new DataTransferredEventArgs { NativeData = lockedPtr, FileDataPath = file });
} }
//} //}
//else if (group == DataGroups.Audio) //else if (group == DataGroups.Audio)

View File

@@ -67,9 +67,9 @@ namespace Tester.WPF
{ {
Image = e.NativeData.GetWPFBitmap(); Image = e.NativeData.GetWPFBitmap();
} }
else if (!string.IsNullOrEmpty(e.FilePath)) else if (!string.IsNullOrEmpty(e.FileDataPath))
{ {
var img = new BitmapImage(new Uri(e.FilePath)); var img = new BitmapImage(new Uri(e.FileDataPath));
Image = img; Image = img;
} }
base.OnDataTransferred(e); base.OnDataTransferred(e);

View File

@@ -76,9 +76,9 @@ namespace Tester.Winform
if (img != null) if (img != null)
pictureBox1.Image = img; pictureBox1.Image = img;
} }
else if (!string.IsNullOrEmpty(e.FilePath)) else if (!string.IsNullOrEmpty(e.FileDataPath))
{ {
var img = new Bitmap(e.FilePath); var img = new Bitmap(e.FileDataPath);
pictureBox1.Image = img; pictureBox1.Image = img;
} }
}; };