diff --git a/NAPS2.Core/ImportExport/Pdf/PdfSharpExporter.cs b/NAPS2.Core/ImportExport/Pdf/PdfSharpExporter.cs index 8c476ef00..cf9f77d5c 100644 --- a/NAPS2.Core/ImportExport/Pdf/PdfSharpExporter.cs +++ b/NAPS2.Core/ImportExport/Pdf/PdfSharpExporter.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; +using System.Threading; using NAPS2.Ocr; using NAPS2.Scan.Images; using NAPS2.Util; @@ -87,13 +88,12 @@ namespace NAPS2.ImportExport.Pdf } } - if (useOcr) + bool result = useOcr + ? BuildDocumentWithOcr(progressCallback, document, images, ocrLanguageCode) + : BuildDocumentWithoutOcr(progressCallback, document, images); + if (!result) { - BuildDocumentWithOcr(document, images, ocrLanguageCode); - } - else - { - BuildDocumentWithoutOcr(document, images); + return false; } PathHelper.EnsureParentDirExists(path); @@ -101,51 +101,69 @@ namespace NAPS2.ImportExport.Pdf return true; } - private void BuildDocumentWithoutOcr(PdfDocument document, IEnumerable images) + private bool BuildDocumentWithoutOcr(Func progressCallback, PdfDocument document, IEnumerable images) { + int progress = 0; foreach (var image in images) { using (Stream stream = image.GetImageStream()) using (var img = new Bitmap(stream)) { - float hAdjust = 72 / img.HorizontalResolution; - float vAdjust = 72 / img.VerticalResolution; - double realWidth = img.Width * hAdjust; - double realHeight = img.Height * vAdjust; + if (!progressCallback(progress)) + { + return false; + } + + Size realSize = GetRealSize(img); PdfPage page = document.AddPage(); - page.Width = (int)realWidth; - page.Height = (int)realHeight; + page.Width = realSize.Width; + page.Height = realSize.Height; using (XGraphics gfx = XGraphics.FromPdfPage(page)) { - gfx.DrawImage(img, 0, 0, (int)realWidth, (int)realHeight); + gfx.DrawImage(img, 0, 0, realSize.Width, realSize.Height); } } + progress++; } + return true; } - private void BuildDocumentWithOcr(PdfDocument document, IEnumerable images, string ocrLanguageCode) + private bool BuildDocumentWithOcr(Func progressCallback, PdfDocument document, IEnumerable images, string ocrLanguageCode) { + int progress = 0; Pipeline.For(images).Step(image => { + if (!progressCallback(progress)) + { + return null; + } + using (Stream stream = image.GetImageStream()) using (var img = new Bitmap(stream)) { - float hAdjust = 72 / img.HorizontalResolution; - float vAdjust = 72 / img.VerticalResolution; - double realWidth = img.Width * hAdjust; - double realHeight = img.Height * vAdjust; + if (!progressCallback(progress)) + { + return null; + } + + Size realSize = GetRealSize(img); PdfPage page; lock (document) { page = document.AddPage(); - page.Width = (int)realWidth; - page.Height = (int)realHeight; + page.Width = realSize.Width; + page.Height = realSize.Height; using (XGraphics gfx = XGraphics.FromPdfPage(page)) { - gfx.DrawImage(img, 0, 0, (int)realWidth, (int)realHeight); + gfx.DrawImage(img, 0, 0, realSize.Width, realSize.Height); } } + if (!progressCallback(progress)) + { + return null; + } + string tempImageFilePath = Path.Combine(Paths.Temp, Path.GetRandomFileName()); img.Save(tempImageFilePath); @@ -156,6 +174,11 @@ namespace NAPS2.ImportExport.Pdf OcrResult ocrResult; try { + if (!progressCallback(progress)) + { + return null; + } + ocrResult = ocrEngine.ProcessImage(tempImageFilePath, ocrLanguageCode); } finally @@ -170,6 +193,10 @@ namespace NAPS2.ImportExport.Pdf { return; } + if (!progressCallback(progress)) + { + return; + } lock (document) { using (XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend)) @@ -185,7 +212,18 @@ namespace NAPS2.ImportExport.Pdf } } } + Interlocked.Increment(ref progress); }); + return progressCallback(progress); + } + + private static Size GetRealSize(Bitmap img) + { + float hAdjust = 72 / img.HorizontalResolution; + float vAdjust = 72 / img.VerticalResolution; + double realWidth = img.Width * hAdjust; + double realHeight = img.Height * vAdjust; + return new Size((int)realWidth, (int)realHeight); } private static RectangleF AdjustBounds(Rectangle b, float hAdjust, float vAdjust) diff --git a/NAPS2.Core/Util/Pipeline.cs b/NAPS2.Core/Util/Pipeline.cs index 861eda41d..cb039c6a5 100644 --- a/NAPS2.Core/Util/Pipeline.cs +++ b/NAPS2.Core/Util/Pipeline.cs @@ -22,7 +22,7 @@ namespace NAPS2.Util return new PipelineSource(input); } - public abstract class PipelineBase : IPipelineSyntax + private abstract class PipelineBase : IPipelineSyntax { public IPipelineSyntax Step(Func pipelineStepFunc) { @@ -55,7 +55,7 @@ namespace NAPS2.Util public abstract IEnumerable GetOutput(List taskList); } - public class PipelineSource : PipelineBase + private class PipelineSource : PipelineBase { private readonly IEnumerable value; @@ -70,7 +70,7 @@ namespace NAPS2.Util } } - public class PipelineStep : PipelineBase + private class PipelineStep : PipelineBase { private readonly PipelineBase previous; private readonly Func func; @@ -91,7 +91,11 @@ namespace NAPS2.Util { foreach (var item in input) { - collection.Add(func(item)); + var result = func(item); + if (!ReferenceEquals(result, null)) + { + collection.Add(result); + } } } finally @@ -103,7 +107,7 @@ namespace NAPS2.Util } } - public class PipelineParallelStep : PipelineBase + private class PipelineParallelStep : PipelineBase { private readonly PipelineBase previous; private readonly Func func; @@ -122,7 +126,14 @@ namespace NAPS2.Util { try { - Parallel.ForEach(input, item => collection.Add(func(item))); + Parallel.ForEach(input, item => + { + var result = func(item); + if (!ReferenceEquals(result, null)) + { + collection.Add(result); + } + }); } finally {