6

How do I remove the curled icon a thumbnail create in a quicklook plugin?

Screenshot of current icon: enter image description here

Screenshot of what I want: enter image description here

GeneratePreviewForURL.m:

#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <QuickLook/QuickLook.h>

#import "GenerateIcon.h"

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

/* -----------------------------------------------------------------------------
   Generate a preview for file

   This function's job is to create preview for designated file
   ----------------------------------------------------------------------------- */

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{
    // To complete your generator please implement the function GeneratePreviewForURL in GeneratePreviewForURL.c

    [GenerateIcon generatePreviewWithRef:preview URL:url];

    return noErr;
}

void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview)
{
    // Implement only if supported
}

GenerateIcon.m:

//
//  GenerateIcon.m
//  Windows Binary Icon
//
//  Created by Asger Hautop Drewsen on 2/5/12.
//  Copyright (c) 2012 Asger Drewsen. All rights reserved.
//

#import "GenerateIcon.h"

@implementation GenerateIcon

+(void) generateThumbnailWithRef:(QLThumbnailRequestRef)requestRef URL:(CFURLRef)url
{
    [GenerateIcon generateMultiWithThumbnailRef:requestRef PreviewRef:nil URL:url];
}
+(void) generatePreviewWithRef:(QLPreviewRequestRef)requestRef URL:(CFURLRef)url
{
    [GenerateIcon generateMultiWithThumbnailRef:nil PreviewRef:requestRef URL:url];
}

     +(void) generateMultiWithThumbnailRef:(QLThumbnailRequestRef)thumbnail PreviewRef:(QLPreviewRequestRef)preview URL:(CFURLRef)url
{
    @autoreleasepool {

        NSString * tempDir = NSTemporaryDirectory();
        if (tempDir == nil)
            tempDir = @"/tmp";

        NSFileManager *fileManager = [[NSFileManager alloc] init];

        NSString *directory = [tempDir stringByAppendingFormat: [NSString stringWithFormat:@"%@-%.0f", @"exe-icons", [NSDate timeIntervalSinceReferenceDate] * 1000.0]];

        //NSString *directory = [tempDir stringByAppendingPathComponent:@"com.tyilo.exe-icons"];

        /*for (NSString *file in [fileManager contentsOfDirectoryAtPath:directory error:nil])
         {
         [fileManager removeItemAtPath:file error:nil];
         }*/

        [fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];

        [[NSTask launchedTaskWithLaunchPath:@"/usr/local/bin/wrestool" arguments:[NSArray arrayWithObjects:
                                                                                  @"-t",
                                                                                  @"group_icon",
                                                                                  @"-o",
                                                                                  directory,
                                                                                  @"-x",
                                                                                  [(__bridge NSURL *)url path],
                                                                                  nil]] waitUntilExit];

        NSArray *icons = [fileManager contentsOfDirectoryAtPath:directory error:nil];

        if (icons.count > 0)
        {
            NSImage *image = [[NSImage alloc] initWithContentsOfFile:[directory stringByAppendingPathComponent: [icons objectAtIndex:0]]];
            NSData *thumbnailData = [image TIFFRepresentation];
            CGSize size = image.size;
            NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithInt:size.width],kQLPreviewPropertyWidthKey,
                                        [NSNumber numberWithInt:size.height],kQLPreviewPropertyHeightKey,
                                        nil];
            CGContextRef CGContext;
            if (thumbnail)
            {
                CGContext = QLThumbnailRequestCreateContext(thumbnail, size, TRUE, (__bridge CFDictionaryRef)properties);
            }
            else
            {
                CGContext = QLPreviewRequestCreateContext(preview, size, TRUE, (__bridge CFDictionaryRef)properties);
            }
            if(CGContext) {
                NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)CGContext flipped:size.width > size.height];
                if(context) {
                    //These two lines of code are just good safe programming…
                    [NSGraphicsContext saveGraphicsState];
                    [NSGraphicsContext setCurrentContext:context];

                    NSBitmapImageRep *thumbnailBitmap = [NSBitmapImageRep imageRepWithData:thumbnailData];
                    [thumbnailBitmap draw];

                    //This line sets the context back to what it was when we're done
                    [NSGraphicsContext restoreGraphicsState];
                }

                // When we are done with our drawing code QLThumbnailRequestFlushContext() is called to flush the context
                if (thumbnail)
                {
                    QLThumbnailRequestFlushContext(thumbnail, CGContext);
                }
                else
                {
                    QLPreviewRequestFlushContext(preview, CGContext);
                }

                // Release the CGContext
                CFRelease(CGContext);
            }
            /*NSLog(@"%@", [directory stringByAppendingPathComponent: [icons objectAtIndex:0]]);
             CGImageRef image = (__bridge CGImageRef) [[NSImage alloc] initByReferencingFile:[directory stringByAppendingPathComponent: [icons objectAtIndex:0]]];
             QLThumbnailRequestSetImage(thumbnail, image, properties);*/
        }
        else
        {
            NSLog(@"Failed to generate thumbnail!");
        }
    }
}

@end

Edit: Added screenshots.

Tyilo
  • 28,998
  • 40
  • 113
  • 198

2 Answers2

6

You need to add the undocumented "IconFlavor" key to the properties dictionary that you supply to QLThumbnailRequestCreateContext() or QLThumbnailRequestSetXXX(), and give it the value 1 for minimal decoration.

See here for an example. At the top of that file are some other values I've discovered for "IconFlavour".

Cœur
  • 37,241
  • 25
  • 195
  • 267
Marginal42
  • 286
  • 4
  • 8
  • Perfect! You, sir, deserves a medal. How did you discovered that? By the way, kQLThumbnailIconPlainFlavor had a better result for exe icons than kQLThumbnailIconShadowFlavor. – VitorMM May 24 '16 at 14:14
0

The aspect of your icons is automatically chosen by Quick Look and there is no public way to customize that. What is your type conformance tree?

For more information on UTIs see Uniform Type Identifiers Overview. Note that your type conformance tree won't necessarily translate to what you want from Quick Look but at least you will have a sane starting point.

Julien
  • 3,427
  • 20
  • 22
  • 1
    I just want to remove the curled corners and I have no idea what you just wrote – Tyilo Feb 10 '12 at 01:01
  • The aspect of the icons produced by Quick Look is inferred from your type declaration (this includes wether to put a curled corner, for example). When you declare your UTI, you need to specify your type conformance (UTTypeConformsTo). My question is: what types your own type conforms to? – Julien Feb 10 '12 at 01:14
  • It currently conforms to `public.item`, however it only works with exe-files. Should I change it to something else? – Tyilo Feb 10 '12 at 01:16
  • You should chose appropriate physical and functional types to conform to. – Julien Feb 14 '12 at 22:19
  • how? could you please give me an example? – Tyilo Feb 15 '12 at 01:33