QuickLook Thumbnailing

RSS for tag

Generate thumbnails for common file types and add a Thumbnail Extension to your app using QuickLook Thumbnailing.

Posts under QuickLook Thumbnailing tag

9 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Finder File Previews lock files on SMB shares
I've developed a new Quicklook data-based preview extension for a custom file type that generates an image preview of the file. I previously used a Quick Look generator plug-in but support for it was deprecated and now removed in macOS Sequoia. My app opens files using a open(url.path, O_RDWR | O_NONBLOCK | O_EXLOCK) call. The locking flags are used to prevent other clients from writing the file if it's already open. I discovered that when Finder is showing the “large” file previews (such as when in column or gallery modes) from a SMB share, the open call fails with EWOULDBLOCK as if the file is locked. It does work just fine on local files. Opening with O_SHLOCK also has the issue. Surprisingly it does work just fine for previews that return Plain Text data instead of Image data. Using the lsof command, it seems like the Quicklook process has some kind of lock on the file. This is the output of the lsof command: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE QuickLook 48487 XXXX txt REG 1,15 125000611 3161369 Attached is a test project that tries a few different opening and locking functions. It also includes a test file and a sample image preview extension that displays a red square. When everything is working, regular console messages show the progress of the tests. When the file is on a SMB share and selected in Finder Gallery mode, the open test will fail with a fault message in the console. Notably, locking with flock works, which is weird because it should have similar semantics according to the man page for open(2). Filed this as FB15051186
5
0
163
1w
Thumbnails for images saved in core data
I'm trying to look at what the best way to do thumbnails for images that are saved in core data, which are being synced across multiple devices. I know I can save a lower quality version into core data, but I'm wondering if there's a better way of doing it. I've come across quick look thumbnailing which looks like what I want, but I'm not sure if it can be adapted for core data as its using file paths, whereas the images are stored in a data type property in core data. From what I can tell, I'd have to save the image locally, produce the thumbnail, then delete the local image
0
0
181
Oct ’24
QLPreviewController Blinks on Previewing Some PDF files
QLPreview keeps blinking and stops previewing the file when opening some high-resolution PDF files with heavy content. This can only be simulated in a real device built in xcode simulators cant simulate the issue. Tested in Xcode Version 15.4 (15F31d) and iPadOS Version 17.5.1. Following is My Sample code : import UIKit import QuickLook class ViewController: UIViewController { var currentViewFilePath = "" let preview = QLPreviewController() override func viewDidLoad() { super.viewDidLoad() self.setupQLPreview() loaddata() // Do any additional setup after loading the view. } func loaddata(){ if let fileURL = Bundle.main.url(forResource: "CD28048D", withExtension: "pdf") { self.currentViewFilePath = fileURL.relativePath self.preview.reloadData() // Use the fileURL here print("File URL: \(fileURL)") } else { print("File not found") } } } extension ViewController:QLPreviewControllerDelegate,QLPreviewControllerDataSource{ func setupQLPreview(){ preview.delegate = self preview.dataSource = self self.view.addSubview(preview.view) let previewhight = (UIScreen.main.bounds.height - ((self.navigationController?.navigationBar.frame.height ?? 0))) preview.view.translatesAutoresizingMaskIntoConstraints = false preview.view.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true preview.view.leftAnchor.constraint(equalTo: self.view.leftAnchor,constant: 4).isActive = true preview.view.rightAnchor.constraint(equalTo: self.view.rightAnchor,constant: -4).isActive = true preview.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor,constant: 4).isActive = true preview.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor,constant: -4).isActive = true preview.view.widthAnchor.constraint(equalToConstant: self.view.frame.width-8).isActive = true preview.view.heightAnchor.constraint(equalToConstant: previewhight-4).isActive = true preview.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true preview.navigationController?.isNavigationBarHidden = true self.addChild(preview) preview.didMove(toParent: self) } func numberOfPreviewItems(in controller: QLPreviewController) -> Int { if self.currentViewFilePath.isEmpty || self.currentViewFilePath == ""{ return 0 }else{ return 1 } } func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { let fileUrl = URL(fileURLWithPath: self.currentViewFilePath) return fileUrl as QLPreviewItem } } while running the above code Xcode debugger prints following errors: View service did terminate with error: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted} #Remote Preview collection viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted} #Remote [u 0AA9D4C5-BBA1-56F6-8FFF-F5F56B99399A:m (null)] [com.apple.quicklook.extension.previewUI(1.0)] Connection to plugin invalidated while in use.
0
2
524
Jul ’24
How to stop Finder from triggering full file download of a file on network share to generate the thumbnail
Default behaviour of the macOS when interacting via Finder with a network share is to create thumbnails to provide a nice user experience. This behaviour is implemented by QuickLook framework. This triggers the full file download and quickly lead to cache using large disk space and even cache trashing. We can disable QuickLook selectively by injecting specially prepared .DS_Store file with instruction/setup to disable thumbnails in that directory but still degrades user's experience only in the network share ecosystem. Is there any way we can provide our own thumbnails or ask Finder to not download full file to generate the thumbnail?
1
0
537
Jun ’24
Accesing Files in Thumbnail Extension and Quick Look Extension
I am developing Thumbnail Extension. To prepare a graphic (in .dylib) for file specified in URL.path I need to access second file, which has the same filename, but different extension. For example, I have "data" in file.*** and "colors" in file.yyy. Is it possible to read data from this second file while processing the first file in my extension? In my current implementation it sometimes works, but most of the time it doesn't work - it is not possible to read data from file.yyy when preparing thumbnail for file.***, causing exception in my .dylib routine. Is there some setting which would allow me to do this?
0
0
437
Jun ’24
Embed external binary in QuickLook Preview application
Hello, I am trying to write a simple QuickLook generator, which takes a file, runs an external binary to produce the data, and then creates and shows an image in a preview. The input files are uncommon data formats, and the binary in this case converts these to PNG. I have tried multiple methods and followed many discussions on these forums and StackOverflow, but unfortunately I am yet to get it working. That said, the program I have builds and runs using the qlmanage tool, however when running in Finder or on the server qlmanage -x the program fails. As I understand, it when using QuickLook in Finder it calls the QuickLook daemon quicklookd which is also called when using the qlmanage -x CLI command, but please correct me if I am wrong about this. The basic idea for all generator functions is: create NSTask or Process and run the third-party binary, using the requested file path as input run the task, pipe output, and read output convert the piped output to NSImage show image Attempt 1 (old-style qlgenerator plugin in Obj-C): Initially I tried adding the binary as an asset to the QuickLook Preview target and the generator would work as mentioned using qlmanage, however it would not work using qlmanage -x or from Finder. Here is the preview function: OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { NSLog(@"QuickLook plugin started"); NSInteger width = 512; NSURL *fileURL = (__bridge NSURL *)url; NSString *escapedFilePath = [fileURL.path stringByReplacingOccurrencesOfString:@" " withString:@"\\ "]; NSLog(@"Original Path: %@", fileURL.path); NSLog(@"Escaped Path: %@", escapedFilePath); NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.pjharrison.qlgwyddion"]; NSURL *nsURLExecutable = [bundle URLForAuxiliaryExecutable:@"gwyddion-thumbnailer"]; if (nsURLExecutable) { // The resource was found, and nsURLData is not nil. // Proceed with using nsURLData. NSLog(@"Resource 'gwyddion-thumbnailer' found in the bundle."); } else { // The resource was not found. Handle the situation accordingly. NSLog(@"Resource 'gwyddion-thumbnailer' not found in the bundle."); } NSTask *task = [[NSTask alloc] init]; NSLog(@"Pathhhh %@", nsURLExecutable.path); [task setExecutableURL:nsURLExecutable]; [task setArguments:@[@"kde4", [@(width) stringValue], escapedFilePath]]; NSLog(@"Task set"); NSString *argumentString = [task.arguments componentsJoinedByString:@" "]; NSLog(argumentString); NSPipe *pipe = [NSPipe pipe]; NSFileHandle *file = pipe.fileHandleForReading; [task setStandardOutput:pipe]; NSLog(@"Pipe set"); [task launch]; NSLog(@"Task launched"); NSData *data = [file readDataToEndOfFile]; NSLog(@"Got data"); [task waitUntilExit]; NSLog(@"Task completed"); NSInteger taskStatusCode = [task terminationStatus]; NSLog(@"Task finished with status code %ld", taskStatusCode); NSString *dataLength = [NSString stringWithFormat:@"%lu", data.length]; NSLog(dataLength); CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData((CFDataRef)data); CGImageRef cgImage = CGImageCreateWithPNGDataProvider(imageDataProvider, NULL, true, kCGRenderingIntentDefault); if (cgImage) { CGFloat height = CGImageGetHeight(cgImage); CGFloat width = CGImageGetWidth(cgImage); CGSize size = CGSizeMake(width, height); // Preview will be drawn in a vectorized context CGRect rect = CGRectMake(0, 0, width, height); CGContextRef cgContext = QLPreviewRequestCreateContext(preview, size, true, NULL); CGContextDrawImage(cgContext, rect, cgImage); NSLog(@"Image drawn"); QLPreviewRequestFlushContext(preview, cgContext); NSLog(@"Flushed"); // release resources if (cgContext) { CFRelease(cgContext); NSLog(@"Context released"); } CGImageRelease(cgImage); NSLog(@"Image released"); } else { NSLog(@"cgImage is NULL"); } return noErr; } Inspection console logs would give various Operation not permitted errors when run from the quicklookd server. I suspect that possibly this is due to App Sandboxing issues. Attempt 2 After coming across various articles online by @eskimo and others, including the official docs and various other posts, I have tried to sign the binary executable as described in the documentation and embed it in the project. Unfortunately after signing the app I have not been able to get the executable to run. When called from the QuickLook Preview function, the process returns with an error code. Perhaps the issue is here and the executable has not been signed properly? Attempt 3 I have also tried to create a Swift-based app and add a QuickLook Extension to the app (creating an app with a .appex) using a similar flow as tried in Attempt 1. Also no luck here so far. At this point I am stuck and would appreciate any help or pointers! Many thanks in advance.
0
0
705
Feb ’24
QLSupportedContentTypes cannot contain system-supported types (UTIs)
Hi folks, My app is reading proprietary files with the file name extension .JPX - which is out of my control. In addition I’m providing QuickLook and Thumbnail extensions, used system-wide and in my app. Unfortunately iOS is assigning the JPEG-2000 file type (UTI „public.jpeg-2000“) to this file extension, and therefore - to work with associated files - my app is importing this UTI and both extensions are listing „public.jpeg-2000“ in their info.plist as QLSupportedContentTypes. This works to some extent in simulators and when debugging from Xcode on a device: Files with the file extension „.JPX“ are listed with thumbnails provided by my extension, although the preview seems to invoke the system-provided viewer and fails. Not perfect, but good enough as my app requires an icon preview (aka thumbnail) in its UIDocumentBrowserViewController. But when I try to submit my app incl. extensions to the Apple App Store / TestFlight asset validation is reporting an error: „Asset validation failed. Invalid Info.plist value. The value for the key ‚QLSupportedContentTypes‘ in bundle … is invalid. [public.jpeg-2000] are system-supported types.“ How to assign QuickLook / Thumbnail extensions to 3rd party files types whose extension is conflicting with a system-supported UTI? I just spent one of my TSIs for this question - as my Apple developer membership is renewed shortly - but maybe this community as some smart tip to share... Appreciate any help, Mattes
1
0
891
Feb ’24