diff --git a/Sources/Kapture/App.swift b/Sources/Kapture/App.swift
index 6e43cd6..d6ff6d3 100644
--- a/Sources/Kapture/App.swift
+++ b/Sources/Kapture/App.swift
@@ -119,33 +119,47 @@ enum LoginItem {
}
}
-func runOCRSelfTest() {
- let text = "Kapture OCR test 1234, hello world"
- let size = NSSize(width: 1600, height: 220)
+func renderTestImage(_ text: String, fontSize: CGFloat = 56) -> CGImage? {
+ let size = NSSize(width: 1900, height: 220)
guard let rep = NSBitmapImageRep(
bitmapDataPlanes: nil, pixelsWide: Int(size.width), pixelsHigh: Int(size.height),
bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false,
colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0
- ) else { exit(1) }
-
+ ) else { return nil }
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)
NSColor.white.setFill()
NSRect(origin: .zero, size: size).fill()
let attrs: [NSAttributedString.Key: Any] = [
- .font: NSFont.boldSystemFont(ofSize: 56),
+ .font: NSFont.systemFont(ofSize: fontSize),
.foregroundColor: NSColor.black,
]
text.draw(at: NSPoint(x: 60, y: 75), withAttributes: attrs)
NSGraphicsContext.restoreGraphicsState()
+ return rep.cgImage
+}
- guard let cgImage = rep.cgImage else { exit(1) }
- OCRService.shared.recognize(cgImage) { recognized in
- print("expected: \(text)")
- print("got: \(recognized)")
- let ok = recognized == text
- print(ok ? "PASS" : "FAIL")
- exit(ok ? 0 : 1)
+func runOCRSelfTest() {
+ let cases: [(expected: String, contains: String)] = [
+ ("Kapture OCR test 1234, hello world", "Kapture OCR test 1234"),
+ ("你好世界,这是一个测试", "你好世界"),
+ ]
+ var index = 0
+
+ func runNext() {
+ guard index < cases.count else { exit(0) }
+ let current = cases[index]
+ index += 1
+ guard let image = renderTestImage(current.expected) else { exit(1) }
+ OCRService.shared.recognize(image) { recognized in
+ print("case: \(current.expected)")
+ print("got: \(recognized)")
+ let ok = recognized.contains(current.contains)
+ print(ok ? "PASS" : "FAIL")
+ if !ok { exit(1) }
+ runNext()
+ }
}
+ runNext()
RunLoop.main.run()
}
diff --git a/Sources/Kapture/OCRService.swift b/Sources/Kapture/OCRService.swift
index e64d11b..ca321ff 100644
--- a/Sources/Kapture/OCRService.swift
+++ b/Sources/Kapture/OCRService.swift
@@ -12,6 +12,11 @@ final class OCRService {
request.recognitionLevel = .accurate
request.usesLanguageCorrection = true
request.recognitionLanguages = ["en-US", "zh-Hans", "zh-Hant", "ja-JP", "ko-KR"]
+ // Without this, Vision defaults to the first listed language and
+ // renders CJK as Latin garbage (verified: 你好世界 -> "177WR").
+ if #available(macOS 13.0, *) {
+ request.automaticallyDetectsLanguage = true
+ }
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
do {
diff --git a/build-app.sh b/build-app.sh
index a7510d9..523f98d 100755
--- a/build-app.sh
+++ b/build-app.sh
@@ -108,9 +108,9 @@ cat > "$APP/Contents/Info.plist" <<'PLIST'
CFBundleIconFile
Icon
CFBundleShortVersionString
- 1.9.0
+ 1.9.1
CFBundleVersion
- 90
+ 91
LSUIElement
NSHighResolutionCapable