1
0
mirror of https://github.com/soukoku/ntwain.git synced 2025-04-05 20:59:23 +08:00

Checked for rc in prepre mem xfer calls now.

This commit is contained in:
Eugene Wang 2023-04-08 13:41:20 -04:00
parent c0eb79310f
commit f015e82682
5 changed files with 199 additions and 180 deletions

View File

@ -2299,7 +2299,7 @@ namespace NTwain.Data
/// Describes the form of the acquired data being passed from the Source to the application.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct TW_IMAGEMEMXFER
public partial struct TW_IMAGEMEMXFER
{
public ushort Compression;
public uint BytesPerRow;
@ -2311,7 +2311,7 @@ namespace NTwain.Data
public TW_MEMORY Memory;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct TW_IMAGEMEMXFER_LINUX64
public partial struct TW_IMAGEMEMXFER_LINUX64
{
public ushort Compression;
public UInt64 BytesPerRow;
@ -2326,7 +2326,7 @@ namespace NTwain.Data
public IntPtr MemoryTheMem;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct TW_IMAGEMEMXFER_MACOSX
public partial struct TW_IMAGEMEMXFER_MACOSX
{
public uint Compression;
public uint BytesPerRow;

View File

@ -274,7 +274,7 @@ namespace NTwain.Data
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
{
if (!(MinValue is IConvertible))
if (MinValue is not IConvertible)
throw new NotSupportedException($"The value type {typeof(TValue).Name} is not supported for range enumeration.");
return new DynamicEnumerator(MinValue, MaxValue, StepSize);
@ -779,6 +779,48 @@ namespace NTwain.Data
}
}
partial struct TW_IMAGEMEMXFER
{
/// <summary>
/// Get a don't care version for app use.
/// </summary>
/// <returns></returns>
public static TW_IMAGEMEMXFER DONTCARE()
{
return new TW_IMAGEMEMXFER
{
BytesPerRow = TwainConst.TWON_DONTCARE32,
BytesWritten = TwainConst.TWON_DONTCARE32,
Columns = TwainConst.TWON_DONTCARE32,
Compression = TwainConst.TWON_DONTCARE16,
Rows = TwainConst.TWON_DONTCARE32,
XOffset = TwainConst.TWON_DONTCARE32,
YOffset = TwainConst.TWON_DONTCARE32,
};
}
}
partial struct TW_IMAGEMEMXFER_MACOSX
{
/// <summary>
/// Get a don't care version for app use.
/// </summary>
/// <returns></returns>
public static TW_IMAGEMEMXFER_MACOSX DONTCARE()
{
return new TW_IMAGEMEMXFER_MACOSX
{
BytesPerRow = TwainConst.TWON_DONTCARE32,
BytesWritten = TwainConst.TWON_DONTCARE32,
Columns = TwainConst.TWON_DONTCARE32,
Compression = TwainConst.TWON_DONTCARE32,
Rows = TwainConst.TWON_DONTCARE32,
XOffset = TwainConst.TWON_DONTCARE32,
YOffset = TwainConst.TWON_DONTCARE32,
};
}
}
//partial struct TW_DEVICEEVENT
//{
// public TWDE Event { get { return (TWDE)_event; } }

View File

@ -19,7 +19,7 @@ namespace NTwain
Data = data;
}
public DataTransferredEventArgs(TW_IMAGEINFO info, TW_SETUPFILEXFER? fileInfo, byte[] data)
public DataTransferredEventArgs(TW_IMAGEINFO info, TW_SETUPFILEXFER? fileInfo, byte[]? data)
{
ImageInfo = info;
FileInfo = fileInfo;

View File

@ -8,9 +8,9 @@ namespace NTwain
/// </summary>
public class TransferReadyEventArgs : EventArgs
{
public TransferReadyEventArgs(TwainAppSession twain, int pendingCount, TWEJ endOfJobFlag)
public TransferReadyEventArgs(int pendingCount, TWEJ endOfJobFlag)
{
_twain = twain;
//_twain = twain;
PendingCount = pendingCount;
EndOfJobFlag = endOfJobFlag;
}
@ -38,28 +38,28 @@ namespace NTwain
/// </summary>
public int PendingCount { get; private set; }
TW_IMAGEINFO? _imgInfo;
private readonly TwainAppSession _twain;
//TW_IMAGEINFO? _imgInfo;
//private readonly TwainAppSession _twain;
/// <summary>
/// Gets the tentative image information for the current transfer if applicable.
/// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer).
/// </summary>
public TW_IMAGEINFO? PendingImageInfo
{
get
{
// only get it if requested since it could be slow
if (!_imgInfo.HasValue)
{
if (_twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS)
{
_imgInfo = info;
}
}
return _imgInfo;
}
}
///// <summary>
///// Gets the tentative image information for the current transfer if applicable.
///// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer).
///// </summary>
//public TW_IMAGEINFO? PendingImageInfo
//{
// get
// {
// // only get it if requested since it could be slow
// if (!_imgInfo.HasValue)
// {
// if (_twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS)
// {
// _imgInfo = info;
// }
// }
// return _imgInfo;
// }
//}
}

View File

@ -22,11 +22,6 @@ namespace NTwain
// so the array max is made with 32 MB. Typical usage should be a lot less.
static readonly ArrayPool<byte> XferMemPool = ArrayPool<byte>.Create(32 * 1024 * 1024, 8);
internal STS GetImageInfo(out TW_IMAGEINFO info)
{
return WrapInSTS(DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out info));
}
/// <summary>
/// Start the transfer loop.
@ -70,7 +65,7 @@ namespace NTwain
{
do
{
var readyArgs = new TransferReadyEventArgs(this, pending.Count, (TWEJ)pending.EOJ);
var readyArgs = new TransferReadyEventArgs(pending.Count, (TWEJ)pending.EOJ);
_uiThreadMarshaller.Invoke((ref TW_PENDINGXFERS pending) =>
{
try
@ -214,7 +209,9 @@ namespace NTwain
{
// assuming user already configured the transfer in transferready event,
// get what will be transferred
DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup);
var rc = DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup);
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
// and just start it
var sts = WrapInSTS(DGAudio.AudioFileXfer.Get(ref _appIdentity, ref _currentDS));
if (sts.RC == TWRC.XFERDONE)
@ -285,84 +282,78 @@ namespace NTwain
private STS TransferMemoryImage(ref TW_PENDINGXFERS pending)
{
var rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup);
if (rc == TWRC.SUCCESS)
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
rc = DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info);
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
rc = DGImage.ImageLayout.Get(ref _appIdentity, ref _currentDS, out TW_IMAGELAYOUT layout);
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
uint buffSize = memSetup.DetermineBufferSize();
var memPtr = Alloc(buffSize);
TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE();
TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE();
memXfer.Memory = new TW_MEMORY
{
uint buffSize = memSetup.DetermineBufferSize();
var memPtr = Alloc(buffSize);
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
};
memXferOSX.Memory = memXfer.Memory;
TW_IMAGEMEMXFER memXfer = new()
byte[] dotnetBuff = XferMemPool.Rent((int)buffSize);
try
{
do
{
Memory = new TW_MEMORY
{
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
}
};
TW_IMAGEMEMXFER_MACOSX memXferOSX = new()
{
Memory = new TW_MEMORY
{
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
}
};
rc = TwainPlatform.IsMacOSX ?
DGImage.ImageMemXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) :
DGImage.ImageMemXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer);
byte[] dotnetBuff = XferMemPool.Rent((int)buffSize);
if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE)
{
try
{
var written = TwainPlatform.IsMacOSX ?
memXferOSX.BytesWritten : memXfer.BytesWritten;
IntPtr lockedPtr = Lock(memPtr);
// assemble!
//Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written);
//outStream.Write(dotnetBuff, 0, (int)written);
}
finally
{
Unlock(memPtr);
}
}
} while (rc == TWRC.SUCCESS);
}
finally
{
if (memPtr != IntPtr.Zero) Free(memPtr);
XferMemPool.Return(dotnetBuff);
}
if (rc == TWRC.XFERDONE)
{
try
{
do
{
rc = TwainPlatform.IsMacOSX ?
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) :
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer);
if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE)
{
try
{
var written = TwainPlatform.IsMacOSX ?
memXferOSX.BytesWritten : memXfer.BytesWritten;
IntPtr lockedPtr = Lock(memPtr);
// assemble!
//Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written);
//outStream.Write(dotnetBuff, 0, (int)written);
}
finally
{
Unlock(memPtr);
}
}
} while (rc == TWRC.SUCCESS);
DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out info);
//var args = new DataTransferredEventArgs(info, null, outStream.ToArray());
//DataTransferred?.Invoke(this, args);
}
finally
catch { }
var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending));
if (sts.RC == TWRC.SUCCESS)
{
if (memPtr != IntPtr.Zero) Free(memPtr);
XferMemPool.Return(dotnetBuff);
}
if (rc == TWRC.XFERDONE)
{
try
{
GetImageInfo(out TW_IMAGEINFO info);
//var args = new DataTransferredEventArgs(info, null, outStream.ToArray());
//DataTransferred?.Invoke(this, args);
}
catch { }
var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending));
if (sts.RC == TWRC.SUCCESS)
{
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
}
return sts;
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
}
return sts;
}
return WrapInSTS(rc);
}
@ -370,94 +361,80 @@ namespace NTwain
private STS TransferMemoryFileImage(ref TW_PENDINGXFERS pending)
{
var rc = DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup);
if (rc == TWRC.SUCCESS)
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup);
if (rc != TWRC.SUCCESS) return WrapInSTS(rc);
uint buffSize = memSetup.DetermineBufferSize();
var memPtr = Alloc(buffSize);
TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE();
TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE();
memXfer.Memory = new TW_MEMORY
{
rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup);
if (rc == TWRC.SUCCESS)
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
};
memXferOSX.Memory = memXfer.Memory;
// TODO: how to get actual file size before hand? Is it imagelayout?
// otherwise will just write to stream with lots of copies
byte[] dotnetBuff = XferMemPool.Rent((int)buffSize);
using var outStream = new MemoryStream();
try
{
do
{
uint buffSize = memSetup.DetermineBufferSize();
var memPtr = Alloc(buffSize);
rc = TwainPlatform.IsMacOSX ?
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) :
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer);
TW_IMAGEMEMXFER memXfer = new()
{
Memory = new TW_MEMORY
{
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
}
};
TW_IMAGEMEMXFER_MACOSX memXferOSX = new()
{
Memory = new TW_MEMORY
{
Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER),
Length = buffSize,
TheMem = memPtr
}
};
// TODO: how to get actual file size before hand?
// otherwise will just write to stream with lots of copies
byte[] dotnetBuff = XferMemPool.Rent((int)buffSize);
using var outStream = new MemoryStream();
try
{
do
{
rc = TwainPlatform.IsMacOSX ?
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) :
DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer);
if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE)
{
try
{
var written = TwainPlatform.IsMacOSX ?
memXferOSX.BytesWritten : memXfer.BytesWritten;
IntPtr lockedPtr = Lock(memPtr);
Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written);
outStream.Write(dotnetBuff, 0, (int)written);
}
finally
{
Unlock(memPtr);
}
}
} while (rc == TWRC.SUCCESS);
}
finally
{
if (memPtr != IntPtr.Zero) Free(memPtr);
XferMemPool.Return(dotnetBuff);
}
if (rc == TWRC.XFERDONE)
if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE)
{
try
{
GetImageInfo(out TW_IMAGEINFO info);
// ToArray bypasses the XferMemPool but I guess this will have to do for now
var args = new DataTransferredEventArgs(info, fileSetup, outStream.ToArray());
DataTransferred?.Invoke(this, args);
}
catch { }
var written = TwainPlatform.IsMacOSX ?
memXferOSX.BytesWritten : memXfer.BytesWritten;
var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending));
if (sts.RC == TWRC.SUCCESS)
{
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
IntPtr lockedPtr = Lock(memPtr);
Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written);
outStream.Write(dotnetBuff, 0, (int)written);
}
finally
{
Unlock(memPtr);
}
return sts;
}
} while (rc == TWRC.SUCCESS);
}
finally
{
if (memPtr != IntPtr.Zero) Free(memPtr);
XferMemPool.Return(dotnetBuff);
}
if (rc == TWRC.XFERDONE)
{
try
{
DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info);
// ToArray bypasses the XferMemPool but I guess this will have to do for now
var args = new DataTransferredEventArgs(info, fileSetup, outStream.ToArray());
DataTransferred?.Invoke(this, args);
}
catch { }
var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending));
if (sts.RC == TWRC.SUCCESS)
{
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
}
return sts;
}
return WrapInSTS(rc);
}
private STS TransferFileImage(ref TW_PENDINGXFERS pending)
{
// assuming user already configured the transfer in transferready event,
@ -470,7 +447,7 @@ namespace NTwain
State = STATE.S7;
try
{
GetImageInfo(out TW_IMAGEINFO info);
DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info);
var args = new DataTransferredEventArgs(info, fileSetup, null);
DataTransferred?.Invoke(this, args);
}
@ -517,7 +494,7 @@ namespace NTwain
{
try
{
GetImageInfo(out TW_IMAGEINFO info);
DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info);
var args = new DataTransferredEventArgs(info, null, data);
DataTransferred?.Invoke(this, args);
}