From 206702bde3ff86c25307f204b232da2a15a291e0 Mon Sep 17 00:00:00 2001 From: Patrick Robertson Date: Sun, 29 Mar 2026 18:24:37 +0200 Subject: [PATCH] Make text from image extraction more efficient + add extra pref to disable --- .../QSObject_FileHandling.m | 73 +++++++++++-------- .../Code-QuickStepCore/QSPreferenceKeys.h | 3 + .../en.lproj/QSAdvancedPrefPane.strings | 2 + Quicksilver/Resources/DefaultsMap.plist | 10 +++ 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/Quicksilver/Code-QuickStepCore/QSObject_FileHandling.m b/Quicksilver/Code-QuickStepCore/QSObject_FileHandling.m index 6b25b1451..972872aa7 100644 --- a/Quicksilver/Code-QuickStepCore/QSObject_FileHandling.m +++ b/Quicksilver/Code-QuickStepCore/QSObject_FileHandling.m @@ -694,7 +694,13 @@ - (id)initWithArray:(NSArray *)paths { return self; } +#define MAX_IMAGE_SCAN_SIZE 50 * 1024 * 1024 // 50MB + - (void)loadAdditionalSearchContext { + if ([[NSUserDefaults standardUserDefaults] boolForKey:kQSDisableExtractTextFromImages]) { + return; + } + if (@available(macOS 10.15, *)) { // For images, use text recognition to extract any text and store as searchable context @@ -709,45 +715,48 @@ - (void)loadAdditionalSearchContext { return; } - NSImage *image = [[NSImage alloc] initWithContentsOfFile:path]; - if (!image) { - return; - } + NSURL *fileURL = [NSURL fileURLWithPath:path]; - // Get the CGImage from NSImage - CGImageRef cgImage = [image CGImageForProposedRect:NULL context:NULL hints:nil]; - if (!cgImage) { + if (!fileURL) { return; } - // Create a text recognition request - VNRecognizeTextRequest *request = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest *request, NSError *error) { - if (error) { - NSLog(@"Text recognition error: %@", error); - return; - } - - NSMutableString *recognizedText = [NSMutableString string]; - for (VNRecognizedTextObservation *observation in request.results) { - VNRecognizedText *text = [[observation topCandidates:1] firstObject]; - if (text) { - [recognizedText appendFormat:@" %@", text.string]; + // skip extracting text for images over 20MB + NSNumber *fileSize = nil; + [fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil]; + if ([fileSize unsignedLongLongValue] > MAX_IMAGE_SCAN_SIZE) return; + + __weak __typeof(self) weakSelf = self; + QSGCDAsync(^{ + // Create a text recognition request + VNRecognizeTextRequest *request = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest *request, NSError *error) { + if (error) { + NSLog(@"Text recognition error: %@", error); + return; } - } + + NSMutableString *recognizedText = [NSMutableString string]; + for (VNRecognizedTextObservation *observation in request.results) { + VNRecognizedText *text = [[observation topCandidates:1] firstObject]; + if (text) { + [recognizedText appendFormat:@" %@", text.string]; + } + } + + if ([recognizedText length] > 0) { + [weakSelf setObject:recognizedText forCache:kAdditionalSearchContext]; + } + }]; + + // Create an image request handler + VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithURL:fileURL options:@{}]; - if ([recognizedText length] > 0) { - [self setObject:recognizedText forCache:kAdditionalSearchContext]; + NSError *error = nil; + [handler performRequests:@[request] error:&error]; + if (error) { + NSLog(@"Error performing text recognition: %@", error); } - }]; - - // Create an image request handler - VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithCGImage:cgImage options:@{}]; - - NSError *error = nil; - [handler performRequests:@[request] error:&error]; - if (error) { - NSLog(@"Error performing text recognition: %@", error); - } + }); } } diff --git a/Quicksilver/Code-QuickStepCore/QSPreferenceKeys.h b/Quicksilver/Code-QuickStepCore/QSPreferenceKeys.h index f6fb562ce..15c6d5c58 100644 --- a/Quicksilver/Code-QuickStepCore/QSPreferenceKeys.h +++ b/Quicksilver/Code-QuickStepCore/QSPreferenceKeys.h @@ -77,3 +77,6 @@ Following lines are no longer used in this project. // A boolean indicating whether the task viewer resizes automatically #define kQSResizeTaskViewerAutomatically @"QSResizeTaskViewerAutomatically" + +// A boolean indicating whether text from image extraction should be disabled or not +#define kQSDisableExtractTextFromImages @"QSDisableExtractTextFromImages" diff --git a/Quicksilver/Localized/en.lproj/QSAdvancedPrefPane.strings b/Quicksilver/Localized/en.lproj/QSAdvancedPrefPane.strings index aaae83e8e..942c31171 100644 --- a/Quicksilver/Localized/en.lproj/QSAdvancedPrefPane.strings +++ b/Quicksilver/Localized/en.lproj/QSAdvancedPrefPane.strings @@ -28,3 +28,5 @@ "QSHistoryMaxLength:title" = "Number of items in Quicksilver’s history"; "QSCloseInterfaceOnSuccessfulDrop:title" = "Close the interface after a successful drag and drop"; + +"QSDisableExtractTextFromImages:title" = "Disable text extraction from images (disables searching for text in images)"; diff --git a/Quicksilver/Resources/DefaultsMap.plist b/Quicksilver/Resources/DefaultsMap.plist index 167c4cbb3..bfa7d50eb 100644 --- a/Quicksilver/Resources/DefaultsMap.plist +++ b/Quicksilver/Resources/DefaultsMap.plist @@ -142,5 +142,15 @@ type checkbox + + category + Command + default + QSDisableExtractTextFromImages + title + Disable text extraction from images (disables searching for text in images) + type + checkbox +