使用ScreenCaptureKit捕获全屏截图时分辨率不符合预期的问题
ScreenCaptureKit捕获全屏截图分辨率不符合Retina预期的问题
使用ScreenCaptureKit捕获整个显示器全屏截图时,返回的CGImageRef分辨率为1920x1080,不符合预期的3456x2234(Retina原生分辨率)。旧API CGWindowListCreateImage能返回正确分辨率,但该API已在macOS 15.0中废弃,且会触发无限隐私弹窗警告。
旧API声明
CG_EXTERN CGImageRef __nullable CGWindowListCreateImage(CGRect screenBounds, CGWindowListOption listOption, CGWindowID windowID, CGWindowImageOption imageOption) SCREEN_CAPTURE_OBSOLETE(10.5,14.0,15.0);
当前使用代码
[SCShareableContent getShareableContentWithCompletionHandler:^(SCShareableContent * _Nullable shareableContent, NSError * _Nullable error) { if (error) { return; } SCDisplay *display = [[shareableContent displays] firstObject]; SCContentFilter *filter = [[SCContentFilter alloc] initWithDisplay:display excludingWindows:@[]]; SCStreamConfiguration *configuration = [[SCStreamConfiguration alloc] init]; configuration.capturesAudio = NO; configuration.excludesCurrentProcessAudio = YES; configuration.preservesAspectRatio = YES; configuration.showsCursor = NO; configuration.captureResolution = SCCaptureResolutionBest; //configuration.pixelFormat = 'BGRA'; [SCScreenshotManager captureImageWithFilter:filter configuration:configuration completionHandler:^(CGImageRef _Nullable cgImage, NSError * _Nullable error) { if (error) { } else { NSLog(@"%@", cgImage); } }]; }];
当前日志输出
Printing description of cgImage: <CGImage 0x11fe306c0> (DP) <<CGColorSpace 0x600002ba0a80> (kCGColorSpaceDeviceRGB)> width = 1920, height = 1080, bpc = 8, bpp = 32, row bytes = 7680 kCGImageAlphaPremultipliedFirst | kCGImageByteOrder32Little | kCGImagePixelFormatPacked is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes (lldb) po [NSScreen mainScreen] <NSScreen: 0x600002bac3c0; name="Built-in Retina Display"; backingScaleFactor=2.000000; frame={{0, 0}, {1728, 1117}}; visibleFrame={{0, 48}, {1728, 1031}}>
旧API返回结果
Printing description of cgImage: <CGImage 0x146e8ad90> (DP) <<CGColorSpace 0x600000c949c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Color LCD)> width = 3456, height = 2234, bpc = 8, bpp = 32, row bytes = 13824 kCGImageAlphaPremultipliedFirst | kCGImageByteOrder32Little | kCGImagePixelFormatPacked is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? No
解决方法
问题根源是仅设置SCCaptureResolutionBest无法保证获取Retina原生分辨率,需手动指定捕获尺寸为显示器的原生物理像素尺寸:
- 获取
SCDisplay的size属性,该值直接对应显示器的原生物理像素(已包含Retina缩放因子); - 在
SCStreamConfiguration中设置width和height为该尺寸,优先级高于captureResolution设置。
修改后的代码:
[SCShareableContent getShareableContentWithCompletionHandler:^(SCShareableContent * _Nullable shareableContent, NSError * _Nullable error) { if (error) { return; } SCDisplay *display = [[shareableContent displays] firstObject]; SCContentFilter *filter = [[SCContentFilter alloc] initWithDisplay:display excludingWindows:@[]]; SCStreamConfiguration *configuration = [[SCStreamConfiguration alloc] init]; configuration.capturesAudio = NO; configuration.excludesCurrentProcessAudio = YES; configuration.preservesAspectRatio = YES; configuration.showsCursor = NO; // 手动指定原生物理像素尺寸 configuration.width = display.size.width; configuration.height = display.size.height; [SCScreenshotManager captureImageWithFilter:filter configuration:configuration completionHandler:^(CGImageRef _Nullable cgImage, NSError * _Nullable error) { if (error) { // 此处添加错误处理逻辑 } else { NSLog(@"%@", cgImage); } }]; }];
原理说明
SCDisplay.size返回的是显示器的原生物理像素,对应你设备上1728×1117 ×2 = 3456×2234的预期分辨率;SCCaptureResolutionBest仅为系统推荐的最优分辨率,可能因系统策略返回缩放后的低分辨率图像,手动指定尺寸可强制获取原生分辨率截图。
内容的提问来源于stack exchange,提问作者Marek H
相关产品推荐
相关产品推荐

