From 830dc8cd9b842d596303d7b788501c0c2ea55d77 Mon Sep 17 00:00:00 2001 From: Eugene Wang <8755753+soukoku@users.noreply.github.com> Date: Sat, 8 Apr 2023 12:07:30 -0400 Subject: [PATCH] Updated mem file xfer with right buffer size and osx calls. --- src/NTwain/TwainAppSession.Xfers.cs | 51 ++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/NTwain/TwainAppSession.Xfers.cs b/src/NTwain/TwainAppSession.Xfers.cs index 49cb6fc..3909d95 100644 --- a/src/NTwain/TwainAppSession.Xfers.cs +++ b/src/NTwain/TwainAppSession.Xfers.cs @@ -275,17 +275,29 @@ namespace NTwain rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup); if (rc == TWRC.SUCCESS) { - // TODO: mac version - var buffSize = Math.Max(memSetup.Preferred, 4096); + uint buffSize = DetermineBufferSize(memSetup); + var memPtr = Alloc(buffSize); + TW_IMAGEMEMXFER memXfer = new() { Memory = new TW_MEMORY { Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER), Length = buffSize, - TheMem = Alloc(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); @@ -294,25 +306,31 @@ namespace NTwain { do { - rc = DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer); + 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 { - IntPtr lockedPtr = Lock(memXfer.Memory.TheMem); - Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)memXfer.BytesWritten); - outStream.Write(dotnetBuff, 0, (int)memXfer.BytesWritten); + 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(memXfer.Memory.TheMem); + Unlock(memPtr); } } } while (rc == TWRC.SUCCESS); } finally { - if (memXfer.Memory.TheMem != IntPtr.Zero) Free(memXfer.Memory.TheMem); + if (memPtr != IntPtr.Zero) Free(memPtr); XferMemPool.Return(dotnetBuff); } @@ -339,6 +357,21 @@ namespace NTwain return WrapInSTS(rc); } + private static uint DetermineBufferSize(TW_SETUPMEMXFER memSetup) + { + // default to 16 kb if source doesn't really want to say what it needs + var buffSize = memSetup.Preferred; + if (buffSize != TwainConst.TWON_DONTCARE32) return buffSize; + + buffSize = memSetup.MaxBufSize; + if (buffSize != TwainConst.TWON_DONTCARE32) return buffSize; + + buffSize = memSetup.MinBufSize; + if (buffSize != TwainConst.TWON_DONTCARE32) return buffSize; + + return 1024 * 16; + } + private STS TransferFileImage(ref TW_PENDINGXFERS pending) { // assuming user already configured the transfer in transferready event,