/ src / modules / PowerOCR / PowerOCR / Helpers / OcrExtensions.cs
OcrExtensions.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System;
  6  using System.Collections.Generic;
  7  using System.Drawing;
  8  using System.Drawing.Imaging;
  9  using System.IO;
 10  using System.Text;
 11  using System.Text.RegularExpressions;
 12  using System.Threading.Tasks;
 13  using System.Windows;
 14  using System.Windows.Media;
 15  
 16  using PowerOCR.Models;
 17  using Windows.Globalization;
 18  using Windows.Graphics.Imaging;
 19  using Windows.Media.Ocr;
 20  
 21  namespace PowerOCR.Helpers
 22  {
 23      internal static class OcrExtensions
 24      {
 25          public static void GetTextFromOcrLine(this OcrLine ocrLine, bool isSpaceJoiningOCRLang, StringBuilder text)
 26          {
 27              // (when OCR language is zh or ja)
 28              // matches words in a space-joining language, which contains:
 29              // - one letter that is not in "other letters" (CJK characters are "other letters")
 30              // - one number digit
 31              // - any words longer than one character
 32              // Chinese and Japanese characters are single-character words
 33              // when a word is one punctuation/symbol, join it without spaces
 34              if (isSpaceJoiningOCRLang)
 35              {
 36                  text.AppendLine(ocrLine.Text);
 37              }
 38              else
 39              {
 40                  bool isFirstWord = true;
 41                  bool isPrevWordSpaceJoining = false;
 42  
 43                  Regex regexSpaceJoiningWord = new(@"(^[\p{L}-[\p{Lo}]]|\p{Nd}$)|.{2,}");
 44  
 45                  foreach (OcrWord ocrWord in ocrLine.Words)
 46                  {
 47                      string wordString = ocrWord.Text;
 48  
 49                      bool isThisWordSpaceJoining = regexSpaceJoiningWord.IsMatch(wordString);
 50  
 51                      if (isFirstWord || (!isThisWordSpaceJoining && !isPrevWordSpaceJoining))
 52                      {
 53                          _ = text.Append(wordString);
 54                      }
 55                      else
 56                      {
 57                          _ = text.Append(' ').Append(wordString);
 58                      }
 59  
 60                      isFirstWord = false;
 61                      isPrevWordSpaceJoining = isThisWordSpaceJoining;
 62                  }
 63              }
 64          }
 65  
 66          public static async Task<string> GetRegionsTextAsTableAsync(OCROverlay passedWindow, Rectangle regionScaled, Language? language)
 67          {
 68              if (language is null)
 69              {
 70                  return string.Empty;
 71              }
 72  
 73              Bitmap bmp = ImageMethods.GetRegionAsBitmap(passedWindow, regionScaled);
 74  
 75              bool scaleBMP = true;
 76  
 77              if (bmp.Width * 1.5 > OcrEngine.MaxImageDimension)
 78              {
 79                  scaleBMP = false;
 80              }
 81  
 82              using Bitmap scaledBitmap = scaleBMP ? ImageMethods.ScaleBitmapUniform(bmp, 1.5) : ImageMethods.ScaleBitmapUniform(bmp, 1.0);
 83              DpiScale dpiScale = VisualTreeHelper.GetDpi(passedWindow);
 84  
 85              OcrResult ocrResult = await GetOcrResultFromImageAsync(scaledBitmap, language);
 86              List<WordBorder> wordBorders = ResultTable.ParseOcrResultIntoWordBorders(ocrResult, dpiScale);
 87              return ResultTable.GetWordsAsTable(wordBorders, dpiScale, LanguageHelper.IsLanguageSpaceJoining(language));
 88          }
 89  
 90          internal static async Task<OcrResult> GetOcrResultFromImageAsync(Bitmap bmp, Language language)
 91          {
 92              await using MemoryStream memoryStream = new();
 93              using WrappingStream wrappingStream = new(memoryStream);
 94  
 95              bmp.Save(wrappingStream, ImageFormat.Bmp);
 96              wrappingStream.Position = 0;
 97  
 98              BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(wrappingStream.AsRandomAccessStream());
 99              SoftwareBitmap softwareBmp = await bmpDecoder.GetSoftwareBitmapAsync();
100  
101              await memoryStream.DisposeAsync();
102              await wrappingStream.DisposeAsync();
103  
104              OcrEngine ocrEngine = OcrEngine.TryCreateFromLanguage(language);
105              return await ocrEngine.RecognizeAsync(softwareBmp);
106          }
107      }
108  }