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:
parent
c0eb79310f
commit
f015e82682
@ -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;
|
||||
|
@ -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; } }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user