diff --git a/Classical-Components-Demo/Droid/Classical-Components-Demo.Droid.csproj b/Classical-Components-Demo/Droid/Classical-Components-Demo.Droid.csproj index a57838d..10cf1f9 100644 --- a/Classical-Components-Demo/Droid/Classical-Components-Demo.Droid.csproj +++ b/Classical-Components-Demo/Droid/Classical-Components-Demo.Droid.csproj @@ -158,7 +158,7 @@ - 4.2.0 + 4.2.1-alpha.2 diff --git a/Classical-Components-Demo/Droid/MainActivity.cs b/Classical-Components-Demo/Droid/MainActivity.cs index 70080f7..e54217f 100644 --- a/Classical-Components-Demo/Droid/MainActivity.cs +++ b/Classical-Components-Demo/Droid/MainActivity.cs @@ -66,8 +66,9 @@ protected override void OnCreate(Bundle savedInstanceState) AssignApplyImageFilterButtonHandler(); AssignImportImageButtonHandler(); AssignCreatePdfButtonHandler(); - AssignCreateTiffButtonHandler(); AssignOcrButtonsHandler(); + AssignCreateSandwichPdfButtonHandler(); + AssignCreateTiffButtonHandler(); AssignCheckRecognizerUiButtonHandler(); PermissionUtils.Request(this, FindViewById(Resource.Layout.Main)); @@ -185,14 +186,26 @@ void AssignCreatePdfButtonHandler() DebugLog("Starting PDF creation..."); - Task.Run(() => + Task.Run(async () => { try { - var pdfOutputUri = GenerateRandomFileUrlInDemoTempStorage(".pdf"); - var images = new AndroidNetUri[] { documentImageUri }; // add more images for PDF pages here - // The SDK call is sync! - SBSDK.CreatePDF(images, pdfOutputUri, PDFPageSize.A4); + var inputUris = new AndroidNetUri[] { documentImageUri }; // add more images for PDF pages here + var pdfOutputUri = await SBSDK.CreatePDF(inputUris, + new PDFConfiguration + { + PageOrientation = PDFPageOrientation.Auto, + PageSize = PDFPageSize.A4, + PdfAttributes = new PDFAttributes + { + Author = "Scanbot User", + Creator = "ScanbotSDK", + Title = "ScanbotSDK PDF", + Subject = "Generating a sandwiched PDF", + Keywords = new[] { "x-platform", "ios", "android" }, + } + }); + DebugLog("PDF file created: " + pdfOutputUri); ShowAlertDialog("PDF file created: " + pdfOutputUri, onDismiss: () => { @@ -255,17 +268,22 @@ void AssignOcrButtonsHandler() Task.Run(() => { try { - var pdfOutputUri = GenerateRandomFileUrlInDemoTempStorage(".pdf"); - var images = new AndroidNetUri[] { documentImageUri }; // add more images for OCR here + var inputUris = new AndroidNetUri[] { documentImageUri }; // add more images for OCR here // The SDK call is sync! - var result = SBSDK.PerformOCR(images, SBSDK.GetOcrConfigs(), pdfOutputUri); - DebugLog("Recognized OCR text: " + result.RecognizedText); - DebugLog("Sandwiched PDF file created: " + pdfOutputUri); - ShowAlertDialog(result.RecognizedText, "OCR Result", () => - { - OpenSharingDialog(pdfOutputUri, "application/pdf"); - }); + // NOTE: + // The default OCR engine is 'OcrConfig.ScanbotOCR' which is ML based. This mode doesn't expect the Langauges array. + // If you wish to use the previous engine please use 'OcrConfig.Tesseract(...)'. The Languages array is mandatory in this mode. + // Uncomment the below code to use the past legacy 'OcrConfig.Tesseract(...)' engine mode. + // var ocrConfig = OcrConfig.Tesseract(withLanguageString: new List{ "en", "de" }); + + // Using the default OCR option + var ocrConfig = OcrConfig.ScanbotOCR; + + var ocrResult = SBSDK.PerformOCR(inputUris, ocrConfig); + + DebugLog("Recognized OCR text: " + ocrResult.RecognizedText); + ShowAlertDialog(ocrResult.RecognizedText, "OCR Result", () => { }); } catch (Exception e) { @@ -282,6 +300,61 @@ void AssignOcrButtonsHandler() }; } + private void AssignCreateSandwichPdfButtonHandler() + { + var createSandwichPdfButton = FindViewById + + + + + + + + + + + @@ -228,7 +252,7 @@ - + @@ -252,7 +276,7 @@ - + @@ -281,7 +305,7 @@ - + @@ -302,7 +326,7 @@ - + diff --git a/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.cs b/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.cs index 4e050dc..932792e 100644 --- a/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.cs +++ b/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.cs @@ -11,6 +11,7 @@ using ScanbotSDK.iOS; using System.Linq; using ClassicalComponentsDemo.iOS.ViewControllers; +using System.Collections.Generic; namespace ClassicalComponentsDemo.iOS { @@ -145,23 +146,22 @@ partial void PerformOCRUpInside(UIButton sender) Task.Run(async () => { - DebugLog("Performing OCR ..."); - var images = AppDelegate.TempImageStorage.ImageURLs; + var inputUrls = AppDelegate.TempImageStorage.ImageURLs; + + // NOTE: + // The default OCR engine is 'OcrConfig.ScanbotOCR' which is ML based. This mode doesn't expect the Langauges array. + // If you wish to use the previous engine please use 'OcrConfig.Tesseract(...)'. The Languages array is mandatory in this mode. + // Uncomment the below code to use the past legacy 'OcrConfig.Tesseract(...)' engine mode. + // var ocrConfig = OcrConfig.Tesseract(withLanguageString: new List{ "en", "de" }); - // Uncomment below code to use the old OCR approach. Use [OCRMode.Legacy] and set the required [InstalledLanguages] property. - //var languages = new List { "en", "de" }; - //var ocrConfig = new OcrConfigs - //{ - // InstalledLanguages = languages, - // OcrMode = OCRMode.Legacy, - // LanguageDataPath = SBSDK.GetOcrConfigs().LanguageDataPath - //}; + // Using the default OCR option + var ocrConfig = OcrConfig.ScanbotOCR; - var result = await SBSDK.PerformOCR(images, SBSDK.GetOcrConfigs()); - DebugLog("OCR result: " + result.RecognizedText); - ShowMessage("OCR Text", result.RecognizedText); + var ocrResult = await SBSDK.PerformOCR(inputUrls, ocrConfig); + DebugLog("OCR result: " + ocrResult.RecognizedText); + ShowMessage("OCR Text", ocrResult.RecognizedText); }); } @@ -379,14 +379,72 @@ partial void CreatePdfTouchUpInside(UIButton sender) Task.Run(async () => { DebugLog("Creating PDF file ..."); - var images = AppDelegate.TempImageStorage.ImageURLs; - var pdfOutputFileUrl = GenerateRandomFileUrlInDemoTempStorage(".pdf"); - await SBSDK.CreatePDF(images, pdfOutputFileUrl, PDFPageSize.A4); + var inputUrls = AppDelegate.TempImageStorage.ImageURLs; + var pdfOutputFileUrl = await SBSDK.CreatePDF(inputUrls, + new PDFConfiguration + { + PageOrientation = PDFPageOrientation.Auto, + PageSize = PDFPageSize.A4, + PdfAttributes = new PDFAttributes + { + Author = "Scanbot User", + Creator = "ScanbotSDK", + Title = "ScanbotSDK PDF", + Subject = "Generating a sandwiched PDF", + Keywords = new[] { "x-platform", "ios", "android" }, + } + }); DebugLog("PDF file created: " + pdfOutputFileUrl); ShowMessage("PDF file created", "" + pdfOutputFileUrl); }); } + partial void CreateSandwichPdfTouchUpInside(UIButton sender) + { + Task.Run(async () => + { + DebugLog("Creating Sandwich PDF ..."); + + var inputUrls = AppDelegate.TempImageStorage.ImageURLs; + // NOTE: + // The default OCR engine is 'OcrConfig.ScanbotOCR' which is ML based. This mode doesn't expect the Langauges array. + // If you wish to use the previous engine please use 'OcrConfig.Tesseract(...)'. The Languages array is mandatory in this mode. + // Uncomment the below code to use the past legacy 'OcrConfig.Tesseract(...)' engine mode. + //var ocrConfig = OcrConfig.Tesseract(withLanguageString: new List{ "en", "de" }); + + // You may also use the default InstalledLanguages property in the OCR configuration. + // SBSDK.GetOcrConfigs() returns all the default OCR configurations from the SDK. + //var languages = SBSDK.GetOcrConfigs().InstalledLanguages; + + // Using the default OCR option + var ocrConfig = OcrConfig.ScanbotOCR; + + try + { + var pdfOutputFileUrl = await SBSDK.CreateSandwichPDF(inputUrls, + new PDFConfiguration + { + PageOrientation = PDFPageOrientation.Auto, + PageSize = PDFPageSize.A4, + PdfAttributes = new PDFAttributes + { + Author = "Scanbot User", + Creator = "ScanbotSDK", + Title = "ScanbotSDK PDF", + Subject = "Generating a sandwiched PDF", + Keywords = new[] { "x-platform", "ios", "android" }, + } + }, ocrConfig); + DebugLog("PDF file created: " + pdfOutputFileUrl); + ShowMessage("PDF file created", "" + pdfOutputFileUrl); + } + catch (Exception ex) + { + ShowErrorMessage(ex.Message); + } + }); + } + public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender) { base.PrepareForSegue(segue, sender); diff --git a/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.designer.cs b/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.designer.cs index e2c2ec0..d464ad3 100644 --- a/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.designer.cs +++ b/Classical-Components-Demo/iOS/ViewControllers/MainSelectionTableViewController.designer.cs @@ -74,6 +74,9 @@ partial class MainSelectionTableViewController [Action ("CreatePdfTouchUpInside:")] partial void CreatePdfTouchUpInside (UIKit.UIButton sender); + [Action ("CreateSandwichPdfTouchUpInside:")] + partial void CreateSandwichPdfTouchUpInside (UIKit.UIButton sender); + [Action ("CreateTiffFileTouchUpInside:")] partial void CreateTiffFileTouchUpInside (UIKit.UIButton sender); @@ -99,6 +102,11 @@ void ReleaseDesignerOutlets () applyImageFilterButton = null; } + if (checkRecognizerButton != null) { + checkRecognizerButton.Dispose (); + checkRecognizerButton = null; + } + if (copyrightLabel != null) { copyrightLabel.Dispose (); copyrightLabel = null; @@ -124,11 +132,6 @@ void ReleaseDesignerOutlets () genericDocumentRecognizerButton = null; } - if (checkRecognizerButton != null) { - checkRecognizerButton.Dispose (); - checkRecognizerButton = null; - } - if (goToPdfViewButton != null) { goToPdfViewButton.Dispose (); goToPdfViewButton = null; diff --git a/Libraries.txt b/Libraries.txt index a5b72c9..c850b6a 100644 --- a/Libraries.txt +++ b/Libraries.txt @@ -1,4 +1,4 @@ -Open Source libraries used in the Scanbot SDK for Xamarin and Xamarin.Forms version 4.2.0: +Open Source libraries used in the Scanbot SDK for Xamarin and Xamarin.Forms version 4.2.1: Xamarin.AndroidX: diff --git a/Ready-To-Use-UI-Demo/Droid/Activities/PagePreviewActivity.cs b/Ready-To-Use-UI-Demo/Droid/Activities/PagePreviewActivity.cs index 9dbb5be..ca41ebf 100644 --- a/Ready-To-Use-UI-Demo/Droid/Activities/PagePreviewActivity.cs +++ b/Ready-To-Use-UI-Demo/Droid/Activities/PagePreviewActivity.cs @@ -27,6 +27,7 @@ using ReadyToUseUIDemo.model; using ScanbotSDK.Xamarin; using ScanbotSDK.Xamarin.Android; +using Uri = Android.Net.Uri; namespace ReadyToUseUIDemo.Droid.Activities { @@ -58,7 +59,7 @@ protected override void OnCreate(Bundle savedInstanceState) var toolbar = FindViewById(Resource.Id.toolbar); SetSupportActionBar(toolbar); - + SupportActionBar.Title = Texts.scan_results; SupportActionBar.SetDisplayHomeAsUpEnabled(true); SupportActionBar.SetDisplayShowHomeEnabled(true); @@ -86,12 +87,12 @@ protected override void OnCreate(Bundle savedInstanceState) recycleView = FindViewById(Resource.Id.pages_preview); recycleView.HasFixedSize = true; recycleView.SetAdapter(adapter); - + var layout = new GridLayoutManager(this, 3); recycleView.SetLayoutManager(layout); adapter.SetItems(PageRepository.Pages); - + progress = FindViewById(Resource.Id.progressBar); var addPage = FindViewById(Resource.Id.action_add_page); @@ -170,97 +171,165 @@ private void UpdateVisibility() save.Enabled = !adapter.IsEmpty; } - enum SaveType + internal void SaveDocument(SaveType type) { - Plain, - OCR, - TIFF + if (!SBSDK.IsLicenseValid()) + { + Alert.ShowLicenseDialog(this); + return; + } + + Task.Run(async delegate + { + var input = adapter.GetDocumentUris().ToArray(); + Uri outputUri = null; + switch (type) + { + case SaveType.PDF: + outputUri = await GeneratePdfAsync(input); + break; + case SaveType.OCR: + PerformOcrAsync(input); + return; + case SaveType.SANDWICH_PDF: + outputUri = await GenerateSandwichPdfAsync(input); + break; + case SaveType.TIFF: + outputUri = GenerateTiffAsync(input); + break; + } + + ShowResult(outputUri); + }); } - public void SaveWithOcr() + private async Task GeneratePdfAsync(Uri[] inputUris) { - SaveDocument(SaveType.OCR); + var outputUri = await SBSDK.CreatePDF(inputUris, + new PDFConfiguration + { + PageOrientation = PDFPageOrientation.Auto, + PageSize = PDFPageSize.A4, + PdfAttributes = new PDFAttributes + { + Author = "Scanbot User", + Creator = "ScanbotSDK", + Title = "ScanbotSDK PDF", + Subject = "Generating a sandwiched PDF", + Keywords = new[] { "x-platform", "ios", "android" }, + } + }); + return outputUri; } - public void SaveWithoutOcr() + private void PerformOcrAsync(Uri[] inputUris) { - SaveDocument(SaveType.Plain); + // NOTE: + // The default OCR engine is 'OcrConfig.ScanbotOCR' which is ML based. This mode doesn't expect the Langauges array. + // If you wish to use the previous engine please use 'OcrConfig.Tesseract(...)'. The Languages array is mandatory in this mode. + // Uncomment the below code to use the past legacy 'OcrConfig.Tesseract(...)' engine mode. + // var ocrConfig = OcrConfig.Tesseract(withLanguageString: new List{ "en", "de" }); + + // Using the default OCR option + var ocrConfig = OcrConfig.ScanbotOCR; + + var ocrResult = SBSDK.PerformOCR(inputUris, ocrConfig); + RunOnUiThread(delegate + { + Alert.ShowAlert(this, "Result", ocrResult?.RecognizedText); + }); } - public void SaveTiff() + private async Task GenerateSandwichPdfAsync(Uri[] inputUris) { - SaveDocument(SaveType.TIFF); + // NOTE: + // The default OCR engine is 'OcrConfig.ScanbotOCR' which is ML based. This mode doesn't expect the Langauges array. + // If you wish to use the previous engine please use 'OcrConfig.Tesseract(...)'. The Languages array is mandatory in this mode. + // Uncomment the below code to use the past legacy 'OcrConfig.Tesseract(...)' engine mode. + //var ocrConfig = OcrConfig.Tesseract(withLanguageString: new List{ "en", "de" }); + + // You may also use the default InstalledLanguages property in the OCR configuration. + // SBSDK.GetOcrConfigs() returns all the default OCR configurations from the SDK. + //var languages = SBSDK.GetOcrConfigs().InstalledLanguages; + + // Using the default OCR option + var ocrConfig = OcrConfig.ScanbotOCR; + + try + { + var outputUri = await SBSDK.CreateSandwichPDF(inputUris, + new PDFConfiguration + { + PageOrientation = PDFPageOrientation.Auto, + PageSize = PDFPageSize.A4, + PdfAttributes = new PDFAttributes + { + Author = "Scanbot User", + Creator = "ScanbotSDK", + Title = "ScanbotSDK PDF", + Subject = "Generating a sandwiched PDF", + Keywords = new[] { "x-platform", "ios", "android" }, + } + }, ocrConfig); + return outputUri; + } + catch (Exception ex) + { + Alert.ShowAlert(this, "Error", ex.Message); + return null; + } } - void SaveDocument(SaveType type) + private Uri GenerateTiffAsync(Uri[] input) { - if (!SBSDK.IsLicenseValid()) + var outputUri = GetOutputUri(".tiff"); + // Please note that some compression types are only compatible for 1-bit encoded images (binarized black & white images)! + var options = new TiffOptions { OneBitEncoded = true, Compression = TiffCompressionOptions.CompressionCcittfax4, Dpi = 250 }; + bool success = SBSDK.WriteTiff(input, outputUri, options); + if (success) { - Alert.ShowLicenseDialog(this); - return; + return outputUri; } + return null; + } - Task.Run(delegate + private void ShowResult(Uri outputUri) + { + if (outputUri == null) { - var input = adapter.GetDocumentUris().ToArray(); - var output = GetOutputUri(".pdf"); + Alert.ShowUnexpectedError(this); + return; + } - if (type == SaveType.TIFF) - { - output = GetOutputUri(".tiff"); - // Please note that some compression types are only compatible for 1-bit encoded images (binarized black & white images)! - var options = new TiffOptions { OneBitEncoded = true, Compression = TiffCompressionOptions.CompressionCcittfax4, Dpi = 250 }; - bool success = SBSDK.WriteTiff(input, output, options); - } - else if (type == SaveType.OCR) - { - var languages = SBSDK.GetOcrConfigs().InstalledLanguages.ToArray(); + Java.IO.File file = Copier.Copy(this, outputUri); - if (languages.Length == 0) - { - RunOnUiThread(delegate - { - Alert.Toast(this, "OCR languages blobs are not available"); - }); - return; - } - SBSDK.PerformOCR(input, SBSDK.GetOcrConfigs(), output); - } - else - { - SBSDK.CreatePDF(input, output, PDFPageSize.A4); - } + var intent = new Intent(Intent.ActionView, outputUri); - Java.IO.File file = Copier.Copy(this, output); + var authority = ApplicationContext.PackageName + ".provider"; + var uri = FileProvider.GetUriForFile(this, authority, file); - var intent = new Intent(Intent.ActionView, output); - - var authority = ApplicationContext.PackageName + ".provider"; - var uri = FileProvider.GetUriForFile(this, authority, file); - - intent.SetDataAndType(uri, MimeUtils.GetMimeByName(file.Name)); - intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask); - intent.AddFlags(ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission); + intent.SetDataAndType(uri, MimeUtils.GetMimeByName(file.Name)); + intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask); + intent.AddFlags(ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission); - RunOnUiThread(delegate - { - StartActivity(Intent.CreateChooser(intent, output.LastPathSegment)); - Alert.Toast(this, "File saved to: " + output.Path); - }); + RunOnUiThread(delegate + { + StartActivity(Intent.CreateChooser(intent, outputUri.LastPathSegment)); + Alert.Toast(this, "File saved to: " + outputUri.Path); }); } - Android.Net.Uri GetOutputUri(string extension) + Uri GetOutputUri(string extension) { var external = GetExternalFilesDir(null).AbsolutePath; var filename = Guid.NewGuid() + extension; var targetFile = System.IO.Path.Combine(external, filename); - return Android.Net.Uri.FromFile(new Java.IO.File(targetFile)); + return Uri.FromFile(new Java.IO.File(targetFile)); } public override bool OnOptionsItemSelected(IMenuItem item) { - + if (item.ItemId == Android.Resource.Id.Home) { base.OnBackPressed(); @@ -275,7 +344,8 @@ public void ApplyFilter(ImageFilterType type) Task.Run(delegate { PageRepository.Apply(type); - RunOnUiThread(delegate { + RunOnUiThread(delegate + { adapter.NotifyDataSetChanged(); progress.Visibility = ViewStates.Gone; }); @@ -385,9 +455,9 @@ public void SetItems(List pages) NotifyDataSetChanged(); } - public List GetDocumentUris() + public List GetDocumentUris() { - var uris = new List(); + var uris = new List(); foreach (Page page in Items) { var documentUri = GetUri(page, PageFileStorage.PageFileType.Document); @@ -438,13 +508,13 @@ public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int positi } } - Android.Net.Uri GetPreviewUri(Page page, PageFileStorage.PageFileType type) + Uri GetPreviewUri(Page page, PageFileStorage.PageFileType type) { // preview URI (low-res!) return SBSDK.PageStorage.GetPreviewImageURI(page.PageId, type); } - Android.Net.Uri GetUri(Page page, PageFileStorage.PageFileType type) + Uri GetUri(Page page, PageFileStorage.PageFileType type) { // hi-res(!) URI return SBSDK.PageStorage.GetImageURI(page.PageId, type); diff --git a/Ready-To-Use-UI-Demo/Droid/Fragments/SaveBottomSheetMenuFragment.cs b/Ready-To-Use-UI-Demo/Droid/Fragments/SaveBottomSheetMenuFragment.cs index 8a27f22..9b8ea32 100644 --- a/Ready-To-Use-UI-Demo/Droid/Fragments/SaveBottomSheetMenuFragment.cs +++ b/Ready-To-Use-UI-Demo/Droid/Fragments/SaveBottomSheetMenuFragment.cs @@ -1,5 +1,4 @@ - -using Android.OS; +using Android.OS; using Android.Views; using Android.Widget; using Google.Android.Material.BottomSheet; @@ -8,37 +7,43 @@ namespace ReadyToUseUIDemo.Droid.Fragments { + internal enum SaveType + { + PDF, + SANDWICH_PDF, + OCR, + TIFF + } + public class SaveBottomSheetMenuFragment : BottomSheetDialogFragment { public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { var view = inflater.Inflate(Resource.Layout.save_bottom_sheet, container, false); - var saveWith = view.FindViewById