【问题标题】:macOS: Determine real size of icon returned from iconForFile methodmacOS:确定从 iconForFile 方法返回的图标的实际大小
【发布时间】:2021-02-19 01:43:37
【问题描述】:

我想要一种方法来判断文件的图标是仅提供 32 x 32 的图像,还是具有现代大图标尺寸 (512 x 512),以便我知道在放大时使用哪种高档方法。

我发现许多跨平台应用程序仍然只提供 32 x 32 尺寸的 Mac 图标,当放大到更大尺寸时往往看起来很糟糕,除非使用最近邻法放大。另一方面,现代大图标在与最近的邻居一起放大时往往看起来很糟糕。在我的 QuickLook 扩展中,我使用 [[NSWorkspace sharedWorkspace] iconForFile:path] 获取图标图像,它始终返回大小为 32 x 32 的 NSImage,但不提供实际可用的最大图标大小的线索。

如果我遍历它的图像表示,最大的总是 2048 x 2048 像素。

有没有办法找出来?

【问题讨论】:

    标签: macos cocoa icons appkit


    【解决方案1】:

    您需要检查图像表示。如果是NSPDFImageRep,您可以拨打[image setSize:NSMakeSize(512,512)];

    获得最大位图表示的最简单解决方案:

    NSImageRep *imgRep = [image bestRepresentationForRect:NSMakeRect(0, 0, 2048, 2048) context:nil hints:nil];
    NSLog(@"%@",NSStringFromSize([imgRep size]));
    

    或者检查所有给定的位图表示。

    NSURL *URL;
    CFErrorRef error;
    URL = (__bridge_transfer NSURL *)LSCopyDefaultApplicationURLForContentType(kUTTypeVCard, kLSRolesViewer, &error);
    NSImage *image = [[NSWorkspace sharedWorkspace] iconForFile:[URL path]];
    NSArray<NSImageRep *>*representations = [image representations];
    NSUInteger indexOfLargest = 0;
    NSUInteger surfaceArea = 0;
    for (NSUInteger i = 0 ; i < [representations count]; i++) {
        NSImageRep *rep = representations[i];
        if ([rep size].width * [rep size].height >= surfaceArea) {
            surfaceArea = [rep size].width * [rep size].height;
            indexOfLargest = i;
        }
    }
    NSLog(@"Representations %@", representations);
    NSLog(@"Largest index is: %lu", (unsigned long)indexOfLargest);
    

    控制台输出:

    2021-07-16 19:02:07.816423+0200 testImages[13756:755791] Representations (
        "NSISIconImageRep 0x600002abe2b0 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=0 Pixels=32x32 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe0d0 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=0 Pixels=32x32 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe1c0 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=0 Pixels=64x64 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe3a0 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=0 Pixels=64x64 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe3f0 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=0 Pixels=16x16 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe440 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=0 Pixels=16x16 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe490 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=0 Pixels=32x32 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe530 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=0 Pixels=32x32 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe580 Size={18, 18} ColorSpace=Generic RGB colorspace BPS=0 Pixels=18x18 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe5d0 Size={18, 18} ColorSpace=Generic RGB colorspace BPS=0 Pixels=18x18 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe620 Size={18, 18} ColorSpace=Generic RGB colorspace BPS=0 Pixels=36x36 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe4e0 Size={18, 18} ColorSpace=Generic RGB colorspace BPS=0 Pixels=36x36 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe670 Size={24, 24} ColorSpace=Generic RGB colorspace BPS=0 Pixels=24x24 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe6c0 Size={24, 24} ColorSpace=Generic RGB colorspace BPS=0 Pixels=24x24 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe710 Size={24, 24} ColorSpace=Generic RGB colorspace BPS=0 Pixels=48x48 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe760 Size={24, 24} ColorSpace=Generic RGB colorspace BPS=0 Pixels=48x48 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe7b0 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=0 Pixels=128x128 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe800 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=0 Pixels=128x128 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe850 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=0 Pixels=256x256 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe8a0 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=0 Pixels=256x256 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe8f0 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=0 Pixels=256x256 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe940 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=0 Pixels=256x256 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abe990 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=0 Pixels=512x512 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abe9e0 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=0 Pixels=512x512 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abea30 Size={512, 512} ColorSpace=Generic RGB colorspace BPS=0 Pixels=512x512 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abea80 Size={512, 512} ColorSpace=Generic RGB colorspace BPS=0 Pixels=512x512 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abead0 Size={512, 512} ColorSpace=Generic RGB colorspace BPS=0 Pixels=1024x1024 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abeb20 Size={512, 512} ColorSpace=Generic RGB colorspace BPS=0 Pixels=1024x1024 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abeb70 Size={1024, 1024} ColorSpace=Generic RGB colorspace BPS=0 Pixels=1024x1024 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abebc0 Size={1024, 1024} ColorSpace=Generic RGB colorspace BPS=0 Pixels=1024x1024 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua",
        "NSISIconImageRep 0x600002abec10 Size={1024, 1024} ColorSpace=Generic RGB colorspace BPS=0 Pixels=2048x2048 Alpha=NO AppearanceName=NSAppearanceNameAqua",
        "NSISIconImageRep 0x600002abec60 Size={1024, 1024} ColorSpace=Generic RGB colorspace BPS=0 Pixels=2048x2048 Alpha=NO AppearanceName=NSAppearanceNameDarkAqua"
    )
    2021-07-16 19:02:07.854533+0200 testImages[13756:755791] Largest index is: 31
    

    如果您想访问原始图标表示:

        NSImage *image = nil;
        OSErr err;
        
        err = GetIconRefFromTypeInfo(0, 0, CFSTR("pdf"), 0, 0, &iconRef);
        if (err == noErr && iconRef) {
            
            IconFamilyHandle iconFamily = NULL;
            err = IconRefToIconFamily(iconRef, kSelectorAllAvailableData, &iconFamily);
            ReleaseIconRef(iconRef);
    
            if(err == noErr && iconFamily)
            {
                NSData *data = [NSData dataWithBytes:*iconFamily length:GetHandleSize((Handle)iconFamily)];
                image = [[NSImage alloc] initWithData:data];
            }
        }
    

    控制台:

    2021-07-19 13:35:33.716142+0200 testImages2[10434:559291] Representations (
        "NSBitmapImageRep 0x60000016e8b0 Size={512, 512} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=1024x1024 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x60000014bc60 Size={256, 256} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=512x512 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x60000014bdb0 Size={512, 512} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=512x512 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x60000014bf00 Size={128, 128} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=256x256 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x60000014ca10 Size={256, 256} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=256x256 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x600000144000 Size={128, 128} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=128x128 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x6000001441c0 Size={32, 32} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=64x64 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x600000144310 Size={16, 16} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=32x32 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x6000001443f0 Size={32, 32} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=32x32 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0",
        "NSBitmapImageRep 0x6000001444d0 Size={16, 16} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=16x16 Alpha=YES Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600002a3eca0"
    )
    

    【讨论】:

    • 嗯,这就是我正在做的,显然我检查过的图标的最大图像表示是 2048 x 2048,尽管用于构建应用程序的实际图标图像只有 32 x 32。我猜测这意味着 2048 x 2048 丑陋的放大版本已经在其他地方创建,每当 macOS 创建其图标图像时,系统无法判断这不是原始图标大小。
    • 只需使用类似这样的 NSImageRep *imgRep = [image bestRepresentationForRect:NSMakeRect(0, 0, 512, 512) context:nil hints:nil]; NSLog(@"%@",NSStringFromSize([imgRep 大小]));要么你知道你想要什么尺寸,要么你想要最大的。
    • @PetterSjölund 我更新了答案。这些方法仍然有效,但已被弃用。如果原始 icns 文件只有 16x16 - 最后一种方法将只给出该图标,您可以手动放大禁用抗锯齿。如果文件有放大的图标 -> 死胡同,你不能做任何事情。
    • @PetterSjölund 如果原始文档图标文件在 512x512 处模糊 -> 它是在打包过程中使用“iconutil”创建的(Xcode 在后台使用它)。 AppKit + NSISIconImageRep -> 它是使用 [NSImage initWithIconRef:] 在具有预定大小的循环中使用“setScalesWhenResized:YES”创建的。是的,他们在 Big Sur 上使用了这些已弃用的功能。您可以使用 hopperapp + 拖放 AppKit.framework 来查看它(在 Big Sur 上它更复杂)
    • 我终于通过检测最常见的模糊图标并将它们替换为我包含在捆绑包中的更清晰的图像来解决这个问题。我仍然会将答案标记为解决方案,因为它对其他人可能比我的 hack 更有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    相关资源
    最近更新 更多