Forum Cross Platform with Xamarin

Scan Document

In Xamarin Forms, how can one scan Document?

Answers

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    1) Use the camera
    2) Use a scanner connected by USB

  • GeetSGeetS USMember ✭✭✭

    A 'scanner' and a 'camera' both do the same thing: They capture an image. They just have other hardware to accomplish the task. A scanner is little more than a camera with a moving sensor... Or a stationary sensor and feed to pull the page past the sensor.

    So to make Scanner app initially I had used the camera to take a photo of the page. Then processed the capture to fit the needs of app ie allowed the user to crop the image and then Convert image into PDF. Only issue is that converting image to PDF. I had tried to use 'Xam.iTextSharpLGPL'(as stated in https://pathofacoder.com/tag/itextsharp-for-xamarin/) but it didn't worked. Then, I had tried iTextSharp, but getting this, Error Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'System.Drawing'. Does anyone have an idea how you overcame this issue? Thanks

    In order to make it working follow below steps:
    1. Right click on solution. Choose Properties & under Configuration, Tick Deploy option.
    2. In 'Droid' project, right click and choose properties:[Set it according to your Emulator settings]
    (i) In 'Application' Tab, under 'Compile using Android Version(Target Version), Choose : Use Latest Platform(Android 7.1(Nouget)).
    (ii) In 'Android Manifest', under Minimum Android version, Choose 'Android 5.0(API Level 21-Lollipop)'.
    (iii) In 'Android Options', (a) Click on 'Advanced' Button. A dialog box will open. In Supported Architecture' dropdown tick all except x84_64.
    (b) Untick 'Use Shared Runtime'.

  • GeetSGeetS USMember ✭✭✭
    edited August 2017

    In order to overcome the error which I had mentioned above, in Droid folder, added the System.Drawing.dll as references.

    Right click on References --> Edit References --> .Net Assembly --> Browse... --> C:\Windows\Microsoft.NET\Framework\v4.0.30319 --> select System.Drawing.dll.

    Now, next problem that I had got is : Java.Lang.IllegalException : Can't compress a recycled bitmap. To resolve the same, in CropImage.cs(under .Droid folder), comment out line 314 ie croppedImage.Recycle(); under Saveoutput() method.
    Now, the only issue is conversion of image to pdf using iTextSharp.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Java.Lang.IllegalException : Can't compress a recycled bitmap.

    Or in other terms... Can't access a disposed object.
    If the bitmap has already been recycled its gone. You're going to have to keep the bitmap in scope and not throw it away until you're done with it.

  • GeetSGeetS USMember ✭✭✭
    edited August 2017

    In order to make it working, in CropImage.cs(under .Droid folder), I had commented line 314 ie croppedImage.Recycle(); under Saveoutput() method.

    Next step is to Convert image to PDF. So, in order to implement that I had used iTextSharp(Reference: http://www.c-sharpcorner.com/blogs/add-image-in-pdf-using-itextsharp1).

    I had created the doc, but the issue is though it creates PDF doc but it didn't displays image inside it(which is added at runtime). Can anyone suggest what can be the reason?

    Below is the code I had written to create PDF using iTextSharp:
    1. In Portable, created a TestPage.xaml
    public TestPage()
    {
    InitializeComponent();
    Xamarin.Forms.Image img = new Xamarin.Forms.Image()
    {
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.FillAndExpand,
    BackgroundColor = Color.Gray,
    };
    Button photo = new Button()
    {
    Text = "Photo",
    TextColor = Color.White,
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.Center,
    BackgroundColor = Color.Accent
    };

            photo.Clicked += async (object sender, EventArgs e) =>
            {
                IList<String> buttons = new List<String>();
                buttons.Add(ChooseImageFrom.Gallery.ToString());
                buttons.Add(ChooseImageFrom.Camera.ToString());
    
                var action = await DisplayActionSheet("Choose photo from", "Cancel", null, buttons.ToArray());
    
                if (action == ChooseImageFrom.Camera.ToString())
                {
                    await CrossMedia.Current.Initialize();
                    if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
                    {
                        return;
                    }
    
                    MediaFile file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
                    {
                        SaveToAlbum = true,
                        DefaultCamera = CameraDevice.Rear,
                        Directory = "Geeta",
                        Name = "Media.jpg"
                    });
    
                    if (file == null)
                    {
                        return;
                    }
    
                    byte[] cropedBytes = await CrossXMethod.Current.CropImageFromOriginalToBytes(file.Path);
    
                    if (cropedBytes != null)
                    {
                        CreatePdfDoc(cropedBytes);  
                        //AvatarImageSource = ImageSource.FromStream(() =>
                        //{
                        //    var cropedImage = new MemoryStream(cropedBytes);
                        //    file.Dispose();
                        //    return cropedImage;
                        //});
                        //img.Source = AvatarImageSource;
                    }
                    else
                    {
                        file.Dispose();
                    }
    
                }
    
                else
                {
                    await CrossMedia.Current.Initialize();
                    if (!CrossMedia.Current.IsPickPhotoSupported)
                    {
                        return;
                    }
                    MediaFile file = await CrossMedia.Current.PickPhotoAsync();
    
                    if (file == null)
                    {
                        return;
                    }
    
                    byte[] cropedBytes = await CrossXMethod.Current.CropImageFromOriginalToBytes(file.Path);
    
                    if (cropedBytes != null)
                    {
                        CreatePdfDoc(cropedBytes);  
                        //AvatarImageSource = ImageSource.FromStream(() =>
                        //{
                        //    var cropedImage = new MemoryStream(cropedBytes);
                        //    file.Dispose();
                        //    return cropedImage;
                        //});
                        //img.Source = AvatarImageSource;
                    }
    
                    else
                    {
                        file.Dispose();
                    }
    
                }
    
    
            };
    
            StackLayout stack = new StackLayout()
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Children = { img, photo },
                BackgroundColor = Color.Aqua
            };
    
            ScrollView scroll = new ScrollView()
            {
                Content = stack
            };
    
            Content = scroll;
            Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
        }
    

    public void CreatePdfDoc(byte[] cropedBytes) //Convert Image to PDF
    {
    try
    {
    Document doc = new Document();
    PdfWriter writer = PdfAWriter.GetInstance(doc, Config.TestStream);
    doc.Open();
    try
    {
    Paragraph par = new Paragraph("Getting Started ITextSharp");
    String ImageURL = "https://xamarin.com/content/images/pages/forms/example-app.png"; //For Image
    iTextSharp.text.Image png = iTextSharp.text.Image.GetInstance(ImageURL);
    png.ScaleToFit(140f, 120f);
    png.SpacingBefore = 10f;
    png.SpacingAfter = 1f;
    png.Alignment = iTextSharp.text.Element.ALIGN_LEFT;
    doc.Add(par);
    doc.Add(png);
    }
    catch (Exception ex)
    {

                }
                finally { doc.Close(); }
            }
            catch (Exception ex)
            {
                throw ex;
            }
    
        }
    }
    
    1. In Portable, defined a class Config like below:
      public static class Config{
      public static string PathApp{get;set;}
      public static Stream TestStream{get;set;}
      }

    2. In MainActivity.cs(under Android project), specify Config.PathApp & Config.TestStream value like below
      protected override void OnCreate(Bundle bundle)
      {
      .........
      base.OnCreate(bundle);
      global::Xamarin.Forms.Forms.Init(this, bundle);
      Config.PathApp = ApplicationContext.GetExternalFilesDir(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
      Config.TestStream = new FileStream(Path.Combine( Config.PathApp,”Test.pdf”), FileMode.CreateNew)
      .....
      }

    3. In AppDelegate.cs(under IOS project), specify Config.PathApp & Config.TestStream value like below
      public override bool FinishedLaunching(UIApplication app, NSDictionary options)
      {
      global::Xamarin.Forms.Forms.Init();
      LoadApplication(new App());
      Config.PathApp = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
      return base.FinishedLaunching(app, options);
      Config.TestStream = new FileStream(Path.Combine( Config.PathApp,”Test.pdf”), FileMode.CreateNew)
      }
  • GeetSGeetS USMember ✭✭✭

    In Emulator, to view this file click on Settings>Storage>Other>Android>data>com.companyname.textapp>file>Download. Here, textapp is the name of the app you are working on.

    Now, the below code clicks image, crops it and then asks for filename to Save and then converts it into PDF. But the problem is that cropping is done only Rectangle. Can anyone, suggest how to modify it to crop it like CamScanner App ie rather then rectangle one can crop from any angle?

    1. TestPage.xaml
      public static string iFileName;
      public void CreatePdfDoc(byte[] cropedBytes) //Convert Image to PDF
      {
      try
      {
      var myinput=await InputBox(this.Navigation); //prompt from User FileName to Save
      var fileService= DependencyService.Get();
      bool rs= fileService.GetFileNameAsync(iFileName);
      Document doc = new Document();
      PdfWriter writer = PdfAWriter.GetInstance(doc, Config.TestStream);
      doc.Open();
      try
      {
      Paragraph par = new Paragraph("Getting Started ITextSharp");
      iTextSharp.text.Image png = iTextSharp.text.Image.GetInstance(new MemoryStream(cropedBytes));
      png.ScaleToFit(140f, 120f);
      png.SpacingBefore = 10f;
      png.SpacingAfter = 1f;
      png.Alignment = iTextSharp.text.Element.ALIGN_LEFT;
      doc.Add(par);
      doc.Add(png);
      }
      catch (Exception ex)
      { }
      finally { doc.Close(); }
      }
      catch (Exception ex)
      {
      throw ex;
      }
      }
      }

    public static Task InputBox(INavigation navigation) //Text Input Popup
    {
    // wait in this proc, until user did his input 
    var tcs = new TaskCompletionSource();
    // var lblTitle = new Label { Text = "Title", HorizontalOptions = LayoutOptions.Center, FontAttributes = FontAttributes.Bold};
    var lblMessage = new Label { Text = "Enter FileName:" };
    var txtInput = new Entry { Text = "" };
    var btnOk = new Button
    {
    Text = "Ok",
    WidthRequest =100,
    BackgroundColor = Color.FromRgb(0.8, 0.8, 0.8),
    };
    btnOk.Clicked += async (s, e) =>
    {
    // close page
    var result = txtInput.Text;
    inputFileName=txtInput.Text; //Added
    await navigation.PopModalAsync();
    // pass result
    tcs.SetResult(result);
    };

    var btnCancel = new Button
    {
        Text = "Cancel",
        WidthRequest = 100,
        BackgroundColor = Color.FromRgb(0.8, 0.8, 0.8)
    };
    btnCancel.Clicked += async  (s, e) =>
    {
        // close page
        await navigation.PopModalAsync();
        // pass empty result
        tcs.SetResult(null);
    };
    
    var slButtons = new StackLayout 
    {
        Orientation = StackOrientation.Horizontal ,
        Children = { btnOk, btnCancel},
    };
    
    var layout = new StackLayout
    {
        Padding =new Thickness (0,15,0,0),
        VerticalOptions= LayoutOptions .StartAndExpand   ,
        HorizontalOptions =LayoutOptions.CenterAndExpand  ,
        Orientation = StackOrientation.Vertical,
    Children = { lblMessage, txtInput, slButtons },
       // Children = { lblTitle, lblMessage, txtInput, slButtons },
    };
    

    AbsoluteLayout ConfirmLayout = new AbsoluteLayout
    {
    Children=
    {
    {new BoxView{Color=Color.Silver},new Rectangle(0.5,0.3,0.7,0.25),AbsolueLayoutFlags.All},
    {layout, new Rectangle(0.5,0.3,0.7,0.25),AbsolueLayoutFlags.All} 
    }
    };
    // create and show page
    var page = new ContentPage();
    // page.Content = layout;
    page.Content = ConfirmLayout;
    page.BackgroundColor=Color.DimGrey;
    navigation.PushModalAsync(page);
    // open keyboard
    txtInput.Focus();
    // code is waiting her, until result is passed with tcs.SetResult() in btn-Clicked
    // then proc returns the result
    return tcs.Task;
    }
    }}

    public enum ChooseImageFrom{
    Camera,
    Gallery
    }

    1. Created interface 'IPDFFileOperation' in Portable Folder, so as to get Filename entered by user.
      public interface IPDFFileOperation
      {
      bool GetFileNameAsync(string Filename);
      }
    2. In Droid folder, created PDFFileOperation.cs and implemented above created interface
      [Reference https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/files/]
      [assembly: Dependency (typeof (PDFFileOperation))]
      namespace CropSample.Droid {
      public class PDFFileOperation : IPDFFileOperation {

      public bool GetFileNameAsync(string Filename)  {
          var filepath = Path.Combine(Config.PathApp,(filename == null) ? “Test.pdf”: string.Format(“{0}.{1}”,filename,”pdf”));
          if(file.Exists(filepath))
            file.Delete(filepath);
       Config.TestStream = new FileStream(filepath, FileMode.CreateNew);
       return true
      }
      

      }
      }

    3. In IOS folder, created PDFFileOperation.cs and implemented interface created in Potable folder.
      [assembly: Dependency (typeof (PDFFileOperation))]
      namespace CropSample.iOS {
      public class PDFFileOperation : IPDFFileOperation {

      public bool GetFileNameAsync(string Filename)  {
         Config.PathApp = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
          var filepath = Path.Combine(Config.PathApp,(filename == null) ? “Test.pdf”: string.Format(“{0}.{1}”,filename,”pdf”));
         if(file.Exists(filepath))
            file.Delete(filepath);
       Config.TestStream = new FileStream(filepath, FileMode.CreateNew);
       return true
      }
      

      }
      }

Sign In or Register to comment.