forked from raycast/script-commands
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathocr.swift
executable file
·143 lines (115 loc) · 4.15 KB
/
ocr.swift
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/swift
// Required parameters:
// @raycast.schemaVersion 1
// @raycast.title OCR
// @raycast.mode silent
// Optional parameters:
// @raycast.icon 🖼
// @raycast.packageName Productivity
// Documentation:
// @raycast.author zhe
// @raycast.authorURL https://github.com/wmszhe
// @raycast.description Use macOS Vision API Identification pictures, if it contain a QR code, Copy the QR code content to the clipboard, If do not include QR codes, identify text content and supplement to clipboard
import Foundation
import CoreImage
import Cocoa
import Vision
let screenCapturePath = "/tmp/ocr.png"
let recognitionLanguages = ["en-US", "zh-CN"]
let joiner = " "
@discardableResult
func screenCapture(_ command: String) throws -> String {
let task = Process()
let pipe = Pipe()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
task.standardOutput = pipe
task.standardError = pipe
try task.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
if let output = String(data: data, encoding: .utf8) {
return output
} else {
throw NSError(domain: "error", code: -1, userInfo: nil)
}
}
func convertCIImageToCGImage(inputImage: CIImage) -> CGImage? {
let context = CIContext(options: nil)
return context.createCGImage(inputImage, from: inputImage.extent)
}
func paste(text: String) {
let pasteboard = NSPasteboard.general
pasteboard.declareTypes([.string], owner: nil)
pasteboard.clearContents()
pasteboard.setString(text, forType: .string)
}
func recognizeTextHandler(request: VNRequest, error: Error?) {
guard let observations = request.results as? [VNRecognizedTextObservation] else {
return
}
let recognizedStrings = observations.compactMap { observation in
// Return the string of the top VNRecognizedText instance.
observation.topCandidates(1).first?.string
}
// Process the recognized strings.
let result = recognizedStrings.joined(separator: joiner)
print("The text content is: " + result)
paste(text: result)
}
func detectText(fileName: URL) {
guard
let ciImage = CIImage(contentsOf: fileName),
let img = convertCIImageToCGImage(inputImage: ciImage)
else {
return
}
let requestHandler = VNImageRequestHandler(cgImage: img)
// Create a new request to recognize text.
let request = VNRecognizeTextRequest(completionHandler: recognizeTextHandler)
request.recognitionLanguages = recognitionLanguages
do {
// Perform the text-recognition request.
try requestHandler.perform([request])
} catch {
print("Unable to perform the requests: \(error).")
}
}
func detectImage(fileName: URL) -> Bool {
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)
guard let ciImage = CIImage(contentsOf: fileName), let features = detector?.features(in: ciImage) else {
return false
}
var isQRCode = false
var result = ""
for feature in features as! [CIQRCodeFeature] {
if feature.type == "QRCode" {
isQRCode = true
}
result += feature.messageString ?? ""
result += "\n"
}
if isQRCode {
print("QR code analysis results: " + result)
paste(text: result)
}
return isQRCode
}
func main() {
// Only support the system above macOS 10.15
guard #available(OSX 10.15, *) else {
return print("Only support the system above macOS 10.15")
}
do {
// It must be ensured that the screenshot is preserved successfully
try screenCapture("/usr/sbin/screencapture -i " + screenCapturePath)
print("screen capture complete, Image preservation location: " + screenCapturePath)
} catch {
return print("\(error)")
}
// Determine whether the picture contains a QR code, if it contain a QR code, Copy the QR code content to the clipboard
guard detectImage(fileName: URL(fileURLWithPath: screenCapturePath)) else {
// If do not include QR codes, identify text content and supplement to clipboard
return detectText(fileName: URL(fileURLWithPath: screenCapturePath))
}
}
main()