-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
xiaorui.wx
committed
Oct 27, 2023
1 parent
bce2a9a
commit a3afbd9
Showing
10 changed files
with
276 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# 1. build MacosOcr project | ||
echo "☕️ start build ocr ..." | ||
cd ./src/MacosOcr | ||
swift build -c release | ||
cd ../../ | ||
cp ./src/MacosOcr/.build/release/MacosOcr ./ocr | ||
|
||
# 2. build LeftMouseDragged project | ||
echo "☕️ start build mouse-drag ..." | ||
cd ./src/LeftMouseDragged | ||
swift build -c release | ||
cd ../../ | ||
cp ./src/LeftMouseDragged/.build/release/LeftMouseDragged ./mouse-drag |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,14 @@ | ||
## executable binary create by swift | ||
## Build swift project | ||
```bash | ||
bash ./build.sh | ||
``` | ||
|
||
## Executable binary create by swift | ||
- OCR | ||
- ocr ability powered by macOS. | ||
- usage: ocr /path/to/img | ||
|
||
- mouse-drag | ||
- mouse drag to (+x,+y) relate to current point | ||
- mouse-drag delay x y | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// swift-tools-version: 5.9 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "LeftMouseDragged", | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
.executableTarget( | ||
name: "LeftMouseDragged"), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// The Swift Programming Language | ||
// https://docs.swift.org/swift-book | ||
|
||
import AppKit | ||
import Cocoa | ||
|
||
func taskDelay(_ millSeconds: Int, _ task: @escaping () -> Void) { | ||
DispatchQueue.main.asyncAfter(deadline: .now() + Double(millSeconds) / 1000.0, execute: task) | ||
} | ||
|
||
func postMouseEvent(button:CGMouseButton, type:CGEventType, point: CGPoint,clickCount:Int64 = 1) | ||
{ | ||
let event = createMouseEvent(button: button, type: type, point: point,clickCount:clickCount) | ||
event.post(tap: CGEventTapLocation.cghidEventTap) | ||
} | ||
|
||
func createMouseEvent(button:CGMouseButton, type:CGEventType, point: CGPoint,clickCount:Int64 = 1) -> CGEvent | ||
{ | ||
let event : CGEvent = CGEvent(mouseEventSource: CGEventSource.init(stateID: CGEventSourceStateID.privateState), mouseType: type, mouseCursorPosition: point, mouseButton: button)! | ||
event.setIntegerValueField(CGEventField.mouseEventClickState, value: clickCount) | ||
return event | ||
} | ||
|
||
func mouseDragged(point:CGPoint,toPoint:CGPoint,button:CGMouseButton,postDelay:Int){ | ||
let toMaxX:Bool = toPoint.x - point.x > 0 | ||
let toMaxY:Bool = toPoint.y - point.y > 0 | ||
|
||
var tempPointY = point.y | ||
var tempPointX = point.x | ||
|
||
postMouseEvent(button: button, type: button == .left ? .leftMouseDown : .rightMouseDown, point: point,clickCount: 1); | ||
|
||
let blockOperation = BlockOperation() | ||
|
||
blockOperation.addExecutionBlock { | ||
while toMaxY ? (toPoint.y > tempPointY) : (toPoint.y < tempPointY){ | ||
Thread.sleep(forTimeInterval: 0.0001 * Double(postDelay)) | ||
toMaxY ? (tempPointY += 1) : (tempPointY -= 1) | ||
postMouseEvent(button: button, type: button == .left ? .leftMouseDragged : .rightMouseDragged, point: CGPoint(x: tempPointX, y: tempPointY),clickCount: 1); | ||
} | ||
} | ||
blockOperation.addExecutionBlock { | ||
while toMaxX ? (toPoint.x > tempPointX) : (toPoint.x < tempPointX) { | ||
Thread.sleep(forTimeInterval: 0.0001 * Double(postDelay)) | ||
toMaxX ? (tempPointX += 1) : (tempPointX -= 1) | ||
postMouseEvent(button: button, type: button == .left ? .leftMouseDragged : .rightMouseDragged, point: CGPoint(x: tempPointX, y: tempPointY),clickCount: 1); | ||
} | ||
|
||
} | ||
blockOperation.completionBlock = { | ||
postMouseEvent(button: button, type: button == .left ? .leftMouseUp : .rightMouseUp, point: toPoint,clickCount: 1); | ||
} | ||
blockOperation.start() | ||
} | ||
|
||
func printJson(_ data: Any) { | ||
let jsonData = try! JSONSerialization.data(withJSONObject: data) | ||
print(String(data: jsonData, encoding: String.Encoding.utf8) ?? "") | ||
} | ||
|
||
func main(args: [String]) -> Int32 { | ||
guard CommandLine.arguments.count == 6 || CommandLine.arguments.count == 4 else { | ||
fputs(String(format: "usage1: %1$@ postDelay x1 y1 x2 y2, dragged from (x1, y1) to (x1, y2), when move a px, sleep(postDelay)\n", CommandLine.arguments[0]), stderr) | ||
fputs(String(format: "usage2: %1$@ postDelay x y, dragged from mouseLocation to (mouseLocation.x + x, mouseLocation.y + y), when move a px, sleep(postDelay)\n", CommandLine.arguments[0]), stderr) | ||
return 1 | ||
} | ||
let postDelay = Int(args[1]) ?? 0 | ||
var mouseLoc = NSEvent.mouseLocation | ||
|
||
if (CommandLine.arguments.count == 4) { | ||
mouseLoc.y = NSHeight(NSScreen.screens[0].frame) - mouseLoc.y; | ||
let newLoc = CGPoint(x: mouseLoc.x+CGFloat(Int(args[2]) ?? 0), y: mouseLoc.y+CGFloat(Int(args[3]) ?? 0)) | ||
mouseDragged( | ||
point: CGPoint(x: mouseLoc.x, y: mouseLoc.y), | ||
toPoint: newLoc, | ||
button: .left, | ||
postDelay: postDelay | ||
) | ||
printJson([ | ||
"success": true, | ||
"from": [ "x1": Int(mouseLoc.x), "y1": Int(mouseLoc.y) ], | ||
"to": [ "x2": Int(newLoc.x), "y2": Int(newLoc.y) ], | ||
]) | ||
return 0 | ||
} | ||
|
||
let x1 = Int(args[2]) ?? Int(mouseLoc.x) | ||
let y1 = Int(args[3]) ?? Int(mouseLoc.y) | ||
let x2 = Int(args[4]) ?? Int(mouseLoc.x) | ||
let y2 = Int(args[5]) ?? Int(mouseLoc.y) | ||
|
||
if (x1 != x2 || y1 != y2) { | ||
mouseDragged( | ||
point: CGPoint(x: x1, y: y1), | ||
toPoint: CGPoint(x: x2, y: y2), | ||
button: .left, | ||
postDelay: postDelay | ||
) | ||
} | ||
printJson([ | ||
"success": true, | ||
"from": [ "x1": x1, "y1": y1 ], | ||
"to": [ "x2": x2, "y2": y2 ], | ||
]) | ||
return 0 | ||
} | ||
|
||
exit(main(args: CommandLine.arguments)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// swift-tools-version: 5.9 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "MacosOcr", | ||
platforms: [ | ||
.macOS(.v10_15) | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
.executableTarget( | ||
name: "MacosOcr"), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// The Swift Programming Language | ||
// https://docs.swift.org/swift-book | ||
|
||
import Cocoa | ||
import Vision | ||
// import ArgumentParser | ||
|
||
// https://developer.apple.com/documentation/vision/vnrecognizetextrequest | ||
|
||
let MODE: VNRequestTextRecognitionLevel = VNRequestTextRecognitionLevel.accurate // or .fast | ||
let USE_LANG_CORRECTION = false | ||
var REVISION:Int | ||
if #available(macOS 13, *) { | ||
REVISION = VNRecognizeTextRequestRevision3 | ||
} else if #available(macOS 11, *) { | ||
REVISION = VNRecognizeTextRequestRevision2 | ||
} else { | ||
REVISION = VNRecognizeAnimalsRequestRevision1 | ||
} | ||
|
||
func main(args: [String]) -> Int32 { | ||
guard CommandLine.arguments.count == 2 else { | ||
fputs(String(format: "usage: %1$@ image\n", CommandLine.arguments[0]), stderr) | ||
return 1 | ||
} | ||
|
||
let src = args[1] | ||
|
||
guard let img = NSImage(byReferencingFile: src) else { | ||
fputs("Error: failed to load image '\(src)'\n", stderr) | ||
return 1 | ||
} | ||
|
||
guard let imgRef = img.cgImage(forProposedRect: &img.alignmentRect, context: nil, hints: nil) else { | ||
fputs("Error: failed to convert NSImage to CGImage for '\(src)'\n", stderr) | ||
return 1 | ||
} | ||
|
||
let request: VNRecognizeTextRequest = VNRecognizeTextRequest { (request, error) in | ||
let observations: [VNRecognizedTextObservation] = request.results as? [VNRecognizedTextObservation] ?? [] | ||
var results: [Any] = [] | ||
for observation: VNRecognizedTextObservation in observations { | ||
let candidate: VNRecognizedText = observation.topCandidates(1)[0] | ||
let value = [ | ||
"word": candidate.string, | ||
"rect": [ | ||
"left": Int(Float(observation.topLeft.x) * Float(imgRef.width)), | ||
"top": Int(Float(1 - observation.topLeft.y) * Float(imgRef.height)), | ||
"width": Int(Float(observation.topRight.x - observation.topLeft.x) * Float(imgRef.width)), | ||
"height": Int(Float(observation.topLeft.y - observation.bottomLeft.y) * Float(imgRef.height)), | ||
], | ||
"confidence": candidate.confidence, | ||
] | ||
results.append(value) | ||
} | ||
let data = try! JSONSerialization.data(withJSONObject: results) | ||
print(String(data: data, encoding: String.Encoding.utf8) ?? "") | ||
} | ||
request.recognitionLevel = MODE | ||
request.usesLanguageCorrection = USE_LANG_CORRECTION | ||
request.revision = REVISION | ||
request.recognitionLanguages = ["zh-Hans", "en-US"] | ||
//request.minimumTextHeight = 0 | ||
//request.customWords = [String] | ||
|
||
try? VNImageRequestHandler(cgImage: imgRef, options: [:]).perform([request]) | ||
return 0 | ||
} | ||
|
||
exit(main(args: CommandLine.arguments)) | ||
|
||
// struct Banner: ParsableCommand { | ||
// static let configuration = CommandConfiguration( | ||
// abstract: "A Swift command-line tool to manage blog post banners", | ||
// subcommands: [Generate.self]) | ||
|
||
// init() { } | ||
// } | ||
|
||
// // Banner.main() | ||
|
||
// struct Generate: ParsableCommand { | ||
|
||
// public static let configuration = CommandConfiguration(abstract: "Generate a blog post banner from the given input") | ||
|
||
// @Argument(help: "The title of the blog post") | ||
// private var title: String | ||
|
||
// @Option(name: .shortAndLong, default: nil, help: "The week of the blog post as used in the file name") | ||
// private var week: Int? | ||
|
||
// @Flag(name: .long, help: "Show extra logging for debugging purposes") | ||
// private var verbose: Bool | ||
|
||
// func run() throws { | ||
// if verbose { | ||
// let weekDescription = week.map { "and week \($0)" } | ||
// print("Creating a banner for title \"\(title)\" \(weekDescription ?? "")") | ||
// } | ||
// } | ||
// } |