123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710 |
- //
- // KMGOCRManager.m
- //
- //
- //
- //
- //
- #import "KMGOCRManager.h"
- #import <PDF_Reader_Pro-Swift.h>
- #import <Vision/VNRecognizeTextRequest.h>
- #import <Vision/VNRequestHandler.h>
- #import <Vision/VNObservation.h>
- #define KMImageScale 4.0
- //#import "KMOCRPreferences.h" //恢复OCR架上版本样式
- /*
- https://cloud.google.com/vision/reference/rest/v1/images/annotate#AnnotateImageResponse
-
- languageHints[]
-
- List of languages to use for TEXT_DETECTION. In most cases, an empty value yields the best results since it enables automatic language detection. For languages based on the Latin alphabet, setting languageHints is not needed. In rare cases, when the language of the text in the image is known, setting a hint will help get better results (although it will be a significant hindrance if the hint is wrong). Text detection returns an error if one or more of the specified languages is not one of the supported languages.
- */
- NSString * KMGOCRLanguageCodeKey = @"KMGOCRLanguageCodeKey";
- NSString * KMGOCRLanguageStringKey = @"KMGOCRLanguageStringKey";
- #pragma mark - KMGOCRResult
- @class KMOCROperationQueue;
- @interface KMGOCRResult ()
- @end
- @implementation KMGOCRResult
- - (void)dealloc {
-
- }
- @end
- #pragma mark - KMGOCRManager
- @interface KMGOCRManager () <KMGOCROperationDelegate, KMOCROperationDelegate>
- @property (nonatomic, retain) NSMutableArray *languages;
- @property (nonatomic, assign) NSString *fileType;
- @property (nonatomic, retain) NSMutableArray *ocrPath;
- @property (nonatomic, retain) NSURL *filePath;
- @property (nonatomic, assign) NSUInteger finishIndex;
- //@property (nonatomic, retain) KMOCRPreferences *ocrPreferences; //恢复OCR架上版本样式
- @property (nonatomic,retain) VNRecognizeTextRequest *appleRequest;
- @property (nonatomic, assign) VNRequestTextRecognitionLevel appleRecognitionMode;
- @property (nonatomic,retain) NSMutableArray *images;
- @end
- @implementation KMGOCRManager
- #pragma mark - Init Methods
- - (id)init {
- if (self = [super init]) {
- }
- return self;
- }
- - (void)dealloc {
- _delegate = nil;
- if (@available(macOS 10.15, *)) {
-
- }
- }
- #pragma mark - Public Methods
- + (KMGOCRManager *)defaultManager {
- static KMGOCRManager *singleton = nil;
- static dispatch_once_t pred;
- dispatch_once(&pred, ^{
- singleton = [[KMGOCRManager alloc] init];
- });
- return singleton;
- }
- + (NSArray *)languages {
- if ([KMGOCRManager defaultManager].OCRType == KMOCRType_Google) {
- return @[@{KMGOCRLanguageCodeKey:@"af", KMGOCRLanguageStringKey:@"Afrikaans"},
- @{KMGOCRLanguageCodeKey:@"sq", KMGOCRLanguageStringKey:@"Albanian"},
- @{KMGOCRLanguageCodeKey:@"ar", KMGOCRLanguageStringKey:@"Arabic"},
- @{KMGOCRLanguageCodeKey:@"hy", KMGOCRLanguageStringKey:@"Armenian"},
- @{KMGOCRLanguageCodeKey:@"az", KMGOCRLanguageStringKey:@"Azerbaijani"},
- @{KMGOCRLanguageCodeKey:@"eu", KMGOCRLanguageStringKey:@"Basque"},
- @{KMGOCRLanguageCodeKey:@"be", KMGOCRLanguageStringKey:@"Belarusian"},
- @{KMGOCRLanguageCodeKey:@"bn", KMGOCRLanguageStringKey:@"Bengali"},
- @{KMGOCRLanguageCodeKey:@"bs", KMGOCRLanguageStringKey:@"Bosnian"},
- @{KMGOCRLanguageCodeKey:@"bg", KMGOCRLanguageStringKey:@"Bulgarian"},
- @{KMGOCRLanguageCodeKey:@"ca", KMGOCRLanguageStringKey:@"Catalan"},
- @{KMGOCRLanguageCodeKey:@"ceb", KMGOCRLanguageStringKey:@"Cebuano"},
- @{KMGOCRLanguageCodeKey:@"ny", KMGOCRLanguageStringKey:@"Chichewa"},
- @{KMGOCRLanguageCodeKey:@"zh-CN", KMGOCRLanguageStringKey:@"Chinese Simplified"},
- @{KMGOCRLanguageCodeKey:@"zh-TW", KMGOCRLanguageStringKey:@"Chinese Traditional"},
- @{KMGOCRLanguageCodeKey:@"hr", KMGOCRLanguageStringKey:@"Croatian"},
- @{KMGOCRLanguageCodeKey:@"cs", KMGOCRLanguageStringKey:@"Czech"},
- @{KMGOCRLanguageCodeKey:@"da", KMGOCRLanguageStringKey:@"Danish"},
- @{KMGOCRLanguageCodeKey:@"nl", KMGOCRLanguageStringKey:@"Dutch"},
- @{KMGOCRLanguageCodeKey:@"en", KMGOCRLanguageStringKey:@"English"},
- @{KMGOCRLanguageCodeKey:@"eo", KMGOCRLanguageStringKey:@"Esperanto"},
- @{KMGOCRLanguageCodeKey:@"et", KMGOCRLanguageStringKey:@"Estonian"},
- @{KMGOCRLanguageCodeKey:@"tl", KMGOCRLanguageStringKey:@"Filipino"},
- @{KMGOCRLanguageCodeKey:@"fi", KMGOCRLanguageStringKey:@"Finnish"},
- @{KMGOCRLanguageCodeKey:@"fr", KMGOCRLanguageStringKey:@"French"},
- @{KMGOCRLanguageCodeKey:@"gl", KMGOCRLanguageStringKey:@"Galician"},
- @{KMGOCRLanguageCodeKey:@"ka", KMGOCRLanguageStringKey:@"Georgian"},
- @{KMGOCRLanguageCodeKey:@"de", KMGOCRLanguageStringKey:@"German"},
- @{KMGOCRLanguageCodeKey:@"el", KMGOCRLanguageStringKey:@"Greek"},
- @{KMGOCRLanguageCodeKey:@"gu", KMGOCRLanguageStringKey:@"Gujarati"},
- @{KMGOCRLanguageCodeKey:@"ht", KMGOCRLanguageStringKey:@"Haitian Creole"},
- @{KMGOCRLanguageCodeKey:@"ha", KMGOCRLanguageStringKey:@"Hausa"},
- @{KMGOCRLanguageCodeKey:@"iw", KMGOCRLanguageStringKey:@"Hebrew"},
- @{KMGOCRLanguageCodeKey:@"hi", KMGOCRLanguageStringKey:@"Hindi"},
- @{KMGOCRLanguageCodeKey:@"hmn", KMGOCRLanguageStringKey:@"Hmong"},
- @{KMGOCRLanguageCodeKey:@"hu", KMGOCRLanguageStringKey:@"Hungarian"},
- @{KMGOCRLanguageCodeKey:@"is", KMGOCRLanguageStringKey:@"Icelandic"},
- @{KMGOCRLanguageCodeKey:@"ig", KMGOCRLanguageStringKey:@"Igbo"},
- @{KMGOCRLanguageCodeKey:@"id", KMGOCRLanguageStringKey:@"Indonesian"},
- @{KMGOCRLanguageCodeKey:@"ga", KMGOCRLanguageStringKey:@"Irish"},
- @{KMGOCRLanguageCodeKey:@"it", KMGOCRLanguageStringKey:@"Italian"},
- @{KMGOCRLanguageCodeKey:@"ja", KMGOCRLanguageStringKey:@"Japanese"},
- @{KMGOCRLanguageCodeKey:@"jw", KMGOCRLanguageStringKey:@"Javanese"},
- @{KMGOCRLanguageCodeKey:@"kn", KMGOCRLanguageStringKey:@"Kannada"},
- @{KMGOCRLanguageCodeKey:@"kk", KMGOCRLanguageStringKey:@"Kazakh"},
- @{KMGOCRLanguageCodeKey:@"km", KMGOCRLanguageStringKey:@"Khmer"},
- @{KMGOCRLanguageCodeKey:@"ko", KMGOCRLanguageStringKey:@"Korean"},
- @{KMGOCRLanguageCodeKey:@"lo", KMGOCRLanguageStringKey:@"Lao"},
- @{KMGOCRLanguageCodeKey:@"la", KMGOCRLanguageStringKey:@"Latin"},
- @{KMGOCRLanguageCodeKey:@"lv", KMGOCRLanguageStringKey:@"Latvian"},
- @{KMGOCRLanguageCodeKey:@"lt", KMGOCRLanguageStringKey:@"Lithuanian"},
- @{KMGOCRLanguageCodeKey:@"mk", KMGOCRLanguageStringKey:@"Macedonian"},
- @{KMGOCRLanguageCodeKey:@"mg", KMGOCRLanguageStringKey:@"Malagasy"},
- @{KMGOCRLanguageCodeKey:@"ms", KMGOCRLanguageStringKey:@"Malay"},
- @{KMGOCRLanguageCodeKey:@"ml", KMGOCRLanguageStringKey:@"Malayalam"},
- @{KMGOCRLanguageCodeKey:@"mt", KMGOCRLanguageStringKey:@"Maltese"},
- @{KMGOCRLanguageCodeKey:@"mi", KMGOCRLanguageStringKey:@"Maori"},
- @{KMGOCRLanguageCodeKey:@"mr", KMGOCRLanguageStringKey:@"Marathi"},
- @{KMGOCRLanguageCodeKey:@"mn", KMGOCRLanguageStringKey:@"Mongolian"},
- @{KMGOCRLanguageCodeKey:@"my", KMGOCRLanguageStringKey:@"Myanmar (Burmese)"},
- @{KMGOCRLanguageCodeKey:@"ne", KMGOCRLanguageStringKey:@"Nepali"},
- @{KMGOCRLanguageCodeKey:@"no", KMGOCRLanguageStringKey:@"Norwegian"},
- @{KMGOCRLanguageCodeKey:@"fa", KMGOCRLanguageStringKey:@"Persian"},
- @{KMGOCRLanguageCodeKey:@"pl", KMGOCRLanguageStringKey:@"Polish"},
- @{KMGOCRLanguageCodeKey:@"pt", KMGOCRLanguageStringKey:@"Portuguese"},
- @{KMGOCRLanguageCodeKey:@"ma", KMGOCRLanguageStringKey:@"Punjabi"},
- @{KMGOCRLanguageCodeKey:@"ro", KMGOCRLanguageStringKey:@"Romanian"},
- @{KMGOCRLanguageCodeKey:@"ru", KMGOCRLanguageStringKey:@"Russian"},
- @{KMGOCRLanguageCodeKey:@"sr", KMGOCRLanguageStringKey:@"Serbian"},
- @{KMGOCRLanguageCodeKey:@"st", KMGOCRLanguageStringKey:@"Sesotho"},
- @{KMGOCRLanguageCodeKey:@"si", KMGOCRLanguageStringKey:@"Sinhala"},
- @{KMGOCRLanguageCodeKey:@"sk", KMGOCRLanguageStringKey:@"Slovak"},
- @{KMGOCRLanguageCodeKey:@"sl", KMGOCRLanguageStringKey:@"Slovenian"},
- @{KMGOCRLanguageCodeKey:@"so", KMGOCRLanguageStringKey:@"Somali"},
- @{KMGOCRLanguageCodeKey:@"es", KMGOCRLanguageStringKey:@"Spanish"},
- @{KMGOCRLanguageCodeKey:@"su", KMGOCRLanguageStringKey:@"Sudanese"},
- @{KMGOCRLanguageCodeKey:@"sw", KMGOCRLanguageStringKey:@"Swahili"},
- @{KMGOCRLanguageCodeKey:@"sv", KMGOCRLanguageStringKey:@"Swedish"},
- @{KMGOCRLanguageCodeKey:@"tg", KMGOCRLanguageStringKey:@"Tajik"},
- @{KMGOCRLanguageCodeKey:@"ta", KMGOCRLanguageStringKey:@"Tamil"},
- @{KMGOCRLanguageCodeKey:@"te", KMGOCRLanguageStringKey:@"Telugu"},
- @{KMGOCRLanguageCodeKey:@"th", KMGOCRLanguageStringKey:@"Thai"},
- @{KMGOCRLanguageCodeKey:@"tr", KMGOCRLanguageStringKey:@"Turkish"},
- @{KMGOCRLanguageCodeKey:@"uk", KMGOCRLanguageStringKey:@"Ukrainian"},
- @{KMGOCRLanguageCodeKey:@"ur", KMGOCRLanguageStringKey:@"Urdu"},
- @{KMGOCRLanguageCodeKey:@"uz", KMGOCRLanguageStringKey:@"Uzbek"},
- @{KMGOCRLanguageCodeKey:@"vi", KMGOCRLanguageStringKey:@"Vietnamese"},
- @{KMGOCRLanguageCodeKey:@"cy", KMGOCRLanguageStringKey:@"Welsh"},
- @{KMGOCRLanguageCodeKey:@"yi", KMGOCRLanguageStringKey:@"Yiddish"},
- @{KMGOCRLanguageCodeKey:@"yo", KMGOCRLanguageStringKey:@"Yoruba"},
- @{KMGOCRLanguageCodeKey:@"zu", KMGOCRLanguageStringKey:@"Zulu"}];
- }
- return @[@{KMGOCRLanguageCodeKey:@"en-US", KMGOCRLanguageStringKey:@"English"},
- @{KMGOCRLanguageCodeKey:@"fr-FR", KMGOCRLanguageStringKey:@"French"},
- @{KMGOCRLanguageCodeKey:@"it-IT", KMGOCRLanguageStringKey:@"Italian"},
- @{KMGOCRLanguageCodeKey:@"de-DE", KMGOCRLanguageStringKey:@"German"},
- @{KMGOCRLanguageCodeKey:@"es-ES", KMGOCRLanguageStringKey:@"Spanish"},
- @{KMGOCRLanguageCodeKey:@"pt-BR", KMGOCRLanguageStringKey:@"Portuguese"},
- @{KMGOCRLanguageCodeKey:@"zh-Hant", KMGOCRLanguageStringKey:@"Chinese Traditional"},
- @{KMGOCRLanguageCodeKey:@"zh-Hans", KMGOCRLanguageStringKey:@"Chinese Simplified"}];
- }
- static inline NSFont * FontWithSize(NSString *strChar, CGSize size) {
- CGFloat fontsize = 1.0;
- NSFont *font = [NSFont systemFontOfSize:fontsize];
- CGSize strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
- while ((fontsize<127) && (strSize.width<size.width || strSize.height<size.height)) {
- fontsize += 1.0;
- font = [NSFont systemFontOfSize:fontsize];
- strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
- }
- return [NSFont systemFontOfSize:fontsize-1];
- }
- - (void)createPDFFile:(NSString *)filePath imagePaths:(NSArray *)paths results:(NSArray *)resultsArray scale:(CGFloat)scale {
- if (paths.count < 1) {
- return;
- }
-
- CFStringRef path = (__bridge CFStringRef)filePath;
- CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0);
- CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("Kdan Mobile PDF Reader"));
-
- CGContextRef pdfContext = CGPDFContextCreateWithURL(url, &CGRectZero, myDictionary);
- CGContextSetRGBFillColor(pdfContext, 1.0, 0.0, 0.0, 0.0);
- CGContextSetTextDrawingMode(pdfContext, kCGTextFill);
-
- CFRelease(myDictionary);
- CFRelease(url);
-
- for (int i=0; i<paths.count; i++) {
- NSString *path = [paths objectAtIndex:i];
- NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
- CIImage *imageCIImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:path]];
- NSSize size = [imageCIImage extent].size;
- CGRect pageRect = CGRectMake(0, 0, size.width/scale, size.height/scale);
-
- CFMutableDictionaryRef pageDictionary = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDataRef boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect));
- CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
- CGPDFContextBeginPage (pdfContext, pageDictionary);
- NSData *imageData = [NSData dataWithContentsOfFile:path];
- CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
- CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
- CGContextSaveGState(pdfContext);
- CGContextDrawImage(pdfContext, pageRect, imageRef);
- CGContextRestoreGState(pdfContext);
- CGImageRelease(imageRef);
-
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:pdfContext flipped:NO]];
- NSArray *results = nil;
- if (i < resultsArray.count) {
- results = resultsArray[i];
- CGFloat newScale = scale;
- if([KMGOCRManager defaultManager].OCRType == KMOCRType_Apple)
- newScale = 1;
- if (results.count == 1) {
- KMGOCRResult *result = results[0];
- NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
- pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
- (result.textBounds.size.width)/newScale,
- (result.textBounds.size.height)/newScale);
- NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
- NSForegroundColorAttributeName:[NSColor clearColor]};
- [result.text drawInRect:bounds withAttributes:dic];
- } else {
- for (int i=1; i<results.count; i++) {
- KMGOCRResult *result = results[i];
- NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
- pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
- (result.textBounds.size.width)/newScale,
- (result.textBounds.size.height)/newScale);
- NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
- NSForegroundColorAttributeName:[NSColor clearColor]};
- [result.text drawInRect:bounds withAttributes:dic];
- }
- }
- }
- [NSGraphicsContext restoreGraphicsState];
-
- CGPDFContextEndPage (pdfContext);
-
- CFRelease(pageDictionary);
- CFRelease(boxData);
- }
-
- CGPDFContextClose(pdfContext);
- CGContextRelease (pdfContext);
- }
- - (void)recognitionImages:(NSArray *)images withLanguages:(NSArray *)languages {
- [self recognitionImages:images withLanguages:languages fileType:nil filePath:nil];
- }
- - (void)recognitionImages:(NSArray *)images withLanguages:(NSArray *)languages fileType:(NSString * _Nullable)fileType filePath:(NSURL *)filePath {
- self.ocrPath = [[NSMutableArray alloc] init];
- self.finishIndex = 0;
- self.fileType = @"PDF";
- self.images = [NSMutableArray arrayWithArray:images];
-
- if (!filePath) {
- self.filePath = [NSURL URLWithString:[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
- } else {
- self.filePath = filePath;
- }
-
- //恢复OCR架上版本样式
- // self.ocrPreferences = [KMOCRPreferences new];
- // _isOCR = self.ocrPreferences.planPopUpBtnCount;
- // if (_isOCR) {
- // self.fileType = fileType;
- // [self ocrRecognitionImages:images withLanguages:languages];
- // } else {
- // [self gocrRecognitionImages:images withLanguages:languages];
- // }
-
- if (self.OCRType == KMOCRType_Google) {
- [self gocrRecognitionImages:images withLanguages:languages];
- }else{
- if (@available(macOS 10.15, *)) {
- if (_appleRequest) {
- [_appleRequest cancel];
- _appleRequest = nil;
- }
- [self recognitionAppleImageAtIndex:self.finishIndex];
- } else {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didFailureOCRImageAtIndex:error:)]) {
- [self.delegate GOCRManager:self didFailureOCRImageAtIndex:self.finishIndex error:nil];
- }
- }
- }
- }
- - (void)cancelRecognition {
- if (@available(macOS 10.15, *)) {
- if (_appleRequest) {
- [_appleRequest cancel];
- _appleRequest = nil;
- }
- }
- [self.images removeAllObjects];
- self.languages = nil;
- self.finishIndex = 0;
- KMOCROperationQueue *queue = [KMOCROperationQueue sharedInstance];
- if (queue.operations.count > 0) {
- for (KMGOCROperation *op in queue.operations) {
- op.operationDelegate = nil;
- }
- [queue cancelAll];
- }
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didCancelOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didCancelOCRImageAtIndex:self.finishIndex];
- }
- self.delegate = nil;
- }
- #pragma mark - Apple OCR
- - (void)recognitionAppleImageAtIndex:(NSUInteger)index {
- if (index >= self.images.count) {
- if (@available(macOS 10.15, *)) {
- [_appleRequest cancel];
- }
- _appleRequest = nil;
- if ([self.delegate respondsToSelector:@selector(GOCRManagerDidFinishOCR:)]) {
- [self.delegate GOCRManagerDidFinishOCR:self];
- }
- return;
- }
- self.finishIndex = index;
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didStartOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didStartOCRImageAtIndex:self.finishIndex];
- }
- if([self.images[self.finishIndex] isKindOfClass:[NSImage class]]) {
- [self recognitionAppleImage:self.images[self.finishIndex]];
- } else {
- NSData *data = self.images[self.finishIndex];
- NSImage *s = [[NSImage alloc] initWithData:data];
- if(_appleRequest) {
- [_appleRequest cancel];
- _appleRequest = nil;
- }
- [self recognitionAppleImage:s];
- }
- }
- - (void)recognitionAppleImage:(NSImage *)image {
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- __block typeof(self) blockSelf = self;
- _appleRequest = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) {
- NSArray *results = nil;
- if (request.results.count > 0) {
- results = [blockSelf responseDataRequest:request dictionary:nil imageSize:image.size];
- }
- NSMutableArray *resultArray = [[NSMutableArray alloc] init];
- for (KMGOCRResult *result in results) {
- NSDictionary *dic = @{@"x":@(result.textBounds.origin.x),
- @"y":@(result.textBounds.origin.y),
- @"width":@(result.textBounds.size.width),
- @"height":@(result.textBounds.size.height),
- @"text":result.text
- };
- [resultArray addObject:dic];
- }
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (error || !results) {
- if (self.delegate && [blockSelf.delegate respondsToSelector:@selector(GOCRManager:didFailureOCRImageAtIndex:error:)]) {
- [blockSelf.delegate GOCRManager:blockSelf didFailureOCRImageAtIndex:blockSelf.finishIndex error:error];
- }
- } else {
- if (self.delegate && [blockSelf.delegate respondsToSelector:@selector(GOCRManager:didFinishOCRImageAtIndex:results:)]) {
- [blockSelf.delegate GOCRManager:blockSelf didFinishOCRImageAtIndex:blockSelf.finishIndex results:results];
- }
- }
- [blockSelf recognitionAppleImageAtIndex:blockSelf.finishIndex+1];
- });
- }];
- self->_appleRequest.usesCPUOnly = YES;
- self->_appleRequest.recognitionLevel = self.appleRecognitionMode;
- if (self.languages.count > 0) {
- NSMutableArray *array = [[NSMutableArray alloc] initWithArray:blockSelf.languages];
- if ([self.languages containsObject:@"zh-Hant"]) {
- [array removeObject:@"zh-Hant"];
- [array insertObject:@"zh-Hant" atIndex:0];
- }
- if ([self.languages containsObject:@"zh-Hans"]) {
- [array removeObject:@"zh-Hans"];
- [array insertObject:@"zh-Hans" atIndex:0];
- }
- self.languages = array;
- self->_appleRequest.recognitionLanguages = self.languages;
- }else{
- self->_appleRequest.recognitionLanguages = @[@"zh-Hans",@"zh-Hant"];
- }
- NSError *error = nil;
- VNImageRequestHandler *handle = [[VNImageRequestHandler alloc] initWithCGImage:[self nsImageToCGImageRef:image] options:@{}];
- if (self->_appleRequest){
- [handle performRequests:@[self->_appleRequest] error:&error];
- }
- });
- }
- #pragma mark - GOCRManager Methods
- - (void)gocrRecognitionImages:(NSArray *)images withLanguages:(NSArray *)languages {
- if (!images || images.count == 0) {
- return;
- }
-
- if ([self.delegate respondsToSelector:@selector(GOCRManagerDidStartOCR:)]) {
- [self.delegate GOCRManagerDidStartOCR:self];
- }
-
- for (NSUInteger i=0; i<images.count; i++) {
-
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didStartOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didStartOCRImageAtIndex:i];
- }
- KMOCROperationQueue *queue = [KMOCROperationQueue sharedInstance];
- queue.maxConcurrentOperationCount = 1;
- NSImage *image = [[NSImage alloc] init];
- if([images[i] isKindOfClass:[NSImage class]]) {
- image = images[i];
- } else {
- NSData *data = images[i];
- image = [[NSImage alloc] initWithData:data];
- }
- KMGOCROperation *op = [[KMGOCROperation alloc] initWithRecognitionImg:image imgIndex:i];
- op.selectedLanguages = [NSMutableArray arrayWithArray:languages];
- op.operationDelegate = self;
- [queue addOperation:op];
- }
- }
- #pragma mark - OCRManager Methods
- - (void)ocrRecognitionImages:(NSArray *)images withLanguages:(NSArray *)languages {
- self.languages = [[NSMutableArray alloc] init];
- if (!images || images.count == 0) {
- return;
- }
-
- if (languages.count == 0) {
- for (NSDictionary *dict in [KMGOCRManager languages]) {
- [self.languages addObject:dict[KMGOCRLanguageCodeKey]];
- }
- } else {
- [self.languages addObjectsFromArray:languages];
- }
-
- for (NSUInteger i=0; i<images.count; i++) {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didStartOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didStartOCRImageAtIndex:i];
- }
- NSString *desktopPath = [NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) objectAtIndex:0];
- NSDateFormatter *formatter = [[NSDateFormatter alloc ] init];
- [formatter setDateFormat:@"YYYY-MM-dd-hh-mm-ss-SSS"];
- NSString *dateString = [formatter stringFromDate:[NSDate date]];
- NSString *fileName;
- if ([self.fileType isEqualToString:@"PDF"]) {
- fileName = [NSString stringWithFormat:@"%@-%ld.pdf",dateString,i];
- } else {
- fileName = [NSString stringWithFormat:@"%@-%ld.txt",dateString,i];
- }
- NSString *strPath = [desktopPath stringByAppendingPathComponent:fileName];
- [_ocrPath addObject:strPath];
-
- KMOCROperationQueue *queue = [KMOCROperationQueue sharedInstance];
- queue.maxConcurrentOperationCount = images.count;
-
- NSImage *image = [[NSImage alloc] init];
- if([images[i] isKindOfClass:[NSImage class]]) {
- image = images[i];
- } else {
- NSData *data = images[i];
- image = [[NSImage alloc] initWithData:data];
- }
-
- KMOCROperation *op = [[KMOCROperation alloc] initWithRecognitionImg:image imgIndex:i];
- op.fileType = self.fileType;
- op.selectedLanguages = self.languages;
- op.filePath = fileName;
- op.operationDelegate = self;
- [queue addOperation:op];
- }
- }
- #pragma mark - Private Methods
- - (void)setIsOCR:(BOOL)isOCR {
- _isOCR = isOCR;
- }
- - (NSString *)joinPDF:(NSArray *)listOfPaths {
- // File paths
- NSDateFormatter *formatter = [[NSDateFormatter alloc ] init];
- [formatter setDateFormat:@"YYYY-MM-dd-hh-mm-ss-SSS"];
- NSString *dateString = [formatter stringFromDate:[NSDate date]];
- NSString *fileName;
- if ([self.fileType isEqualToString:@"PDF"]) {
- fileName = [NSString stringWithFormat:@"%@.pdf",dateString];
- } else {
- fileName = [NSString stringWithFormat:@"%@.txt",dateString];
- }
-
- // NSString *pdfPathOutput = [[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:dateString];
- NSString *pdfPathOutput = [[_filePath path] stringByAppendingPathComponent:fileName];
- CFURLRef pdfURLOutput = (CFURLRef)CFBridgingRetain([NSURL fileURLWithPath:pdfPathOutput]);
- NSInteger numberOfPages = 0;
- CGContextRef writeContext = CGPDFContextCreateWithURL(pdfURLOutput, NULL, NULL);
- for (NSString *source in listOfPaths) {
- CFURLRef pdfURL = (CFURLRef)CFBridgingRetain([[NSURL alloc] initFileURLWithPath:source]);
- CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
- numberOfPages = CGPDFDocumentGetNumberOfPages(pdfRef);
- CGPDFPageRef page;
- CGRect mediaBox;
- for (int i=1; i<=numberOfPages; i++) {
- page = CGPDFDocumentGetPage(pdfRef, i);
- mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
- CGContextBeginPage(writeContext, &mediaBox);
- CGContextDrawPDFPage(writeContext, page);
- CGContextEndPage(writeContext);
- }
- CGPDFDocumentRelease(pdfRef);
- CFRelease(pdfURL);
- }
- CFRelease(pdfURLOutput);
- CGPDFContextClose(writeContext);
- CGContextRelease(writeContext);
-
- if ([self.delegate respondsToSelector:@selector(GOCRManagerDidFinishOCR:)]) {
- [self.delegate GOCRManagerDidFinishOCR:self];
- }
- NSLog(@"pdfPathOutput == %@",pdfPathOutput);
- return pdfPathOutput;
- }
- #pragma mark - KMOCROperationDelegate
- - (void)OCROperation:(KMOCROperation *)operation startOCRImageAtIndex:(NSInteger)index {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didStartOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didStartOCRImageAtIndex:index];
- }
- }
- - (void)OCROperation:(KMOCROperation *)operation cancelOCRImageAtIndex:(NSInteger)index {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didCancelOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didCancelOCRImageAtIndex:index];
- }
- }
- - (void)OCROperation:(KMOCROperation *)operation finishOCRImageAtIndex:(NSInteger)index results:(NSArray *)result {
- self.finishIndex++;
-
- if ([self.delegate respondsToSelector:@selector(CHOCRManager:didFinishOCRImageAtIndex:results:)]) {
- [self.delegate CHOCRManager:self didFinishOCRImageAtIndex:_finishIndex results:result];
- }
- }
- - (void)OCROperation:(KMOCROperation *)operation failureOCRImageAtIndex:(NSInteger)index error:(NSError *)error {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didFailureOCRImageAtIndex:error:)]) {
- [self.delegate GOCRManager:self didFailureOCRImageAtIndex:index error:error];
- }
- }
- #pragma mark - KMGOCROperationDelegate
- - (void)GOCROperation:(KMGOCROperation *)operation startOCRImageAtIndex:(NSInteger)index{
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didStartOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didStartOCRImageAtIndex:index];
- }
- }
- - (void)GOCROperation:(KMGOCROperation *)operation cancelOCRImageAtIndex:(NSInteger)index{
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didCancelOCRImageAtIndex:)]) {
- [self.delegate GOCRManager:self didCancelOCRImageAtIndex:index];
- }
- }
- - (void)GOCROperation:(KMGOCROperation *)operation finishOCRImageAtIndex:(NSInteger)index results:(NSArray *)results {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didFinishOCRImageAtIndex:results:)]) {
- [self.delegate GOCRManager:self didFinishOCRImageAtIndex:index results:results];
- }
- self.finishIndex++;
- if(self.finishIndex == self.images.count) {
- if ([self.delegate respondsToSelector:@selector(GOCRManagerDidFinishOCR:)]) {
- [self.delegate GOCRManagerDidFinishOCR:self];
- }
- }
- }
- - (void)GOCROperation:(KMGOCROperation *)operation failureOCRImageAtIndex:(NSInteger)index error:(NSError *)error {
- if ([self.delegate respondsToSelector:@selector(GOCRManager:didFailureOCRImageAtIndex:error:)]) {
- [self.delegate GOCRManager:self didFailureOCRImageAtIndex:index error:error];
- }
- }
- // Apple OCR 结果解析
- - (NSArray *)responseDataRequest:(VNRequest *)request dictionary:(NSDictionary *)dictionary imageSize:(CGSize)imageSize{
- NSMutableArray *results = [NSMutableArray array];
- NSInteger maximumCandidates = 1;
- NSString *OCRStr = @"";
-
- if (request) {//Apple SDK识别出来的数据
- for (VNRecognizedTextObservation *observation in request.results) {
- VNRecognizedText *text = [observation topCandidates:maximumCandidates].firstObject;
-
- OCRStr = [OCRStr stringByAppendingString:[NSString stringWithFormat:@"%@\n",text.string]];
-
- NSError *error = nil;
- VNRectangleObservation *rectangleObservation = [text boundingBoxForRange:NSMakeRange(0, text.string.length) error:&error];
- CGFloat x = 0, y = 0, width = 0, height = 0;
- x = rectangleObservation.topLeft.x * imageSize.width;
- y = (1 - rectangleObservation.topLeft.y) * imageSize.height;
- width = rectangleObservation.boundingBox.size.width * imageSize.width;
- height = rectangleObservation.boundingBox.size.height * imageSize.height;
-
- KMGOCRResult *result = [[KMGOCRResult alloc] init];
- result.text = text.string;
- result.locale = @"";
- result.textBounds = CGRectMake(x, y, width, height);
- [results addObject:result];
- }
- //按照Google逻辑 array第一个元素为整个Image的文本
- if (results.count > 0) {
- KMGOCRResult *result = [[KMGOCRResult alloc] init];
- result.text = OCRStr;
- if (self.languages.count > 0) {
- result.locale = self.languages[0];
- }
- result.textBounds = CGRectZero;
- [results insertObject:result atIndex:0];
- }
- }
- return results;
- }
- - (CGImageRef)nsImageToCGImageRef:(NSImage*)image;
- {
- NSData * imageData = [image TIFFRepresentation];
- CGImageRef imageRef;
- if(imageData)
- {
- CGImageSourceRef imageSource =
- CGImageSourceCreateWithData(
- (CFDataRef)imageData, NULL);
- imageRef = CGImageSourceCreateImageAtIndex(
- imageSource, 0, NULL);
- }
- return imageRef;
- }
- @end
- @interface KMOCROperationQueue ()
- @end
- @implementation KMOCROperationQueue
- - (void)dealloc {
-
- }
- + (instancetype)sharedInstance {
- static KMOCROperationQueue *sharedInstance;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- sharedInstance = [KMOCROperationQueue new];
- });
- return sharedInstance;
- }
- - (void)addOCROperation:(NSOperation *)op {
- [self addOperation:op];
- }
- - (void)cancelAll {
- [self cancelAllOperations];
- }
- @end
|