public Stream Transfer(int pageNumber, WiaBackgroundEventLoop eventLoop, string format) { if (pageNumber == 1) { // The only downside of the common dialog is that it steals focus. // If this is the first page, then the user has just pressed the scan button, so that's not // an issue and we can use it and get the benefits of progress display and immediate cancellation. ImageFile imageFile = eventLoop.GetSync(wia => (ImageFile) new CommonDialogClass().ShowTransfer(wia.Item, format)); if (imageFile == null) { return(null); } return(new MemoryStream((byte[])imageFile.FileData.get_BinaryData())); } // For subsequent pages, we don't want to take focus in case the user has switched applications, // so we use the custom form. var form = formFactory.Create <FScanProgress>(); form.PageNumber = pageNumber; form.EventLoop = eventLoop; form.Format = format; form.ShowDialog(); if (form.Exception != null) { throw form.Exception; } if (form.DialogResult == DialogResult.Cancel) { return(null); } return(form.ImageStream); }
protected override IEnumerable <ScannedImage> ScanInternal() { using (var eventLoop = new WiaBackgroundEventLoop(ScanProfile, ScanDevice, threadFactory)) { bool supportsFeeder = eventLoop.GetSync(wia => WiaApi.DeviceSupportsFeeder(wia.Device)); if (ScanProfile.PaperSource != ScanSource.Glass && !supportsFeeder) { throw new NoFeederSupportException(); } bool supportsDuplex = eventLoop.GetSync(wia => WiaApi.DeviceSupportsDuplex(wia.Device)); if (ScanProfile.PaperSource == ScanSource.Duplex && !supportsDuplex) { throw new NoDuplexSupportException(); } int pageNumber = 1; int retryCount = 0; bool retry = false; bool cancel = false; do { ScannedImage image; try { if (pageNumber > 1 && ScanProfile.WiaDelayBetweenScans) { int delay = (int)(ScanProfile.WiaDelayBetweenScansSeconds.Clamp(0, 30) * 1000); Thread.Sleep(delay); } image = TransferImage(eventLoop, pageNumber, out cancel); pageNumber++; retryCount = 0; retry = false; } catch (ScanDriverException e) { if (ScanProfile.WiaRetryOnFailure && e.InnerException is COMException && (uint)((COMException)e.InnerException).ErrorCode == 0x80004005 && retryCount < MAX_RETRIES) { Thread.Sleep(1000); retryCount += 1; retry = true; continue; } throw; } catch (Exception e) { throw new ScanDriverUnknownException(e); } if (image != null) { yield return(image); } } while (retry || (!cancel && ScanProfile.PaperSource != ScanSource.Glass)); } }
public Stream Transfer(int pageNumber, WiaBackgroundEventLoop eventLoop, string format) { // The console shouldn't spawn new forms, so use the silent transfer method. ImageFile imageFile = eventLoop.GetSync(wia => (ImageFile)wia.Item.Transfer(format)); if (imageFile == null) { return(null); } return(new MemoryStream((byte[])imageFile.FileData.get_BinaryData())); }
protected override async Task ScanInternal(ScannedImageSource.Concrete source) { using (var eventLoop = new WiaBackgroundEventLoop(ScanProfile, ScanDevice)) { bool supportsFeeder = eventLoop.GetSync(wia => WiaApi.DeviceSupportsFeeder(wia.Device)); if (ScanProfile.PaperSource != ScanSource.Glass && !supportsFeeder) { throw new NoFeederSupportException(); } bool supportsDuplex = eventLoop.GetSync(wia => WiaApi.DeviceSupportsDuplex(wia.Device)); if (ScanProfile.PaperSource == ScanSource.Duplex && !supportsDuplex) { throw new NoDuplexSupportException(); } int pageNumber = 1; int retryCount = 0; bool retry = false; bool done = false; do { ScannedImage image; try { if (pageNumber > 1 && ScanProfile.WiaDelayBetweenScans) { int delay = (int)(ScanProfile.WiaDelayBetweenScansSeconds.Clamp(0, 30) * 1000); Thread.Sleep(delay); } (image, done) = await TransferImage(eventLoop, pageNumber); pageNumber++; retryCount = 0; retry = false; } catch (ScanDriverException e) { if (ScanProfile.WiaRetryOnFailure && e.InnerException is COMException comError && (uint)comError.ErrorCode == 0x80004005 && retryCount < MAX_RETRIES) { Thread.Sleep(1000); retryCount += 1; retry = true; continue; } throw; } if (image != null) { source.Put(image); } } while (!CancelToken.IsCancellationRequested && (retry || !done && ScanProfile.PaperSource != ScanSource.Glass)); } }
protected override IEnumerable <ScannedImage> ScanInternal() { using (var eventLoop = new WiaBackgroundEventLoop(ScanProfile, ScanDevice, threadFactory)) { bool supportsFeeder = eventLoop.GetSync(wia => WiaApi.DeviceSupportsFeeder(wia.Device)); if (ScanProfile.PaperSource != ScanSource.Glass && !supportsFeeder) { throw new NoFeederSupportException(); } bool supportsDuplex = eventLoop.GetSync(wia => WiaApi.DeviceSupportsDuplex(wia.Device)); if (ScanProfile.PaperSource == ScanSource.Duplex && !supportsDuplex) { throw new NoDuplexSupportException(); } int pageNumber = 1; int retryCount = 0; bool retry = false; bool cancel = false; do { ScannedImage image; try { image = TransferImage(eventLoop, pageNumber, out cancel); pageNumber++; Debug.WriteLine("Succeeded with retry count {0}", retryCount); retryCount = 0; retry = false; } catch (ScanDriverException e) { if (e.InnerException is COMException && (uint)((COMException)e.InnerException).ErrorCode == 0x80004005 && retryCount < 10) { Thread.Sleep(1000); retryCount += 1; Debug.WriteLine("Retrying {0}", retryCount); retry = true; continue; } throw; } catch (Exception e) { throw new ScanDriverUnknownException(e); } if (image != null) { yield return(image); } } while (retry || (!cancel && ScanProfile.PaperSource != ScanSource.Glass)); } }
private ScannedImage TransferImage(WiaBackgroundEventLoop eventLoop, int pageNumber, out bool cancel) { try { // TODO: Use the NoUI flag uniformly var transfer = ScanParams.NoUI ? new ConsoleWiaTransfer() : wiaTransfer; using (var stream = transfer.Transfer(pageNumber, eventLoop, WiaApi.Formats.BMP)) { if (stream == null) { cancel = true; return(null); } cancel = false; using (Image output = Image.FromStream(stream)) { using (var result = ScannedImageHelper.PostProcessStep1(output, ScanProfile)) { if (blankDetector.ExcludePage(result, ScanProfile)) { return(null); } ScanBitDepth bitDepth = ScanProfile.UseNativeUI ? ScanBitDepth.C24Bit : ScanProfile.BitDepth; var image = new ScannedImage(result, bitDepth, ScanProfile.MaxQuality, ScanProfile.Quality); image.SetThumbnail(thumbnailRenderer.RenderThumbnail(result)); ScannedImageHelper.PostProcessStep2(image, ScanProfile, pageNumber); return(image); } } } } catch (NoPagesException) { if (ScanProfile.PaperSource != ScanSource.Glass && pageNumber == 1) { // No pages were in the feeder, so show the user an error throw new NoPagesException(); } // At least one page was scanned but now the feeder is empty, so exit normally cancel = true; return(null); } catch (ScanDriverException) { throw; } catch (Exception e) { throw new ScanDriverUnknownException(e); } }
private Stream DoTransfer(int pageNumber, WiaBackgroundEventLoop eventLoop, string format) { var invoker = (FormBase)DialogParent; if (eventLoop.GetSync(wia => wia.Item) == null) { return(null); } if (ScanParams.NoUI) { return(eventLoop.GetSync(wia => WiaApi.Transfer(wia, format, false))); } if (pageNumber == 1) { // The only downside of the common dialog is that it steals focus. // If this is the first page, then the user has just pressed the scan button, so that's not // an issue and we can use it and get the benefits of progress display and immediate cancellation. return(ScanParams.Modal ? eventLoop.GetSync(wia => invoker.InvokeGet(() => WiaApi.Transfer(wia, format, true))) : eventLoop.GetSync(wia => WiaApi.Transfer(wia, format, true))); } // For subsequent pages, we don't want to take focus in case the user has switched applications, // so we use the custom form. var form = formFactory.Create <FScanProgress>(); var waitHandle = new AutoResetEvent(false); form.PageNumber = pageNumber; form.Transfer = () => eventLoop.GetSync(wia => WiaApi.Transfer(wia, format, false)); form.Closed += (sender, args) => waitHandle.Set(); if (ScanParams.Modal) { invoker.Invoke(() => form.ShowDialog(DialogParent)); } else { invoker.Invoke(() => form.Show(DialogParent)); } waitHandle.WaitOne(); if (form.Exception != null) { WiaApi.ThrowDeviceError(form.Exception); } if (form.DialogResult == DialogResult.Cancel) { return(null); } return(form.ImageStream); }
private IScannedImage TransferImage(WiaBackgroundEventLoop eventLoop, int pageNumber) { try { using (var stream = wiaTransfer.Transfer(pageNumber, eventLoop, WiaApi.Formats.BMP)) { if (stream == null) { // User cancelled return(null); } using (Image output = Image.FromStream(stream)) { double scaleFactor = 1; if (!ScanSettings.UseNativeUI) { scaleFactor = ScanSettings.AfterScanScale.ToIntScaleFactor(); } using (var result = ImageScaleHelper.ScaleImage(output, scaleFactor)) { ScanBitDepth bitDepth = ScanSettings.UseNativeUI ? ScanBitDepth.C24Bit : ScanSettings.BitDepth; return(scannedImageFactory.Create(result, bitDepth, ScanSettings.MaxQuality)); } } } } catch (COMException e) { if ((uint)e.ErrorCode == WiaApi.Errors.OUT_OF_PAPER) { if (ScanSettings.PaperSource != ScanSource.Glass && pageNumber == 1) { throw new NoPagesException(); } return(null); } else if ((uint)e.ErrorCode == WiaApi.Errors.OFFLINE) { throw new DeviceOfflineException(); } else { throw new ScanDriverUnknownException(e); } } }
protected override IEnumerable <IScannedImage> ScanInternal() { using (var eventLoop = new WiaBackgroundEventLoop(ScanSettings, ScanDevice)) { bool supportsFeeder = eventLoop.GetSync(wia => WiaApi.DeviceSupportsFeeder(wia.Device)); if (ScanSettings.PaperSource != ScanSource.Glass && !supportsFeeder) { throw new NoFeederSupportException(); } int pageNumber = 1; while (true) { bool feederReady = eventLoop.GetSync(wia => WiaApi.DeviceFeederReady(wia.Device)); if (ScanSettings.PaperSource != ScanSource.Glass && !feederReady) { if (pageNumber == 1) { throw new NoPagesException(); } break; } IScannedImage image; try { image = TransferImage(eventLoop, pageNumber++); } catch (ScanDriverException) { throw; } catch (Exception e) { throw new ScanDriverUnknownException(e); } if (image == null) { break; } yield return(image); if (ScanSettings.PaperSource == ScanSource.Glass) { break; } } } }
private async Task <(ScannedImage, bool)> TransferImage(WiaBackgroundEventLoop eventLoop, int pageNumber) { return(await Task.Factory.StartNew(() => { try { ChaosMonkey.MaybeError(0, new COMException("Fail", -2147467259)); using (var stream = DoTransfer(pageNumber, eventLoop, WiaApi.Formats.BMP)) { if (stream == null) { return (null, true); } using (Image output = Image.FromStream(stream)) { using (var result = scannedImageHelper.PostProcessStep1(output, ScanProfile)) { if (blankDetector.ExcludePage(result, ScanProfile)) { return (null, false); } ScanBitDepth bitDepth = ScanProfile.UseNativeUI ? ScanBitDepth.C24Bit : ScanProfile.BitDepth; var image = new ScannedImage(result, bitDepth, ScanProfile.MaxQuality, ScanProfile.Quality); scannedImageHelper.PostProcessStep2(image, result, ScanProfile, ScanParams, pageNumber); string tempPath = scannedImageHelper.SaveForBackgroundOcr(result, ScanParams); scannedImageHelper.RunBackgroundOcr(image, ScanParams, tempPath); return (image, false); } } } } catch (NoPagesException) { if (ScanProfile.PaperSource != ScanSource.Glass && pageNumber == 1) { // No pages were in the feeder, so show the user an error throw new NoPagesException(); } // At least one page was scanned but now the feeder is empty, so exit normally return (null, true); } }, TaskCreationOptions.LongRunning)); }
protected override IEnumerable <ScannedImage> ScanInternal() { using (var eventLoop = new WiaBackgroundEventLoop(ScanProfile, ScanDevice, threadFactory)) { bool supportsFeeder = eventLoop.GetSync(wia => WiaApi.DeviceSupportsFeeder(wia.Device)); if (ScanProfile.PaperSource != ScanSource.Glass && !supportsFeeder) { throw new NoFeederSupportException(); } bool supportsDuplex = eventLoop.GetSync(wia => WiaApi.DeviceSupportsDuplex(wia.Device)); if (ScanProfile.PaperSource == ScanSource.Duplex && !supportsDuplex) { throw new NoDuplexSupportException(); } int pageNumber = 1; bool cancel; do { ScannedImage image; try { image = TransferImage(eventLoop, pageNumber++, out cancel); } catch (ScanDriverException) { throw; } catch (Exception e) { throw new ScanDriverUnknownException(e); } if (image != null) { yield return(image); } } while (!cancel && ScanProfile.PaperSource != ScanSource.Glass); } }