1using System; 2using System.Diagnostics; 3using System.Drawing; 4using System.Drawing.Imaging; 5using System.IO; 6using System.Text; 7 8namespace WindowCapture.Helpers 9{ 10 /// <summary> 11 /// Calls the bundled .NET 8 Windows-OCR helper (bin/Ocr/WC.Ocr.exe, WinRT Windows.Media.Ocr) 12 /// to extract text from an image. Local, offline, free; RU + EN. Returns null on failure. 13 /// </summary> 14 public static class OcrClient 15 { 16 public static string HelperPath() 17 { 18 return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ocr", "WC.Ocr.exe"); 19 } 20 21 public static bool IsAvailable { get { return File.Exists(HelperPath()); } } 22 23 /// <summary>Recognize text in the image. lang is a BCP-47 tag ("ru"/"en"); the helper falls 24 /// back to the user's profile languages if it's unavailable.</summary> 25 public static string Recognize(Bitmap image, string lang) 26 { 27 if (image == null) return null; 28 string exe = HelperPath(); 29 if (!File.Exists(exe)) return null; 30 31 string tmp = Path.Combine(Path.GetTempPath(), "wc_ocr_" + Guid.NewGuid().ToString("N") + ".png"); 32 try 33 { 34 image.Save(tmp, ImageFormat.Png); 35 var psi = new ProcessStartInfo 36 { 37 FileName = exe, 38 Arguments = "\"" + tmp + "\" " + (lang ?? ""), 39 UseShellExecute = false, 40 RedirectStandardOutput = true, 41 RedirectStandardError = true, 42 CreateNoWindow = true, 43 StandardOutputEncoding = Encoding.UTF8 44 }; 45 using (var p = Process.Start(psi)) 46 { 47 string outText = p.StandardOutput.ReadToEnd(); 48 p.StandardError.ReadToEnd(); // drain so the child can't block on a full stderr buffer 49 if (!p.WaitForExit(15000)) { try { p.Kill(); } catch { } return null; } 50 if (p.ExitCode != 0) return null; 51 return outText; 52 } 53 } 54 catch { return null; } 55 finally { try { File.Delete(tmp); } catch { } } 56 } 57 } 58}