import Foundation import Vision import AppKit struct OcrLine: Encodable { let text: String let x: Double let y: Double let width: Double let height: Double } let args = CommandLine.arguments guard args.count >= 2 else { fputs("usage: swift ocr_image_text.swift \\n", stderr) exit(2) } let imageURL = URL(fileURLWithPath: args[1]) guard let image = NSImage(contentsOf: imageURL), let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { fputs("failed to load image: \\(args[1])\\n", stderr) exit(1) } let request = VNRecognizeTextRequest() request.recognitionLevel = .accurate request.usesLanguageCorrection = true request.recognitionLanguages = ["zh-Hans", "en-US"] request.minimumTextHeight = 0.006 let handler = VNImageRequestHandler(cgImage: cgImage, options: [:]) try handler.perform([request]) let observations = request.results ?? [] let lines = observations.compactMap { observation -> OcrLine? in guard let candidate = observation.topCandidates(1).first else { return nil } let box = observation.boundingBox return OcrLine( text: candidate.string, x: Double(box.minX), y: Double(box.minY), width: Double(box.width), height: Double(box.height) ) }.sorted { let y0 = Int($0.y * 1000) let y1 = Int($1.y * 1000) if y0 != y1 { return y0 > y1 } return $0.x < $1.x } let data = try JSONEncoder().encode(lines) FileHandle.standardOutput.write(data)