123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922 |
- //
- // KMOCRPDFWindowController.swift
- // PDF Reader Pro
- //
- // Created by liujiajie on 2023/11/14.
- //
- import Cocoa
- import PDFKit
- class KMOCRPDFWindowController: NSWindowController, NSWindowDelegate, KMGOCRManagerDelegate, NSPopoverDelegate,NSTextFieldDelegate{
- var resultString: String = ""
- var ocrDictionary: NSMutableDictionary?
- var currentIndexPage: Int = 0
- // {
- // didSet {
- // if PDFView.document.pageCount > currentIndexPage {
- // currentIndexPage = 0
- // self.currentPageLabel.stringValue = "\(currentIndexPage + 1)"
- // // let page = self.PDFView.document.page(at: UInt(currentIndexPage))
- // self.PDFView.go(toPageIndex: currentIndexPage, animated: true)
- // }
- // }
- // }
- var PDFView: CPDFView!
-
- @IBOutlet var prePdfBGView: NSView!
- @IBOutlet var currentPageLabel: NSTextField!
- @IBOutlet var totalPageLabel: NSTextField!
-
- @IBOutlet var pageLabel: NSTextField!
- @IBOutlet var planLabel: NSTextField!
-
- @IBOutlet var ocrCopyButton: NSButton!
-
- @IBOutlet var pageRangeBox: NSComboBox!
- @IBOutlet var planComboBox: NSPopUpButton!
-
- @IBOutlet var progressIndicator: NSProgressIndicator!
- @IBOutlet var progressControl: NSProgressIndicator!
- @IBOutlet var failedBox: NSBox!
- @IBOutlet var failedLabel: NSTextField!
-
- @IBOutlet var cancelButton: NSButton!
- @IBOutlet var startButton: NSButton!
-
- @IBOutlet var languageLabel: NSTextField!
- @IBOutlet var ocrResultLabel: NSTextField!
-
- @IBOutlet var languageButton: NSButton!
- @IBOutlet var txtTextView: NSTextView!
-
- @IBOutlet var deleteButton: NSButton!
-
- @IBOutlet var emptyBox: NSBox!
-
- @IBOutlet var emptyLabel: NSTextField!
-
- var errorOCRArrays: Array<Any>?
-
- var pageIndexs: Array<Any>?
-
- var password: String = ""
- var pathFile: String = ""
-
- var pdfDocument: CPDFDocument?
-
- @IBOutlet var saveButton: NSButton!
- @IBOutlet var box1: NSBox!
- @IBOutlet var boxLabel1: NSTextField!
- @IBOutlet var previewLabel: NSTextField!
- @IBOutlet var savePDFButton: NSButton!
-
- var ocrCurrentIndex: Int = 0
- var appleOCRManger: KMGOCRManager?
- var googleOCRManger: KMGOCRManager?
-
- var savedFileName: String = ""
-
- private var _fileAttri: KMFileAttribute?
-
- func getOCRResrultsFolderPath() -> String {
- var path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last
- path?.append("/")
- path?.append(Bundle.main.bundleIdentifier!)
- if (FileManager.default.fileExists(atPath: path!) == false) {
- try?FileManager.default.createDirectory(atPath: path!, withIntermediateDirectories: false)
- }
-
- path?.append("/")
- path?.append("OCR_Resrults")
-
- return path!
- }
-
- convenience init(cpdfDocument: CPDFDocument, pwd: String?) {
- self.init(windowNibName: "KMOCRPDFWindowController")
- self.pdfDocument = cpdfDocument
- self.password = pwd ?? ""
- let url: URL? = cpdfDocument.documentURL
- let lastPathComponent = url?.deletingPathExtension()
- if let str = lastPathComponent?.lastPathComponent {
- if str.count > 0 {
- self.pathFile = str
- }else {
- self.pathFile = NSLocalizedString("Untitled", comment: "")
- }
- } else {
- self.pathFile = NSLocalizedString("Untitled", comment: "")
- }
-
- self._fileAttri = KMFileAttribute()
- self._fileAttri?.password = self.pdfDocument?.password ?? ""
- if self.pdfDocument?.documentURL != nil && self.pdfDocument?.documentURL.path != nil{
- self._fileAttri?.filePath = self.pdfDocument?.documentURL.path ?? ""
- }else {
- self._fileAttri?.filePath = ""
- }
- }
-
- convenience init(filePath: String, pwd: String?) {
- self.init(windowNibName: "KMOCRPDFWindowController")
- self.password = pwd ?? ""
- let pathExtension = filePath.lastPathComponent.customPathExtension
- if pathExtension.count > 0{
- if pathExtension.lowercased() == "pdf" {
- pdfDocument = CPDFDocument(url: URL(fileURLWithPath: filePath))
- } else {
- if let image = NSImage(contentsOf: URL(fileURLWithPath: filePath)) {
- self.pdfDocument = CPDFDocument()
- _ = pdfDocument?.km_insertPage(image.size, withImage: filePath, at: pdfDocument?.pageCount ?? 0)
- }
- }
- }
- self.pathFile = filePath.lastPathComponent.deletingPathExtension
-
- self._fileAttri = KMFileAttribute()
- self._fileAttri?.password = self.pdfDocument?.password ?? ""
- self._fileAttri?.filePath = self.pdfDocument?.documentURL.path ?? ""
- }
- deinit {
- NotificationCenter.default.removeObserver(self)
- releaseSomething()
- }
-
- func releaseSomething() {
- KMGOCRManager.default().delegate = nil
- appleOCRManger?.cancelRecognition()
- appleOCRManger?.delegate = nil
- googleOCRManger?.cancelRecognition()
- googleOCRManger?.delegate = nil
- self.PDFView.document = nil
- }
- override func windowDidLoad() {
- super.windowDidLoad()
- let preView: CPDFView = CPDFView(frame: self.prePdfBGView.bounds)
- self.prePdfBGView.addSubview(preView)
- self.PDFView = preView
- self.PDFView.setDisplay(.singlePage) //self.displayViewMode = CPDFDisplayViewSinglePageContinuous;
-
- self.pageLabel.stringValue = NSLocalizedString("Page Range", comment: "")
- self.planLabel.stringValue = NSLocalizedString("OCR Plan", comment: "")
-
- self.planComboBox.removeAllItems()
- self.planComboBox.addItems(withTitles: [NSLocalizedString("Plan 1 (Online)", comment: ""), NSLocalizedString("Plan 2 (Offline)", comment: "")])
- let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
- if plan == 0 {
- KMGOCRManager.default().ocrType = .google
- self.planComboBox.selectItem(at: 0)
- } else {
- KMGOCRManager.default().ocrType = .apple
- self.planComboBox.selectItem(at: 1)
- }
- self.pageRangeBox.addItems(withObjectValues: [NSLocalizedString("All Pages", comment: ""), NSLocalizedString("Current Page", comment: ""), NSLocalizedString("Odd Pages Only", comment: ""), NSLocalizedString("Even Pages Only", comment: ""), NSLocalizedString("e.g. 1,3-5,10", comment: "")])
- self.pageRangeBox.placeholderString = NSLocalizedString("e.g. 1,3-5,10", comment: "")
-
- self.pageRangeBox.selectItem(at: 0)
- self.pageRangeBox.isEditable = false
- if self.pageRangeBox.indexOfSelectedItem == 4 {
- self.window?.makeFirstResponder(self.pageRangeBox)
- self.pageRangeBox.stringValue = ""
- self.pageRangeBox.isEditable = true
- }
- self.emptyLabel.stringValue = NSLocalizedString("Recognize text from Image-based or Scanned PDF with OCR", comment: "")
- self.failedLabel.stringValue = NSLocalizedString("OCR failed. Please try to change the OCR Plan to \"Plan 2 (Offline)\"", comment: "")
- self.txtTextView.textColor = NSColor.textColor
- self.txtTextView.enclosingScrollView?.autohidesScrollers = true
- self.ocrResultLabel.stringValue = NSLocalizedString("OCR Results", comment: "")
- self.ocrCopyButton?.toolTip = KMLocalizedString("Copy and edit text from documents with OCR.", nil)
- self.deleteButton?.toolTip = NSLocalizedString("Delete", comment: "")
- self.deleteButton?.title = NSLocalizedString("Delete", comment: "")
- self.ocrCopyButton?.title = NSLocalizedString("Copy", comment: "")
- self.errorOCRArrays = []
- self.pageIndexs = []
- self.ocrCopyButton.isEnabled = false
- self.deleteButton.isEnabled = false
- self.saveButton.isEnabled = false
- self.savePDFButton.isEnabled = false
- self.boxLabel1.stringValue = NSLocalizedString("Settings", comment: "")
- self.previewLabel.stringValue = NSLocalizedString("Preview", comment: "")
-
- self.saveButton.title = NSLocalizedString("Save as TXT", comment: "")
- self.savePDFButton.title = NSLocalizedString("Save as PDF", comment: "")
- self.saveButton.toolTip = NSLocalizedString("Export as a searchable PDF or text file.", comment: "")
- self.savePDFButton.toolTip = NSLocalizedString("Export as a searchable PDF or text file.", comment: "")
-
- self.cancelButton.title = NSLocalizedString("Cancel", comment: "")
- self.startButton.title = NSLocalizedString("OCR", comment: "")
- self.languageLabel.stringValue = NSLocalizedString("Select OCR Language:", comment: "")
-
- self.updateLanguageButton((KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]))
- NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedLanguagesChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedLanguagesChangeNotification"), object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedPlanChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedPlanChangeNotification"), object: nil)
-
- self.progressControl.isHidden = true
- emptyBox.isHidden = false
- failedBox.isHidden = true
-
- self.PDFView.document = self.pdfDocument
- self.PDFView.go(toPageIndex: self.currentIndexPage, animated: false)
- self.PDFView.autoScales = true
- self.reloadPDFData()
- if !(self.pdfDocument?.isLocked ?? false) && ((self.pdfDocument?.unlock(withPassword: self.password)) != nil) {
-
- } else {
- if let docUrl = self.pdfDocument?.documentURL {
- KMBaseWindowController.checkPassword(url: self.pdfDocument!.documentURL, type: .owner) { success, pwd in
- if success {
- self.pdfDocument?.unlock(withPassword: pwd)
- self.password = pwd
- self.reloadPDFData()
- } else {
- self.close()
- }
- }
- } else {
- KMPrint("document url is nil")
- }
- }
-
- NotificationCenter.default.addObserver(self, selector: #selector(PDFViewDocumentChangedNotification(notification:)), name: NSNotification.Name.CPDFViewPageChanged, object: nil)
- }
-
- func windowShouldClose(_ sender: NSWindow) -> Bool {
- close()
- return true
- }
-
- override func close() {
- releaseSomething()
- if ((self.window?.isSheet) != nil) {
- // self.km_endSheet()
- self.window?.sheetParent?.endSheet(self.window!)
- } else {
- super.close()
- }
- }
-
- func reloadPDFData() { // 隐藏PDFView滑动条
- self.PDFView.documentView()?.enclosingScrollView?.hasVerticalScroller = false
- self.PDFView.documentView()?.enclosingScrollView?.hasHorizontalScroller = false
- let pageCount: Int = Int(self.pdfDocument?.pageCount ?? 0)
- let currentPageIndex = self.pdfDocument?.index(for: self.PDFView.currentPage())
- self.currentPageLabel.stringValue = "\((currentPageIndex ?? 0) + 1)"
- self.totalPageLabel.stringValue = "/ \(pageCount)"
- }
- //MARK: KMOCRSelectedLanguagesChangeNotification
- @objc func OCRSelectedLanguagesChangeNotification(notification: NSNotification) {
- if let selectedLanguages = notification.object as? [String] {
- updateLanguageButton(selectedLanguages)
- }
- }
-
- @objc func OCRSelectedPlanChangeNotification(notification: NSNotification) {
- let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
- if plan == 0 {
- self.planComboBox.selectItem(at: 0)
- } else {
- self.planComboBox.selectItem(at: 1)
- }
- KMGOCRManager.default().selectedLanguages = NSMutableArray()
- updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
- }
- @objc func PDFViewDocumentChangedNotification(notification: NSNotification) {
- let pageIndex = self.PDFView.currentPageIndex+1
- self.currentPageLabel.stringValue = "\(pageIndex)"
- }
-
- func updateLanguageButton(_ languages: [String]?) {
- if languages?.count ?? 0 < 1 {
- self.languageButton.title = NSLocalizedString("Auto Detection", comment: "")
- return
- }
- var languageName: String? = nil
- if languages?.count ?? 0 > 0 {
- for i in 0..<(languages?.count ?? 0) {
- let language = languages?[i]
- if i == 0 {
- languageName = language
- } else {
- languageName = languageName?.appendingFormat(",%@", language ?? "")
- }
- }
- } else {
- languageName = ""
- }
-
- self.languageButton.title = languageName ?? ""
- }
- func imageRep(withSize size: NSSize, scale: CGFloat, drawingHandler: (NSRect) -> Void) -> Any? {
- let bmpImageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(size.width * scale), pixelsHigh: Int(size.height * scale), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .calibratedRGB, bitmapFormat: .alphaFirst, bytesPerRow: 0, bitsPerPixel: 0)
- // bmpImageRep?.bitmapImageRepByRetaggingWithColorSpace = .sRGB
- bmpImageRep?.size = size
- NSGraphicsContext.saveGraphicsState()
- NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: bmpImageRep!)
- // drawingHandler(.zero, size)
- drawingHandler(NSRect(origin: NSZeroPoint, size: size))
- NSGraphicsContext.restoreGraphicsState()
- return bmpImageRep
- }
- func bitmapImage(withSize size: NSSize, drawingHandler: (NSRect) -> Void) -> NSImage? {
- let image = NSImage(size: size)
- let scale = KMImageScale
- image.addRepresentation(imageRep(withSize: size, scale: scale, drawingHandler: drawingHandler) as! NSBitmapImageRep)
- return image
- }
- func thumbnail(with page: CPDFPage) -> NSImage? {
- let bounds = page.bounds(for: .cropBox)
- var pageSize = bounds.size
- var scale: CGFloat = 1.0
- var thumbnailSize: NSSize
- var pageRect = NSZeroRect
- var image: NSImage?
- let aSize = pageSize.width
- if page.rotation % 180 == 90 {
- pageSize = NSSize(width: pageSize.height, height: pageSize.width)
- }
-
- if aSize > 0.0 {
- if pageSize.height > pageSize.width {
- thumbnailSize = NSSize(width: round(aSize * pageSize.width / pageSize.height), height: aSize)
- } else {
- thumbnailSize = NSSize(width: aSize, height: round(aSize * pageSize.height / pageSize.width))
- }
- let kKMMaxPixelsLimit = 75000000
- let totalPixelNumber = Int((thumbnailSize.width * KMImageScale) * (thumbnailSize.height * KMImageScale))
- if totalPixelNumber >= kKMMaxPixelsLimit {
- let sizeScale = sqrt(Float(kKMMaxPixelsLimit - 1000) / Float(totalPixelNumber))
- thumbnailSize = NSSize(width: floor(thumbnailSize.width * CGFloat(sizeScale)), height: floor(thumbnailSize.height * CGFloat(sizeScale)))
- }
- scale = max(thumbnailSize.width / pageSize.width, (thumbnailSize.height) / pageSize.height)
- } else {
- thumbnailSize = NSSize(width: pageSize.width, height: pageSize.height)
- }
-
- if thumbnailSize.width.isNaN || thumbnailSize.height.isNaN || thumbnailSize.width == 0.0 || thumbnailSize.height == 0.0 {
- thumbnailSize = NSSize(width: 186.0, height: 256.0)
- }
-
- pageRect.size = thumbnailSize
-
- image = bitmapImage(withSize: thumbnailSize) { rect in
- NSGraphicsContext.current?.imageInterpolation = .high
-
- NSGraphicsContext.saveGraphicsState()
- NSColor.white.setFill()
- pageRect.fill()
- NSGraphicsContext.restoreGraphicsState()
-
- if abs(scale - 1.0) > 0.0 {
- let transform = NSAffineTransform()
- transform.scale(by: scale)
- transform.concat()
- }
-
- page.draw(with: .cropBox, to: (NSGraphicsContext.current?.cgContext as! CGContext))
-
- NSGraphicsContext.current?.imageInterpolation = .default
- }
-
- return image
- }
- func savedName() -> String {
- var resultArrays: Array<Any> = []
- var ocrIndexArrays: Array<Any> = []
-
- let sortedKeys = self.ocrDictionary?.allKeys.sorted(by: {
- ($0 as? String)?.compare($1 as? String ?? "") == .orderedAscending
- })
- for i in 0 ..< (sortedKeys?.count ?? 0) {
- let keyS = sortedKeys?[i]
- ocrIndexArrays.append(keyS as Any)
- resultArrays.append(self.ocrDictionary?[keyS as Any] as Any)
- }
-
- var fileName = self.savedFileName
- if fileName.count > 50 {
- fileName = String(fileName.prefix(50))
- }
-
- if sortedKeys?.count ?? 0 > 1 {
- fileName = "\(self.pathFile) Pages \(fileName) _OCR"
- } else {
- fileName = "\(self.pathFile) Page \(fileName) _OCR"
- }
-
- var returnName = fileName
- switch self.pageRangeBox.indexOfSelectedItem {
- case 0:
- returnName = "\(self.pathFile)_OCR"
- case 2:
- returnName = "\(self.pathFile) Odd_OCR"
- case 3:
- returnName = "\(self.pathFile) Even_OCR"
- default:
- break
- }
-
- return returnName
- }
- func savePDF() {
- var resultArrays: Array<Any> = []
- var ocrIndexArrays: Array<Any> = []
- let sortedKeys = self.ocrDictionary?.allKeys.sorted(by: { ($0 as? String)?.compare($1 as? String ?? "") == .orderedAscending })
- for i in 0 ..< (sortedKeys?.count ?? 0) {
- let keyS = sortedKeys?[i]
- ocrIndexArrays.append(keyS as Any)
- resultArrays.append(self.ocrDictionary?[keyS as Any] as Any)
- }
-
- let fileName = self.savedFileName
-
- let saveAccessCtr = KMSavePanelAccessoryController()
- let outputSavePanel = NSSavePanel()
- outputSavePanel.allowedFileTypes = ["pdf"]
- outputSavePanel.nameFieldStringValue = fileName
- outputSavePanel.accessoryView = saveAccessCtr.view
- outputSavePanel.beginSheetModal(for: self.window!) { [self] (result) in
- if result == .OK {
-
- let savePDFPath = outputSavePanel.url?.path ?? ""
- if !FileManager.default.fileExists(atPath: getOCRResrultsFolderPath()) {
- try? FileManager.default.createDirectory(atPath: getOCRResrultsFolderPath(), withIntermediateDirectories: false, attributes: nil)
- }
- var imagePath = [Any]()
- for i in 0..<ocrIndexArrays.count {
- let rPath = (getOCRResrultsFolderPath() as NSString).appendingPathComponent("\(i).png")
- if let index = ocrIndexArrays[i] as? NSNumber, let page = self.pdfDocument?.page(at: UInt(index.intValue)), let image = self.thumbnail(with: page) {
- try? image.tiffRepresentation?.write(to: URL(fileURLWithPath: rPath), options: .atomic)
- }
- imagePath.append(rPath)
- }
-
- KMGOCRManager.default().createPDFFile(savePDFPath, imagePaths: imagePath, results: resultArrays, scale: KMImageScale)
- if saveAccessCtr.openAutomaticButton.state == .on {
- self.cancelButtonAction("")
- NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePDFPath), display: true, completionHandler: {document,documentWasAlreadyOpen,error in
-
- })
- } else {
- self.viewFileAtFinder(savePDFPath)
- }
- }
- }
- }
- func viewFileAtFinder(_ fileName: String) {
- let workspace = NSWorkspace.shared
- let url = URL(fileURLWithPath: fileName)
- workspace.activateFileViewerSelecting([url])
- }
- func saveText() {
- let sortedKeys = self.ocrDictionary?.allKeys.sorted(by: { ($0 as? String)?.compare($1 as? String ?? "") == .orderedAscending })
- let fileName = self.savedFileName
-
- let saveAccessCtr = KMSavePanelAccessoryController()
- let outputSavePanel = NSSavePanel()
- outputSavePanel.allowedFileTypes = ["txt"]
- outputSavePanel.nameFieldStringValue = fileName
- outputSavePanel.accessoryView = saveAccessCtr.view
- outputSavePanel.beginSheetModal(for: self.window!) { (result) in
- if result == .OK {
- let outputURL = outputSavePanel.url
- try? self.txtTextView?.string.write(to: outputURL!, atomically: true, encoding: .utf8)
- if saveAccessCtr.openAutomaticButton?.state == .on {
- NSWorkspace.shared.open(outputURL!)
- } else {
- self.viewFileAtFinder(outputURL?.path ?? "")
- }
- }
- }
- }
- func fileNameWithNums(_ nums: [NSNumber]) -> String {
- var fileName: String? = nil
- if nums.count > 0 {
- if nums.count == 1 {
- if let num = nums.first {
- let idx = num.intValue + 1
- return "\(idx)"
- }
- }
- var sortIndex = NSSet()
- for num in nums {
- let idx = num.intValue + 1
- // sortIndex.insert(NSNumber(value: idx))
- sortIndex.adding(NSNumber(value: idx))
- }
- let sort = NSSortDescriptor(key: nil, ascending: true)
- let sortDesc = [sort]
- let sortArray = sortIndex.sortedArray(using: sortDesc)
-
- var a = 0
- var b = 0
- if sortArray.count == 1 {
- let num: NSNumber = sortArray.last as! NSNumber
- fileName = "\(num.intValue)"
- return fileName ?? ""
- }
-
- for i in 0 ..< sortArray.count {
- let num = sortArray[i]
- if fileName?.count ?? 0 > 0 {
- if (num as AnyObject).intValue == b + 1 {
- b = (num as AnyObject).intValue
- if (i == sortArray.count - 1) {
- fileName = (fileName ?? "") + "\(a)-\(b)"
- }
- } else {
- if a == b {
- fileName = (fileName ?? "") + "\(a),"
- } else {
- fileName = (fileName ?? "") + "\(a)-\(b),"
- }
- a = (num as AnyObject).intValue
- b = (num as AnyObject).intValue
- if (i == sortArray.count - 1) {
- fileName = (fileName ?? "") + "\(a)"
- }
- }
- } else {
- fileName = ""
- a = (num as AnyObject).intValue
- b = (num as AnyObject).intValue
- }
- }
- return fileName ?? ""
- }
- return ""
- }
-
- @IBAction func cancelButtonAction(_ sender: Any) {
- if FileManager.default.fileExists(atPath: getOCRResrultsFolderPath()) {
- try? FileManager.default.removeItem(atPath: getOCRResrultsFolderPath())
- }
- KMGOCRManager.default().cancelRecognition()
- self.close()
- }
- @IBAction func startButtonAction(_ sender: Any) {
- self.ocrCurrentIndex = 0
- txtTextView.string = ""
- ocrDictionary = NSMutableDictionary()
- let pdfDocument = self.pdfDocument
- errorOCRArrays?.removeAll()
- pageIndexs?.removeAll()
- if self.pageRangeBox.indexOfSelectedItem == 0 {
- for i in 0..<(pdfDocument?.pageCount ?? 0) {
- pageIndexs?.append(NSNumber(value: i))
- }
- } else if self.pageRangeBox.indexOfSelectedItem == 1 {
- let page = PDFView.currentPage()
- let pageIndex = PDFView.document?.index(for: page)
- pageIndexs?.append(NSNumber(value: pageIndex!))
- } else if self.pageRangeBox.indexOfSelectedItem == 2 {
- for i in 0..<(pdfDocument?.pageCount ?? 0) where i % 2 == 0 {
- pageIndexs?.append(NSNumber(value: i))
- }
- } else if self.pageRangeBox.indexOfSelectedItem == 3 {
- for i in 0..<(pdfDocument?.pageCount ?? 0) where i % 2 != 0 {
- pageIndexs?.append(NSNumber(value: i))
- }
- } else {
- var attribute = self._fileAttri
- if attribute == nil {
- attribute = KMFileAttribute()
- self._fileAttri = attribute
-
- attribute?.password = self.pdfDocument?.password ?? ""
- attribute?.filePath = self.pdfDocument?.documentURL.path ?? ""
- }
- // attribute.pdfDocument = pdfDocument
-
- attribute?.bAllPage = false
- attribute?.pagesType = .custom
- attribute?.pagesString = self.pageRangeBox.stringValue
- let selectPages = attribute?.fetchSelectPages() ?? []
- if selectPages.count > 0 {
- for num in selectPages {
- pageIndexs?.append(NSNumber(value: num - 1))
- }
- }
- }
- batchesOCR()
- }
- func batchesOCR() {
- savedFileName = savedName()
- let intervalOCR: UInt = 10
- let selctPageImages: NSMutableArray = NSMutableArray()
-
- for i in 0..<intervalOCR {
- if ocrCurrentIndex + Int(i) >= self.pageIndexs?.count ?? 0 { continue }
-
- autoreleasepool {
- let index = self.pageIndexs?[self.ocrCurrentIndex + Int(i)] as! NSNumber
- let page = self.pdfDocument?.page(at: UInt(index.intValue))
- let img: NSImage = thumbnail(with: page!)!
- let data: NSData = img.tiffRepresentation! as NSData
- selctPageImages.add(data)
- }
- }
-
- if selctPageImages.count < 1 && ocrCurrentIndex == 0 {
- let alert = NSAlert()
- alert.alertStyle = .critical
- alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
-
- if #available(OSX 10.11, *) {
- alert.beginSheetModal(for: self.window!, completionHandler: nil)
- } else {
- alert.runModal()
- }
- }
-
- if selctPageImages.count < 1 {
- return
- }
-
- if appleOCRManger != nil {
- appleOCRManger?.cancelRecognition()
- appleOCRManger?.delegate = nil
- appleOCRManger = nil
- }
-
- if googleOCRManger != nil {
- googleOCRManger?.cancelRecognition()
- googleOCRManger?.delegate = nil
- googleOCRManger = nil
- }
-
- ocrCopyButton.isEnabled = false
- saveButton.isEnabled = false
- savePDFButton.isEnabled = false
- startButton.isEnabled = false
- deleteButton.isEnabled = false
- progressControl.isHidden = false
- progressControl.startAnimation(nil)
- emptyBox.isHidden = true
- failedBox.isHidden = true
-
- DispatchQueue.main.async {
- let languages = KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageCodeKey)
- if self.planComboBox.indexOfSelectedItem == 0 {
- self.googleOCRManger = KMGOCRManager()
- self.googleOCRManger?.ocrType = .google
- self.googleOCRManger?.delegate = self
- self.googleOCRManger?.recognitionImages((selctPageImages as! [Any]), withLanguages: languages as? [Any])
- } else {
- self.appleOCRManger = KMGOCRManager()
- self.appleOCRManger?.ocrType = .apple
- self.appleOCRManger?.delegate = self
- self.appleOCRManger?.recognitionImages((selctPageImages as! [Any]), withLanguages: languages as? [Any])
- }
- }
- }
- @IBAction func planSelectButtonAction(_ sender: NSPopUpButton) {
- let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
- if plan != sender.indexOfSelectedItem {
- KMGOCRManager.default().selectedLanguages = NSMutableArray()
- updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
- }
- UserDefaults.standard.set(sender.indexOfSelectedItem, forKey: "KMOCRCurrentPlanKey")
- UserDefaults.standard.synchronize()
- if self.planComboBox.indexOfSelectedItem == 0 {
- KMGOCRManager.default().ocrType = .google
- } else {
- KMGOCRManager.default().ocrType = .apple
- }
- NotificationCenter.default.post(name: NSNotification.Name("KMOCRSelectedPlanChangeNotification"), object: nil)
- }
- @IBAction func languageButtonAction(_ sender: Any) {
- let popover = NSPopover()
- popover.delegate = self
- popover.contentViewController = KMLanguageViewController(nibName: "KMLanguageViewController", bundle: Bundle.main)
- popover.animates = true
- popover.behavior = .transient
- popover.show(relativeTo: (sender as! NSView).bounds, of: sender as! NSView, preferredEdge: .minX)
- }
- @IBAction func helpButtonAction(_ sender: Any) {
- let helpController = NSViewController()
- let textView = NSTextView(frame: NSRectToCGRect(NSMakeRect(0, 0, 300.0, 50.0)))
- textView.backgroundColor = NSColor.clear
- textView.isEditable = false
- textView.layer?.cornerRadius = 6
- let tStrAuto = NSLocalizedString("Choose automatic language detection for better OCR results.", comment: "")
- textView.alignment = .justified
- textView.string = "\n\(tStrAuto)"
- helpController.view = textView
- let popover = NSPopover()
- popover.delegate = self
- popover.contentViewController = helpController
- popover.animates = true
- popover.behavior = .transient
- popover.show(relativeTo: (sender as! NSView).bounds, of: sender as! NSView, preferredEdge: .minY)
- }
- @IBAction func buttonItemClick_CopyTxt(_ sender: NSButton) {
- let pasteboard = NSPasteboard.general
- pasteboard.clearContents()
- let str: NSPasteboardWriting = self.txtTextView.string as NSPasteboardWriting
- pasteboard.writeObjects([str])
- let _ = CustomAlertView.alertView(message: NSLocalizedString("Copy successful!", comment: ""), fromView: sender.superview!, withStyle: .black)
- }
- @IBAction func buttonItemClick_Delete(_ sender: NSButton) {
- ocrCopyButton.isEnabled = false
- saveButton.isEnabled = false
- savePDFButton.isEnabled = false
- deleteButton.isEnabled = false
- emptyBox.isHidden = false
- failedBox.isHidden = true
- resultString = ""
- txtTextView.string = ""
- ocrDictionary = NSMutableDictionary()
- }
- @IBAction func boxItemClicked_PageRange(_ sender: NSButton) {
- if 4 != pageRangeBox.indexOfSelectedItem {
- self.window?.makeFirstResponder(self)
- pageRangeBox.isEditable = false
- } else {
- pageRangeBox.stringValue = ""
- pageRangeBox.isEditable = true
- self.window?.makeFirstResponder(pageRangeBox)
- }
- }
-
- @IBAction func nextButtonAction(_ sender: NSButton) {
- self.PDFView.goToNextPage(nil)
- self.reloadPDFData()
- }
- @IBAction func previousButtonAction(_ sender: NSButton) {
- self.PDFView.goToPreviousPage(nil)
- self.reloadPDFData()
- }
- @IBAction func buttonClicked_SaveButton(_ sender: NSButton) {
- self.saveText()
- }
- @IBAction func savePDFButtonAction(_ sender: NSButton) {
- self.savePDF()
- }
- func controlTextDidEndEditing(_ notification: Notification) {
- guard let textField = notification.object as? NSTextField else { return }
- if textField == currentPageLabel {
- let index = Int(currentPageLabel.stringValue) ?? 0
- let pageCount = pdfDocument?.pageCount
- let currentPageIndex = pdfDocument?.index(for: PDFView.currentPage())
- if index > 0 && index <= pageCount ?? 0 {
- PDFView.go(to: pdfDocument?.page(at: UInt(index-1))!)
- reloadPDFData()
- } else {
- currentPageLabel.stringValue = "\((currentPageIndex ?? 0)+1)"
- }
- }
- }
- func controlTextDidChange(_ notification: Notification) {
- guard let textField = notification.object as? NSTextField else { return }
- if textField == currentPageLabel {
- let string = textField.formatter?.string(for: NSNumber(value: Int(textField.stringValue) ?? 0))
- textField.stringValue = string ?? ""
- }
- }
- func popoverDidClose(_ notification: Notification) {
-
- }
-
- func gocrManagerDidStartOCR(_ manager: KMGOCRManager!) {
-
- }
- //MARK: KMGOCRManagerDelegate
- func gocrManagerDidFinishOCR(_ manager: KMGOCRManager!) {
- self.batchesOCR()
- }
- func gocrManager(_ manager: KMGOCRManager!, didCancelOCRImageAt index: Int) {
-
- }
- func gocrManager(_ manager: KMGOCRManager!, didStartOCRImageAt index: Int) {
- DispatchQueue.main.async {
- self.pageRangeBox.isEnabled = false
- self.languageButton.isEnabled = false
- self.planComboBox.isEnabled = false
- }
- }
- func gocrManager(_ manager: KMGOCRManager!, didFinishOCRImageAt index: Int, results: [KMGOCRResult]!) {
- self.dealWithResults(results, OCRImageAtIndex: index)
- }
- func gocrManager(_ manager: KMGOCRManager!, didFailureOCRImageAt index: Int, error: Error!) {
- let pagenum = self.pageIndexs?[index] as! NSNumber
- if (error != nil) {
- self.errorOCRArrays?.append(pagenum)
- }
- self.dealWithResults([], OCRImageAtIndex: index)
- }
-
- func dealWithResults(_ rlts: [KMGOCRResult]?, OCRImageAtIndex index: Int) {
- if index >= self.pageIndexs?.count ?? 0 {
- return
- }
-
- let key = self.pageIndexs?[self.ocrCurrentIndex] as! NSNumber
-
- if ocrDictionary == nil {
- ocrDictionary = NSMutableDictionary()
- }
-
- ocrDictionary?.setObject(rlts as Any, forKey: key)
-
- let sortedKeys = self.ocrDictionary?.allKeys.sorted(by: { ($0 as! NSNumber).compare($1 as! NSNumber) == .orderedAscending })
- var textString = ""
-
- for key in sortedKeys! {
- let results: Array<KMGOCRResult> = self.ocrDictionary?.object(forKey: key) as! Array<KMGOCRResult>
- var rStr = ""
- if results.count > 0 {
- rStr = results[0].text
- }
- if textString.count > 0 {
- textString += "\n\n"
- }
- textString += String(format: NSLocalizedString("Page %ld", comment: ""), (key as! NSNumber).intValue + 1)
- textString += "\n"
- textString += rStr
- }
-
- self.txtTextView.string = textString
- self.resultString = textString
-
- self.ocrCurrentIndex += 1
-
- if self.ocrCurrentIndex >= (self.pageIndexs?.count ?? 0) - 1 {
- self.progressControl.stopAnimation(nil)
- self.progressControl.isHidden = true
- self.saveButton.isEnabled = true
- self.savePDFButton.isEnabled = true
- self.ocrCopyButton.isEnabled = true
- self.deleteButton.isEnabled = true
- self.startButton.isEnabled = true
- DispatchQueue.main.async {
- self.pageRangeBox.isEnabled = true
- self.languageButton.isEnabled = true
- self.planComboBox.isEnabled = true
- }
- if appleOCRManger != nil {
- appleOCRManger?.cancelRecognition()
- appleOCRManger?.delegate = nil
- appleOCRManger = nil
- }
-
- if googleOCRManger != nil {
- googleOCRManger?.cancelRecognition()
- googleOCRManger?.delegate = nil
- googleOCRManger = nil
- }
-
- KMGOCRManager.default().delegate = nil
-
- if self.errorOCRArrays?.count ?? 0 < 1 {
-
- } else if self.errorOCRArrays?.count == self.pageIndexs?.count {
- if KMGOCRManager.default().ocrType == .google {
- self.failedLabel.stringValue = NSLocalizedString("OCR failed.Please try to change the OCR Plan to \"Plan 2 (Offline)\"", comment: "")
- self.failedBox.isHidden = false
- } else {
- let alert = NSAlert()
- alert.alertStyle = NSAlert.Style.critical
- alert.messageText = ""
- if #available(macOS 10.15, *) {
- alert.informativeText = NSLocalizedString("Unable to perform OCR on this document. Please try again later.", comment: "")
- } else {
- alert.informativeText = NSLocalizedString("OCR failed, please try again. Note: OCR Plan 2(Offline) is supported in macOS 10.15+.", comment: "")
- self.failedLabel.stringValue = NSLocalizedString("OCR failed, please try again. Note: OCR Plan 2(Offline) is supported in macOS 10.15+.", comment: "")
- self.failedBox.isHidden = false
- }
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
- let response = alert.runModal()
- if response == NSApplication.ModalResponse.alertFirstButtonReturn {
-
- }
- }
- } else {
- var contextString = String(format: "%@", NSLocalizedString("Some problems occurred during the last operation:", comment: ""))
- contextString += "\n"
-
- if self.errorOCRArrays?.count ?? 0 > 1 {
- contextString += NSLocalizedString("Pages", comment: "")
- } else {
- contextString += NSLocalizedString("Page", comment: "")
- }
- if self.errorOCRArrays?.count ?? 0 > 0 {
- contextString += String(format: ": %@", self.fileNameWithNums(self.errorOCRArrays as! Array<NSNumber>))
- }
-
- let alert = NSAlert()
- alert.alertStyle = NSAlert.Style.critical
- alert.messageText = NSLocalizedString("Completed", comment: "")
- alert.informativeText = contextString
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
- let response = alert.runModal()
- if response == NSApplication.ModalResponse.alertFirstButtonReturn {
-
- }
- }
- }
- }
-
-
- }
|