Skip to content

Commit

Permalink
Merge pull request #1 from Shakshi3104/support_macos12
Browse files Browse the repository at this point in the history
Fallback on macOS 12
  • Loading branch information
Shakshi3104 authored Nov 15, 2022
2 parents cc0e00d + cd47b54 commit 7815ad3
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 12 deletions.
81 changes: 77 additions & 4 deletions LiTeX/LiveTextCLI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation
import ArgumentParser
import Cocoa
import VisionKit
import Vision

@main
struct Litex: AsyncParsableCommand {
Expand All @@ -18,16 +19,38 @@ struct Litex: AsyncParsableCommand {
discussion: """
LiTeX allows use Live Text as the command line tool and output results to a text file.
""",
version: "1.0.0",
version: "1.1.0",
shouldDisplay: true
)

@Argument(help: "An image filepath.")
var imagefilePath: String
var imageFilepath: String

@Flag(help: "Use VNRecognizeTextRequest of Vision. This option is only available on macOS 13 and newer.")
var useVision: Bool = false
}


// MARK: - Text recognition
extension Litex {
func run() async throws {
if #available(macOS 13.0, *) {
if useVision {
// recognize by Vision
recognizeTextByVision()
} else {
// recognize by Live Text
try? await recognizeTextByLiveText()
}
} else {
// Fallback on earlier versions
recognizeTextByVision()
}
}

// MARK: - recognize text via ImageAnalyzer (Live Text)
@available(macOS 13, *)
func recognizeTextByLiveText() async throws {
#if DEBUG
print("⚙️ Live Text Supported: \(ImageAnalyzer.isSupported)")
print("⚙️ Supported Languages: \(ImageAnalyzer.supportedTextRecognitionLanguages)")
Expand All @@ -40,10 +63,11 @@ extension Litex {
}

// convert image filepath string to URL
let imageURL = URL(filePath: imagefilePath)
let imageURL = URL(filePath: imageFilepath)

// setup ImageAnalyzer
let configuration = ImageAnalyzer.Configuration([.text])
var configuration = ImageAnalyzer.Configuration([.text])
configuration.locales = ["ja-JP", "en-US"]
let analyzer = ImageAnalyzer()

// analyze the image
Expand All @@ -59,14 +83,63 @@ extension Litex {
if analysis.hasResults(for: .text) {
print(analysis.transcript)

#if RELEASE
// output to the text file
let outputFilename = imageURL.deletingPathExtension().lastPathComponent + "_text.txt"
let outputFilepath = imageURL.deletingLastPathComponent().appending(path: outputFilename)

try? analysis.transcript.write(to: outputFilepath, atomically: true, encoding: .utf8)
#endif
} else {
print("Text is not included in the image.")
}
}
}

// MARK: - recognize text via VNRecognizeTextRequest (Vision)
func recognizeTextByVision() {
// convert image filepath string to URL
let imageURL = URL(fileURLWithPath: imageFilepath)

let nsImage = NSImage(contentsOf: imageURL)
guard let cgImage = nsImage?.cgImage else { return }

// setup request
let requestHandler = VNImageRequestHandler(cgImage: cgImage)
let request = VNRecognizeTextRequest(completionHandler: { request, error in
guard let observations = request.results as? [VNRecognizedTextObservation] else {
return
}

let recognizedStrings = observations.compactMap { observation in
return observation.topCandidates(1).first?.string
}

// output to the text file
let recognizedText = recognizedStrings.joined(separator: "\n")
print(recognizedText)

#if RELEASE
let outputFilename = imageURL.deletingPathExtension().lastPathComponent + "_text.txt"
let outputFilepath = imageURL.deletingLastPathComponent().appendingPathComponent(outputFilename)

try? recognizedText.write(to: outputFilepath, atomically: true, encoding: .utf8)
#endif
})

// perform
do {
request.recognitionLanguages = ["ja-JP", "en-US"]
#if DEBUG
let supportedLanguages = try request.supportedRecognitionLanguages()
print("⚙️ Supported Languages: \(supportedLanguages)")
let recognitionLanguages = request.recognitionLanguages
print("⚙️ Recognized Languages: \(recognitionLanguages)")
#endif

try requestHandler.perform([request])
} catch {
print("Unable to perform the request: \(error).")
}
}
}
26 changes: 26 additions & 0 deletions LiTeX/NSImage+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// NSImage+Extension.swift
// litex
//
// Created by MacBook Pro M1 on 2022/11/15.
//

import Cocoa

// MARK: - NSImage extension
// https://qiita.com/HaNoHito/items/2fe95aba853f9cedcd3e
extension NSImage {
var cgImage: CGImage {
var imageRect = NSRect(x: 0, y: 0, width: size.width, height: size.height)
#if swift(>=3.0)
guard let image = cgImage(forProposedRect: &imageRect, context: nil, hints: nil) else {
abort()
}
#else
guard let image = CGImageForProposedRect(&imageRect, context: nil, hints: nil) else {
abort()
}
#endif
return image
}
}
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

**LiTeX** allows use [Live Text](https://support.apple.com/en-us/HT212630) as the command line tool and output results to a text file.

LiTeX requires **macOS 13** (using [ImageAnalyzer of VisionKit](https://developer.apple.com/documentation/visionkit/imageanalyzer))
LiTeX requires **macOS 13** to use Live Text (using [ImageAnalyzer of VisionKit](https://developer.apple.com/documentation/visionkit/imageanalyzer)).
On macOS 12, LiTeX uses [VNRecognizeTextRequest of Vision](https://developer.apple.com/documentation/vision/vnrecognizetextrequest).

<p align="center">
<img src="materials/litex_demo.gif" width=1024>
Expand All @@ -15,12 +16,14 @@ LiTeX requires **macOS 13** (using [ImageAnalyzer of VisionKit](https://develope
## Usage

```sh
USAGE: litex <imagefile-path>
USAGE: litex <image-filepath> [--use-vision]

ARGUMENTS:
<imagefile-path> An image filepath.
<image-filepath> An image filepath.

OPTIONS:
--use-vision Use VNRecognizeTextRequest of Vision. This option is only
available on macOS 13.
--version Show the version.
-h, --help Show help information.
```
Expand All @@ -34,7 +37,7 @@ OPTIONS:

## Requirements

- macOS 13.0+
- macOS 12.0+
- Xcode 14.1+

## Swift Package Dependencies
Expand Down
13 changes: 9 additions & 4 deletions litex.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
CE68ABB5291F4FD1005BB9AC /* LiveTextCLI.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE68ABB4291F4FD1005BB9AC /* LiveTextCLI.swift */; };
CEC86FB32920E38F00412B80 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = CEC86FB22920E38F00412B80 /* ArgumentParser */; };
CEE572142923B31700071D63 /* NSImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE572132923B31700071D63 /* NSImage+Extension.swift */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -28,6 +29,7 @@
CE68ABB4291F4FD1005BB9AC /* LiveTextCLI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTextCLI.swift; sourceTree = "<group>"; };
CE95759A29222E0900E47D13 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
CEDF16032921159600693286 /* litex_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = litex_icon.png; sourceTree = "<group>"; };
CEE572132923B31700071D63 /* NSImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSImage+Extension.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -65,6 +67,7 @@
isa = PBXGroup;
children = (
CE68ABB4291F4FD1005BB9AC /* LiveTextCLI.swift */,
CEE572132923B31700071D63 /* NSImage+Extension.swift */,
);
path = LiTeX;
sourceTree = "<group>";
Expand Down Expand Up @@ -148,6 +151,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CEE572142923B31700071D63 /* NSImage+Extension.swift in Sources */,
CE68ABB5291F4FD1005BB9AC /* LiveTextCLI.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -205,7 +209,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -259,10 +263,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = RELEASE;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
Expand All @@ -274,7 +279,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = WHBF4Z49B6;
ENABLE_HARDENED_RUNTIME = YES;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
};
Expand All @@ -286,7 +291,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = WHBF4Z49B6;
ENABLE_HARDENED_RUNTIME = YES;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
};
Expand Down

0 comments on commit 7815ad3

Please sign in to comment.