Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New PowerToy] Create new OCR PowerToy #19172

Merged
merged 81 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
390d9cf
Init commit
TheJoeFin Jul 4, 2022
0ddb1c4
Fix unintended GUID change of Microsoft.PowerToys.Run.Plugin.TimeZone…
TheJoeFin Jul 4, 2022
41699d3
Region and click word working
TheJoeFin Jul 5, 2022
6b9eba8
Code style
TheJoeFin Jul 5, 2022
a0fb725
Close even when there is no result from the OCR
TheJoeFin Jul 5, 2022
a1ec4c9
Fix spelling concerns, and make overlay black to match snipping tool
TheJoeFin Jul 6, 2022
f84b5ba
increase opacity of overlay to match snipping tool
TheJoeFin Jul 6, 2022
612e4e5
Code Style and cleanup
TheJoeFin Jul 6, 2022
c915e44
Code style
TheJoeFin Jul 6, 2022
8325ba9
Create Logos and hook them into the project file
TheJoeFin Jul 9, 2022
11a7ab6
Make the PowerOCR VCXProj more like Awake VCXProj
TheJoeFin Jul 10, 2022
cbcce05
Rename MainWindow to OCROverlay
TheJoeFin Jul 10, 2022
a614491
Add WindowUtilities and WindowForms
TheJoeFin Jul 10, 2022
82d8d77
Remove fsg to fix spelling error
TheJoeFin Jul 10, 2022
cbe6245
launch OCR Overlay on every screen
TheJoeFin Jul 10, 2022
0096230
Add PowerOCR to Runner Main.cpp
TheJoeFin Jul 10, 2022
9c37a9d
Add PowerOCR Settings and Properties
TheJoeFin Jul 10, 2022
45efdea
Add PowerOcrViewModel
TheJoeFin Jul 10, 2022
1df892b
Fix wrong setting reference in PowerOcrSettingsVM
TheJoeFin Jul 12, 2022
7df0983
Try to clean up the Cpp project for PowerOCR
TheJoeFin Jul 12, 2022
2f7e0a4
Went to ARM64 was x64 thanks @snickler
TheJoeFin Jul 13, 2022
c15f67f
Clean up PowerOCR C++ Proj with file refs
TheJoeFin Jul 13, 2022
0631501
Rewrite C++ dllmain comparing to awake
TheJoeFin Jul 13, 2022
66662d5
Changes for spelling issues. The rest will stay
TheJoeFin Jul 14, 2022
73a3973
Create PowerOcr Settings Page and add to settings shell
TheJoeFin Jul 14, 2022
6b425c2
Fix PowerOcr Settings
TheJoeFin Jul 15, 2022
8b9badc
Fix multi-monitor scaling issue
TheJoeFin Jul 15, 2022
13baf3a
Add close all overlays when escaping
TheJoeFin Jul 15, 2022
5f7b901
Update src/runner/main.cpp to call correct Power OCR dll
TheJoeFin Jul 18, 2022
b4dd0ee
Update expect.txt
crutkas Jul 18, 2022
ca3ab9a
Add many files from Color Picker for hotkey activation
TheJoeFin Jul 23, 2022
208e4d5
Organize project into helper folder
TheJoeFin Jul 23, 2022
3fafb0d
Use new hotkey activation and keep process alive
TheJoeFin Jul 23, 2022
5f5aec3
Fix bug where scalebmp wasn't working
TheJoeFin Jul 23, 2022
90a1d59
Add The file headers and dispose app.xaml.cs
TheJoeFin Jul 23, 2022
6597b82
Merge branch 'microsoft:main' into main
TheJoeFin Jul 23, 2022
f1e1055
Code style changes
TheJoeFin Jul 23, 2022
1bb7ff6
Fix bug where PowerOCR was toggling Awake
TheJoeFin Jul 24, 2022
44e3064
Unsubscribe from keyboard events making they don't fire twice
TheJoeFin Jul 24, 2022
1da03c3
Add SndPowerOcrSetting and add to SettingsVM
TheJoeFin Jul 24, 2022
b8a0ce4
Trying to make the runner close PowerOCR when runner closes
TheJoeFin Aug 4, 2022
0d267e9
Fix app_name
TheJoeFin Aug 4, 2022
71696f6
Update spellcheck expect
TheJoeFin Aug 4, 2022
aa3a065
use mutex on PowerOCR app to keep to single instance
TheJoeFin Aug 10, 2022
03ccc73
Sync upstream
TheJoeFin Aug 10, 2022
5c220ed
Merge branch 'microsoft:main' into main
TheJoeFin Aug 10, 2022
be9cb3b
Rebuild the module interface using ColorPicker as a template.
TheJoeFin Aug 13, 2022
fe3d310
Merge branch 'microsoft:main' into main
TheJoeFin Aug 13, 2022
a22ac15
Fix project names of the module interface
TheJoeFin Aug 14, 2022
ce11546
Put app startup args back to 0 like color picker
TheJoeFin Aug 14, 2022
8eb07a2
Runner now finds and enables/disables PowerOCR
TheJoeFin Aug 15, 2022
4b64848
remove unneeded item groups from settings proj, per stefansjfw
TheJoeFin Aug 16, 2022
262495f
Add PowerOCR Screenshots
TheJoeFin Aug 16, 2022
05a9b7d
Revert changed project GUID
TheJoeFin Aug 16, 2022
0176611
Merge branch 'microsoft:main' into main
TheJoeFin Aug 16, 2022
71de017
Add OOBE content for PowerOCR
TheJoeFin Aug 19, 2022
43f7a30
Keep cursor on one screen since the OCR window does not span screens.
TheJoeFin Aug 19, 2022
b59f42d
reload settings when activation key is pressed
TheJoeFin Aug 19, 2022
24e26c2
New screenshots and OOBE text
TheJoeFin Aug 20, 2022
8ce93ac
Merge branch 'microsoft:main' into main
TheJoeFin Aug 20, 2022
f11c9cb
Add PowerOCR as a case in the settings App.xaml.cs OnLaunched
TheJoeFin Aug 20, 2022
6f2c370
Settings and OOBE Text Changes
TheJoeFin Aug 21, 2022
4c98e95
Using using on bitmaps and change OCR overlay to stay open if no result
TheJoeFin Aug 21, 2022
f415e6c
Keyboard activation is handled is true
TheJoeFin Aug 21, 2022
ad4e07b
Remove unused start PowerOCR OOBE Method
TheJoeFin Aug 21, 2022
6076b61
[PowerOCR]Add some telemetry
jaimecbernardo Aug 22, 2022
cf89107
Add some logging
jaimecbernardo Aug 22, 2022
14af8d1
Don't recreate the OCR overlay Windows more times
jaimecbernardo Aug 22, 2022
e4588d2
Add to BugReportTool to get event viewer errors
jaimecbernardo Aug 22, 2022
50bce5a
Fix wrong comment
jaimecbernardo Aug 22, 2022
aa5b3b1
Fix another comment
jaimecbernardo Aug 22, 2022
05ab02f
Add files to installer
jaimecbernardo Aug 22, 2022
83ead1b
Add to signing
jaimecbernardo Aug 22, 2022
bf84066
Don't take Esc away from other apps
jaimecbernardo Aug 23, 2022
dab9926
Default to Win Shift R
jaimecbernardo Aug 23, 2022
d2896d6
Use low level keyboard hook from runner
jaimecbernardo Aug 23, 2022
3fc84b6
Remove esc from local low level keyboard hook
jaimecbernardo Aug 23, 2022
e1d5913
Merge branch 'main' into main
jaimecbernardo Aug 24, 2022
ec6cab0
Merge branch 'main' into main
jaimecbernardo Aug 24, 2022
9302213
Fix some nits
jaimecbernardo Aug 24, 2022
a279e30
Default to Win Shift T
jaimecbernardo Aug 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions PowerToys.sln
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerContextMenu", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerLib", "src\modules\imageresizer\ImageResizerLib\ImageResizerLib.vcxproj", "{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerOCR", "PowerOCR", "{A50C70A6-2DA0-4027-B90E-B1A40755A8A5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerOCRModuleInterface", "src\modules\PowerOCR\PowerOCRModuleInterface\PowerOCRModuleInterface.vcxproj", "{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerOCR", "src\modules\PowerOCR\PowerOCR\PowerOCR.csproj", "{25C91A4E-BA4E-467A-85CD-8B62545BF674}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Expand Down Expand Up @@ -1632,6 +1638,30 @@ Global
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x64.Build.0 = Release|x64
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x86.ActiveCfg = Release|x64
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x86.Build.0 = Release|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|ARM64.ActiveCfg = Debug|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|ARM64.Build.0 = Debug|x64
TheJoeFin marked this conversation as resolved.
Show resolved Hide resolved
TheJoeFin marked this conversation as resolved.
Show resolved Hide resolved
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x64.ActiveCfg = Debug|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x64.Build.0 = Debug|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x86.ActiveCfg = Debug|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x86.Build.0 = Debug|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|ARM64.ActiveCfg = Release|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|ARM64.Build.0 = Release|x64
TheJoeFin marked this conversation as resolved.
Show resolved Hide resolved
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x64.ActiveCfg = Release|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x64.Build.0 = Release|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x86.ActiveCfg = Release|x64
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x86.Build.0 = Release|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.ActiveCfg = Debug|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.Build.0 = Debug|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x64.ActiveCfg = Debug|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x64.Build.0 = Debug|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x86.ActiveCfg = Debug|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x86.Build.0 = Debug|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|ARM64.ActiveCfg = Release|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|ARM64.Build.0 = Release|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x64.ActiveCfg = Release|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x64.Build.0 = Release|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x86.ActiveCfg = Release|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1770,6 +1800,9 @@ Global
{5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{93B72A06-C8BD-484F-A6F7-C9F280B150BF} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{A50C70A6-2DA0-4027-B90E-B1A40755A8A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
Expand Down
8 changes: 8 additions & 0 deletions src/modules/PowerOCR/PowerOCR/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Application
x:Class="PowerOCR.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PowerOCR"
Startup="Application_Startup">
<Application.Resources />
</Application>
15 changes: 15 additions & 0 deletions src/modules/PowerOCR/PowerOCR/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using PowerOCR.Utilities;
using System.Windows;

namespace PowerOCR;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
WindowUtilities.LaunchOCROverlayOnEveryScreen();
}
}
10 changes: 10 additions & 0 deletions src/modules/PowerOCR/PowerOCR/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Windows;

[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
237 changes: 237 additions & 0 deletions src/modules/PowerOCR/PowerOCR/ImageMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
namespace PowerOCR;

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Windows.Globalization;
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using BitmapDecoder = Windows.Graphics.Imaging.BitmapDecoder;

internal class ImageMethods
{
internal static ImageSource GetWindowBoundsImage(Window passedWindow)
{
bool isGrabFrame = false;

DpiScale dpi = VisualTreeHelper.GetDpi(passedWindow);
int windowWidth = (int)(passedWindow.ActualWidth * dpi.DpiScaleX);
int windowHeight = (int)(passedWindow.ActualHeight * dpi.DpiScaleY);

System.Windows.Point absPosPoint = passedWindow.GetAbsolutePosition();
int thisCorrectedLeft = (int)(absPosPoint.X * dpi.DpiScaleX);
int thisCorrectedTop = (int)(absPosPoint.Y * dpi.DpiScaleY);

if (isGrabFrame == true)
{
thisCorrectedLeft += (int)(2 * dpi.DpiScaleX);
thisCorrectedTop += (int)(26 * dpi.DpiScaleY);
windowWidth -= (int)(4 * dpi.DpiScaleX);
windowHeight -= (int)(70 * dpi.DpiScaleY);
}

Bitmap bmp = new(windowWidth, windowHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);

g.CopyFromScreen(thisCorrectedLeft, thisCorrectedTop, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
return BitmapToImageSource(bmp);
}

internal static async Task<string> GetRegionsText(Window? passedWindow, Rectangle selectedRegion)
{
Bitmap bmp = new(selectedRegion.Width, selectedRegion.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);

System.Windows.Point absPosPoint = passedWindow == null ? (new()) : passedWindow.GetAbsolutePosition();

int thisCorrectedLeft = (int)absPosPoint.X + selectedRegion.Left;
int thisCorrectedTop = (int)absPosPoint.Y + selectedRegion.Top;

g.CopyFromScreen(thisCorrectedLeft, thisCorrectedTop, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
// bmp = PadImage(bmp);

string? ResultText = await ExtractText(bmp);

return ResultText != null ? ResultText.Trim() : "";
}

internal static async Task<string> GetClickedWord(Window passedWindow, System.Windows.Point clickedPoint)
{
DpiScale dpi = VisualTreeHelper.GetDpi(passedWindow);
Bitmap bmp = new((int)(passedWindow.ActualWidth * dpi.DpiScaleX), (int)(passedWindow.ActualHeight * dpi.DpiScaleY), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);

System.Windows.Point absPosPoint = passedWindow.GetAbsolutePosition();
int thisCorrectedLeft = (int)absPosPoint.X;
int thisCorrectedTop = (int)absPosPoint.Y;

g.CopyFromScreen(thisCorrectedLeft, thisCorrectedTop, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);

System.Windows.Point adjustedPoint = new(clickedPoint.X, clickedPoint.Y);

string ResultText = await ExtractText(bmp, adjustedPoint);
return ResultText.Trim();
}

public static async Task<string> ExtractText(Bitmap bmp, System.Windows.Point? singlePoint = null)
{
Language? selectedLanguage = GetOCRLanguage();
if (selectedLanguage == null)
return "";

bool isCJKLang = false;

if (selectedLanguage.LanguageTag.StartsWith("zh", StringComparison.InvariantCultureIgnoreCase) == true)
isCJKLang = true;
else if (selectedLanguage.LanguageTag.StartsWith("ja", StringComparison.InvariantCultureIgnoreCase) == true)
isCJKLang = true;
else if (selectedLanguage.LanguageTag.StartsWith("ko", StringComparison.InvariantCultureIgnoreCase) == true)
isCJKLang = true;

XmlLanguage lang = XmlLanguage.GetLanguage(selectedLanguage.LanguageTag);
CultureInfo culture = lang.GetEquivalentCulture();

bool scaleBMP = true;

if (singlePoint != null
|| bmp.Width * 1.5 > OcrEngine.MaxImageDimension)
scaleBMP = false;

Bitmap scaledBitmap = scaleBMP ? ScaleBitmapUniform(bmp, 1.5) : ScaleBitmapUniform(bmp, 1.0);
StringBuilder text = new();

await using (MemoryStream memory = new())
{
scaledBitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(memory.AsRandomAccessStream());
SoftwareBitmap softwareBmp = await bmpDecoder.GetSoftwareBitmapAsync();

OcrEngine ocrEngine = OcrEngine.TryCreateFromLanguage(selectedLanguage);
OcrResult ocrResult = await ocrEngine.RecognizeAsync(softwareBmp);

if (singlePoint == null)
foreach (OcrLine line in ocrResult.Lines) text.AppendLine(line.Text);
else
{
Windows.Foundation.Point fPoint = new(singlePoint.Value.X, singlePoint.Value.Y);
foreach (OcrLine ocrLine in ocrResult.Lines)
foreach (OcrWord ocrWord in ocrLine.Words)
if (ocrWord.BoundingRect.Contains(fPoint))
_ = text.Append(ocrWord.Text);
}
}
if (culture.TextInfo.IsRightToLeft)
{
string[] textListLines = text.ToString().Split(new char[] { '\n', '\r' });

_ = text.Clear();
foreach (string textLine in textListLines)
{
List<string> wordArray = textLine.Split().ToList();
wordArray.Reverse();
_ = isCJKLang == true ? text.Append(string.Join("", wordArray)) : text.Append(string.Join(' ', wordArray));

if (textLine.Length > 0)
_ = text.Append('\n');
}
return text.ToString();
}
else
{
return text.ToString();
}
}

public static Bitmap ScaleBitmapUniform(Bitmap passedBitmap, double scale)
{
using MemoryStream memory = new();
passedBitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
TransformedBitmap transformedBmp = new();
transformedBmp.BeginInit();
transformedBmp.Source = bitmapimage;
transformedBmp.Transform = new ScaleTransform(scale, scale);
transformedBmp.EndInit();
return BitmapSourceToBitmap(transformedBmp.Source);
}

public static Bitmap BitmapSourceToBitmap(BitmapSource source)
{
Bitmap bmp = new(
source.PixelWidth,
source.PixelHeight,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
BitmapData data = bmp.LockBits(
new Rectangle(System.Drawing.Point.Empty, bmp.Size),
ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
source.CopyPixels(
Int32Rect.Empty,
data.Scan0,
data.Height * data.Stride,
data.Stride);
bmp.UnlockBits(data);
return bmp;
}

internal static BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using MemoryStream memory = new();
bitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();

return bitmapimage;
}

public static Language? GetOCRLanguage()
{
// use currently selected Language
string inputLang = InputLanguageManager.Current.CurrentInputLanguage.Name;

Language? selectedLanguage = new(inputLang);
List<Language> possibleOCRLangs = OcrEngine.AvailableRecognizerLanguages.ToList();

if (possibleOCRLangs.Count < 1)
{
MessageBox.Show("No possible OCR languages are installed.", "Text Grab");
return null;
}

if (possibleOCRLangs.All(l => l.LanguageTag != selectedLanguage.LanguageTag))
{
List<Language>? similarLanguages = possibleOCRLangs.Where(
la => la.AbbreviatedName == selectedLanguage.AbbreviatedName).ToList();

if (similarLanguages != null)
{
selectedLanguage = similarLanguages.Count > 0
? similarLanguages.FirstOrDefault()
: possibleOCRLangs.FirstOrDefault();
}
}

return selectedLanguage;
}
}
54 changes: 54 additions & 0 deletions src/modules/PowerOCR/PowerOCR/OCROverlay.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<Window
x:Class="PowerOCR.OCROverlay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PowerOCR"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="PowerOCR"
Width="800"
Height="450"
AllowsTransparency="True"
Background="Transparent"
Loaded="Window_Loaded"
ResizeMode="NoResize"
Topmost="True"
WindowStyle="None"
mc:Ignorable="d">
<Grid>
<Viewbox>
<Image x:Name="BackgroundImage" Stretch="UniformToFill" />
</Viewbox>
<Canvas
Name="RegionClickCanvas"
Cursor="Cross"
MouseDown="RegionClickCanvas_MouseDown"
MouseMove="RegionClickCanvas_MouseMove"
MouseUp="RegionClickCanvas_MouseUp">
<Canvas.Clip>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry x:Name="FullWindow" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry x:Name="clippingGeometry" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Canvas.Clip>
<Canvas.Background>
<SolidColorBrush
x:Name="BackgroundBrush"
Opacity="0"
Color="Black" />
</Canvas.Background>
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem
Name="CancelMenuItem"
Click="CancelMenuItem_Click"
Header="Cancel" />
</ContextMenu>
</Canvas.ContextMenu>
</Canvas>
</Grid>
</Window>
Loading