5

My quick look generator used to work properly but is now broken.
Is it a bug or am I doing something wrong?

Here’s my code:

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, 
                               CFURLRef url, CFStringRef contentTypeUTI, 
                               CFDictionaryRef options) {

    NSDictionary * myDoc = [NSDictionary dictionaryWithContentsOfURL:(NSURL *)url];

        if (myDoc) {

            NSData * pngData = [myDoc valueForKey:@"pngPreview"];

            if (pngData) {

                QLPreviewRequestSetDataRepresentation(preview,(__bridge CFDataRef)pngData,
                                                      kUTTypeImage,NULL);
            }
        }
}

My doc is a normal plist with a png preview stored as data in it.
I checked that pngPreview does contain png data, I created the image and its size was 350×350.

However, I’m constantly getting these errors:

qlmanage[702] : CGImageCreate: invalid image size: 0 x 0.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x9e27, name = 'com.apple.tsm.portname' See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x3f2b, name = 'com.apple.CFPasteboardClient' See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] Failed to allocate communication port for com.apple.CFPasteboardClient; this is likely due to sandbox restrictions

My app is not sandboxed so I don’t think the last 3 errors are important.

I used to use kUTTypePNG but have tried kUTTypeImage to no avail (the docs for QLPreviewRequestSetDataRepresentation says currently supported UTIs are kUTTypeImage, kUTTypePDF, kUTTypeHTML, kUTTypeXML, kUTTypePlainText, kUTTypeRTF, kUTTypeMovie, and kUTTypeAudio).

Other points to consider: The docs state: "The binary of a Quick Look generator must be universal and must be 32-bit only." This page But this page states: "For OS X v10.6 and later, you must build Quick Look generators for both 32- and 64-bit." Which is rather unclear...
How do I set my target?

wdyp
  • 560
  • 4
  • 16

1 Answers1

4

Facing the same problem I've decided to go an alternate route: use QLPreviewRequestCreateContext to get a context in which to draw my image in:

QLPreviewRequestRef preview; // The preview request passed to GeneratePreviewForURL()
CGImageRef image;  // Create your CGImage however you like
CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
CGContextRef ctxt = QLPreviewRequestCreateContext(preview, size, YES, nil);
CGContextDrawImage(ctxt, CGRectMake(0, 0, size.width, size.height), image);
QLPreviewRequestFlushContext(preview, ctxt);
CGContextRelease(ctxt);

At least that works...

Guy Moreillon
  • 993
  • 10
  • 28
  • Thank you! I’ve no idea how to do this with QLPreviewRequestCreateContext. Could you post some code? I would mark it as the good answer to my question! Thanks! – wdyp Oct 11 '14 at 08:38
  • I added a code sample to my answer above, hope that helps – Guy Moreillon Oct 11 '14 at 20:39
  • Thank you for sharing! So I tried it and I’m getting this error… : CGContextDrawImage: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update. [WARNING] Flushing preview context for while there was no context created – wdyp Oct 11 '14 at 21:45
  • 1
    Maybe I didn’t created the image correctly from my NSData… Here’s how I did: `CFDataRef imgData = (__bridge CFDataRef)pngData;` `CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData (imgData);` `CGImageRef image = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);` – wdyp Oct 11 '14 at 21:48
  • Apparently QLPreviewRequestCreateContext is returning a nil context. Check that the size you provide is not (0,0). The way you create your image seems OK though. – Guy Moreillon Oct 12 '14 at 12:36
  • Well I tried if (ctxt) to make sure the context exists and it appears to exist... I'll check the size as you suggest, but how can I get say NSLog to work from the QL bundle? Sorry: I guess this must be a very stupid question! I'm not very good at CF code... Debugging is not easy! – wdyp Oct 12 '14 at 12:50
  • You can debug your code step-by-step in the debugger by running qlmanage as the executable of your QuickLook project. It's all explained there: https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/Quicklook_Programming_Guide/Articles/QLDebugTest.html – Guy Moreillon Oct 12 '14 at 16:06
  • OK, I’ve got a qlmanage executable but the breakpoints are simply ignored… – wdyp Oct 18 '14 at 17:12
  • Be sure to give the right options to qlmanage: -p to get a preview, -t for a thumbnail, otherwise nothing will happen. – Guy Moreillon Oct 18 '14 at 20:44
  • I implemented this, but I can't get it to behave appropriately in a HiDPI (retina) environment. I tried using `false` for the third parameter (making it a vector context as opposed to bitmap), but then it ignores the size arguments I give it. Any suggestions? – Bob Mar 06 '18 at 17:16