forked from ynkdir/py-win32more
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwinrt_ocr.py
123 lines (95 loc) · 3.41 KB
/
winrt_ocr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import asyncio
from ctypes import sizeof
from win32more import FAILED, WinError
from win32more.Windows.Graphics.Imaging import BitmapDecoder
from win32more.Windows.Media.Ocr import OcrEngine
from win32more.Windows.Storage import FileAccessMode
from win32more.Windows.Storage.Pickers import FileOpenPicker
from win32more.Windows.UI.Popups import MessageDialog
from win32more.Windows.Win32.System.LibraryLoader import GetModuleHandle
from win32more.Windows.Win32.System.WinRT import (
RO_INIT_MULTITHREADED,
RoInitialize,
RoUninitialize,
)
from win32more.Windows.Win32.UI.Input.KeyboardAndMouse import SetActiveWindow
from win32more.Windows.Win32.UI.Shell import IInitializeWithWindow
from win32more.Windows.Win32.UI.WindowsAndMessaging import (
CW_USEDEFAULT,
MSG,
WNDCLASS,
WS_OVERLAPPED,
CreateWindowEx,
DefWindowProc,
DispatchMessage,
GetMessage,
PostQuitMessage,
RegisterClass,
SetTimer,
TranslateMessage,
)
def create_owner_window():
CLASS_NAME = "Owner Window"
hInstance = GetModuleHandle(None)
wc = WNDCLASS()
wc.cbSize = sizeof(WNDCLASS)
wc.lpfnWndProc = DefWindowProc
wc.hInstance = hInstance
wc.lpszClassName = CLASS_NAME
atom = RegisterClass(wc)
if not atom:
raise WinError()
hwnd = CreateWindowEx(
0, CLASS_NAME, "", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0
)
if not hwnd:
raise WinError()
# workaround to avoid that dialog window appear in background.
SetActiveWindow(hwnd)
return hwnd
async def show_message(owner_window, title, msg):
dialog = MessageDialog.CreateWithTitle(msg, title)
dialog.as_(IInitializeWithWindow).Initialize(owner_window)
return await dialog.ShowAsync()
async def open_file(owner_window, filter):
picker = FileOpenPicker.CreateInstance()
picker.as_(IInitializeWithWindow).Initialize(owner_window)
picker.FileTypeFilter.Append(filter)
return await picker.PickSingleFileAsync()
async def read_image(storage_file):
bitmap = await BitmapDecoder.CreateWithIdAsync(
BitmapDecoder.PngDecoderId, await storage_file.OpenAsync(FileAccessMode.Read)
)
return await bitmap.GetSoftwareBitmapAsync()
def list_ocr_languages():
print("AvailableRecognizerLanguages:")
for lang in OcrEngine.AvailableRecognizerLanguages:
print(f"{lang.LanguageTag}: {lang.DisplayName}")
async def ocr(software_image):
# lang = Language.CreateLanguage("ja")
engine = OcrEngine.TryCreateFromUserProfileLanguages()
result = await engine.RecognizeAsync(software_image)
return result.Text
async def winrt_ocr(owner_window):
list_ocr_languages()
storage_file = await open_file(owner_window, ".png")
if not storage_file:
return
software_bitmap = await read_image(storage_file)
text = await ocr(software_bitmap)
await show_message(owner_window, "Ocr result", text)
async def main():
hr = RoInitialize(RO_INIT_MULTITHREADED)
if FAILED(hr):
raise WinError(hr)
task = asyncio.create_task(winrt_ocr(create_owner_window()))
task.add_done_callback(lambda _: PostQuitMessage(0))
SetTimer(0, 0, 100, None) # to poll asyncio
msg = MSG()
while GetMessage(msg, 0, 0, 0) > 0:
TranslateMessage(msg)
DispatchMessage(msg)
await asyncio.sleep(0)
RoUninitialize()
if __name__ == "__main__":
asyncio.run(main())