I am trying to get a screenshot of whole display. However I am being returned different resolution which is also non retina. Instead of 3456x2234
CGImageRef
I am being given 1920x1080
.
Note that the old API CGWindowListCreateImage
has been made obsolete in macOS 15.0 and triggers unlimited privacy popup warning. Old API gives expected result.
CG_EXTERN CGImageRef __nullable CGWindowListCreateImage(CGRect screenBounds,
CGWindowListOption listOption, CGWindowID windowID,
CGWindowImageOption imageOption)
SCREEN_CAPTURE_OBSOLETE(10.5,14.0,15.0);
Code:
[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);
}
}];
}];
Log:
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}}>
Old API would return:
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
The SCStreamConfiguration
defaults to 1920x1080
. It has to be configured manually.
configuration.width = NSWidth(filter.contentRect) * filter.pointPixelScale;
configuration.height = NSHeight(filter.contentRect) * filter.pointPixelScale;
Taking a display screenshot:
[SCShareableContent getShareableContentWithCompletionHandler:^(SCShareableContent * _Nullable shareableContent, NSError * _Nullable error) {
if (error) { return; }
SCDisplay *display = [[shareableContent displays] firstObject]; //or match displayID to window's screen deviceDescription NSScreenNumber
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.width = NSWidth(filter.contentRect) * filter.pointPixelScale;
configuration.height = NSHeight(filter.contentRect) * filter.pointPixelScale;
//configuration.pixelFormat = 'BGRA';
[SCScreenshotManager captureImageWithFilter:filter configuration:configuration completionHandler:^(CGImageRef _Nullable cgImage, NSError * _Nullable error) {
if (error) {
} else {
NSLog(@"%@", cgImage);
}
}];
}];
NOTE: You need to retain the cgImage or pass it as NSImage object.