Skip to content
This repository has been archived by the owner on Feb 9, 2023. It is now read-only.

Commit

Permalink
Implement qrcode recognizer
Browse files Browse the repository at this point in the history
  • Loading branch information
sfragrance committed Dec 4, 2017
1 parent 62d384c commit ffdfef8
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 41 deletions.
1 change: 1 addition & 0 deletions Captuocr/HistoryViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ extension HistoryWindowController {
}

func initialize() {
viewmodel.itemsource.removeAll()
historyCenter.getRecordList()
.forEach { record in
viewmodel.itemsource.append(record)
Expand Down
4 changes: 4 additions & 0 deletions Captuocr/HistoryWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ class HistoryWindowController: NSWindowController {
bindViewmodel()
initialize()
}

func reload() {
initialize()
}
}
22 changes: 20 additions & 2 deletions Captuocr/MenuInfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,31 @@
"is_separator": false,
"title": "截图识字",
"key": "c",
"selector": "capturePic"
"selector": "capturePic4Txt"
},
{
"is_separator": false,
"title": "选择文件",
"key": "s",
"selector": "selectPic"
"selector": "selectPic4Txt"
},
{
"is_separator": true,
"title": "",
"key": "",
"selector": ""
},
{
"is_separator": false,
"title": "截图识别二维码",
"key": null,
"selector": "capturePic4Qrcode"
},
{
"is_separator": false,
"title": "选择文件识别二维码",
"key": null,
"selector": "selectPic4Qrcode"
},
{
"is_separator": true,
Expand Down
5 changes: 2 additions & 3 deletions Captuocr/MenuInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@ import Foundation
struct MenuInfo {
var is_separator: Bool
var title: String
var key: String
var key: String?
var selector: String
init(_ anyObj: NSDictionary?) throws {
guard
let anyObj = anyObj,
let is_separator = anyObj["is_separator"] as? Bool,
let title = anyObj["title"] as? String,
let key = anyObj["key"] as? String,
let selector = anyObj["selector"] as? String else {
throw NSError()
}
self.is_separator = is_separator
self.title = title
self.key = key
key = anyObj["key"] as? String
self.selector = selector
}
}
22 changes: 1 addition & 21 deletions Captuocr/PreferenceGeneralView.xib
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PreferenceGeneralView" customModule="Captuocr" customModuleProvider="target">
<connections>
<outlet property="checkEnableQRcode" destination="Nml-vx-BvS" id="PON-gB-mlW"/>
<outlet property="checkShowInDock" destination="015-xH-t5U" id="7Lu-Sd-axD"/>
<outlet property="labelNextTime" destination="DwB-5e-C6C" id="e0B-Iz-tYI"/>
<outlet property="stepperFontsize" destination="vpt-tb-oYI" id="GsY-TY-PNB"/>
Expand Down Expand Up @@ -41,7 +40,7 @@
</textField>
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vpt-tb-oYI">
<rect key="frame" x="608" y="320" width="19" height="27"/>
<stepperCell key="cell" continuous="YES" alignment="left" minValue="11" maxValue="30" doubleValue="11" autorepeat="NO" valueWraps="YES" id="WwP-fz-Lt1"/>
<stepperCell key="cell" alignment="left" minValue="11" maxValue="30" doubleValue="11" autorepeat="NO" valueWraps="YES" id="WwP-fz-Lt1"/>
</stepper>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tnD-n9-z6p">
<rect key="frame" x="13" y="373" width="58" height="17"/>
Expand Down Expand Up @@ -69,21 +68,6 @@
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Kuz-px-CL2">
<rect key="frame" x="13" y="263" width="144" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="启用二维码识别(TODO)" id="yUE-Zf-Ll3">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="Nml-vx-BvS">
<rect key="frame" x="158" y="262" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" enabled="NO" inset="2" id="zCH-Oq-54D">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="DwB-5e-C6C">
<rect key="frame" x="179" y="291" width="84" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="下次启动生效" id="adJ-7A-bgp">
Expand All @@ -95,26 +79,22 @@
</subviews>
<constraints>
<constraint firstItem="zOR-Z5-LHY" firstAttribute="centerY" secondItem="015-xH-t5U" secondAttribute="centerY" id="7Ap-aH-IEt"/>
<constraint firstItem="Kuz-px-CL2" firstAttribute="centerY" secondItem="Nml-vx-BvS" secondAttribute="centerY" id="AXy-mJ-7TI"/>
<constraint firstAttribute="trailing" secondItem="vpt-tb-oYI" secondAttribute="trailing" constant="15" id="DAk-dW-huf"/>
<constraint firstItem="RgY-Z2-aCt" firstAttribute="top" secondItem="tnD-n9-z6p" secondAttribute="bottom" constant="6" id="I0o-7B-qZf"/>
<constraint firstItem="M1r-2z-QRp" firstAttribute="top" secondItem="RgY-Z2-aCt" secondAttribute="bottom" constant="22" id="IZr-eO-abg"/>
<constraint firstItem="vpt-tb-oYI" firstAttribute="leading" secondItem="M1r-2z-QRp" secondAttribute="trailing" constant="3" id="Jqp-F2-0J1"/>
<constraint firstItem="015-xH-t5U" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="160" id="Rde-4U-ELY"/>
<constraint firstItem="Nml-vx-BvS" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="160" id="Tdi-p5-hST"/>
<constraint firstItem="DwB-5e-C6C" firstAttribute="centerY" secondItem="015-xH-t5U" secondAttribute="centerY" id="TjS-rs-Ak9"/>
<constraint firstAttribute="trailing" secondItem="RgY-Z2-aCt" secondAttribute="trailing" constant="15" id="UiH-Wu-L0k"/>
<constraint firstItem="RgY-Z2-aCt" firstAttribute="leading" secondItem="tnD-n9-z6p" secondAttribute="leading" id="Ygj-Lw-wG4"/>
<constraint firstItem="M1r-2z-QRp" firstAttribute="centerY" secondItem="vpt-tb-oYI" secondAttribute="centerY" id="Z97-8j-wvz"/>
<constraint firstItem="84i-AH-feA" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="15" id="d54-Hu-Hd3"/>
<constraint firstItem="M1r-2z-QRp" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="160" id="dGD-vK-BEq"/>
<constraint firstItem="015-xH-t5U" firstAttribute="top" secondItem="M1r-2z-QRp" secondAttribute="bottom" constant="15" id="hRo-DQ-a5T"/>
<constraint firstItem="Kuz-px-CL2" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="15" id="jz9-Hh-l0P"/>
<constraint firstItem="tnD-n9-z6p" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="15" id="maU-08-ef8"/>
<constraint firstItem="84i-AH-feA" firstAttribute="centerY" secondItem="M1r-2z-QRp" secondAttribute="centerY" id="nOf-BT-uea"/>
<constraint firstItem="tnD-n9-z6p" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="15" id="q4F-Ww-M1h"/>
<constraint firstItem="DwB-5e-C6C" firstAttribute="leading" secondItem="015-xH-t5U" secondAttribute="trailing" constant="3" id="xFZ-sk-cXm"/>
<constraint firstItem="Nml-vx-BvS" firstAttribute="top" secondItem="015-xH-t5U" secondAttribute="bottom" constant="15" id="xS5-ef-4M1"/>
<constraint firstItem="zOR-Z5-LHY" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="15" id="zRg-Ro-owf"/>
</constraints>
<point key="canvasLocation" x="210.5" y="223.5"/>
Expand Down
88 changes: 73 additions & 15 deletions Captuocr/StatusBarCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class StatusBarCenter {
historyCenter = AppDelegate.container.resolve(HistoryCenter.self)!
popover.behavior = .transient
recognizeVc = RecognizeBoxViewController(nibName: NSNib.Name("RecognizeBox"), bundle: Bundle.main)
recognizeVc.view.frame = NSRect(x: 0, y: 0, width: 834, height: 474)
popover.contentViewController = recognizeVc
menuinfos = minfos
let icon = NSImage(named: NSImage.Name("icons8-text-16"))
Expand All @@ -38,20 +39,26 @@ class StatusBarCenter {
private func buildMenu() {
tarMenu.removeAllItems()
menuinfos.map {
$0.is_separator
? NSMenuItem.separator()
: NSMenuItem(title: $0.title, action: NSSelectorFromString($0.selector), keyEquivalent: $0.key)
}.forEach {
if !$0.isSeparatorItem {
$0.target = self
$0.keyEquivalentModifierMask = NSEvent.ModifierFlags(rawValue: UInt(Int(NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue)))
if $0.is_separator {
return NSMenuItem.separator()
} else {
let menuItem = NSMenuItem()
menuItem.title = $0.title
menuItem.target = self
menuItem.action = NSSelectorFromString($0.selector)
if let hotkey = $0.key, !hotkey.isEmpty {
menuItem.keyEquivalentModifierMask = NSEvent.ModifierFlags(rawValue: UInt(Int(NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue)))
menuItem.keyEquivalent = hotkey
}
return menuItem
}
}.forEach {
tarMenu.addItem($0)
}
}

@objc
func capturePic() {
func capturePic4Txt() {
guard let picPath = Utils.capturePic() else {
return
}
Expand All @@ -60,7 +67,7 @@ class StatusBarCenter {
}

@objc
func selectPic() {
func selectPic4Txt() {
let dialog = NSOpenPanel()
dialog.title = "选择图片"
dialog.directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
Expand All @@ -77,10 +84,39 @@ class StatusBarCenter {
}
}
}

@objc
func capturePic4Qrcode() {
guard let picPath = Utils.capturePic() else {
return
}

recognizeQrcode(picPath: picPath)
}

@objc
func selectPic4Qrcode() {
let dialog = NSOpenPanel()
dialog.title = "选择图片"
dialog.directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
dialog.showsResizeIndicator = true
dialog.showsHiddenFiles = false
dialog.canChooseDirectories = false
dialog.canCreateDirectories = false
dialog.allowsMultipleSelection = false
dialog.allowedFileTypes = ["png", "jpg", "bmp"]

if dialog.runModal() == NSApplication.ModalResponse.OK {
if let result = dialog.url {
recognizeQrcode(picPath: result.path)
}
}
}

@objc
func history() {
if let windowController = AppDelegate.container.resolve(HistoryWindowController.self) {
windowController.reload()
windowController.showWindow(self)
}
}
Expand Down Expand Up @@ -113,9 +149,6 @@ class StatusBarCenter {
Async.main {
self.statusItem.image = NSImage(named: NSImage.Name("icons8-text-16"))
self.statusItem.title = nil
self.recognizeVc = RecognizeBoxViewController(nibName: NSNib.Name("RecognizeBox"), bundle: Bundle.main)
self.recognizeVc.view.frame = NSRect(x: 0, y: 0, width: 834, height: 474)
self.popover.contentViewController = self.recognizeVc
self.recognizeVc.viewmodel.image.value = base64
self.recognizeVc.viewmodel.recognizedText.value = final
self.showPopover()
Expand All @@ -130,9 +163,6 @@ class StatusBarCenter {
Async.main {
self.statusItem.image = NSImage(named: NSImage.Name("icons8-text-16"))
self.statusItem.title = nil
self.recognizeVc = RecognizeBoxViewController(nibName: NSNib.Name("RecognizeBox"), bundle: Bundle.main)
self.recognizeVc.view.frame = NSRect(x: 0, y: 0, width: 834, height: 474)
self.popover.contentViewController = self.recognizeVc
self.recognizeVc.viewmodel.image.value = base64
self.recognizeVc.viewmodel.recognizedText.value = error.localizedDescription
self.showPopover()
Expand All @@ -141,6 +171,34 @@ class StatusBarCenter {
}
}
}

private func recognizeQrcode(picPath: String){
let scanImage = CIImage(contentsOf: URL(fileURLWithPath: picPath))
// Extract QR code features
let context = CIContext()
let options = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options)!
let features = detector.features(in: scanImage!)

// Process each QR code found
var qrtext:String=""
for feature in features as! [CIQRCodeFeature] {
qrtext+=feature.messageString! + "\n"
}
let picData = try? Data(contentsOf: URL(fileURLWithPath: picPath))
if let base64 = picData?.base64EncodedString(){
let record = HistoryRecord()
record.txt = qrtext
record.imgBase64 = base64
record.type = .qrcode
self.historyCenter.addRecord(record: record)

self.recognizeVc.viewmodel.image.value = base64
self.recognizeVc.viewmodel.recognizedText.value = qrtext
self.showPopover()
}

}

private func showPopover() {
if let button = statusItem.button {
Expand Down

0 comments on commit ffdfef8

Please sign in to comment.