KanKonga
KanKonga

Reputation: 55

Why the screenshot is blurred even though the `.captureResolution` is set to `.best` - ScreenCaptureKit - macOS

Why the screenshot is blurred even though the .captureResolution is set to .best and configuration.width is set to 3840 * 2.

It outputs the image in the size set with the configuration.width, but still blurred regardless of the high resolution image it produces.

I'm trying to capture as image (screenshot), not as video.

I don't expect the quality more than my current display, however, the output is worse than the current display. When I take a screenshot with macOS standard screenshot tool, then the quality is perfect. Seems only the screenshot manager is not working properly.

Errors: No errors

@objc func takeScreenshot() {
    Task {
        do {
            let content = try await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: false)
            guard let mainDisplayID = NSScreen.main?.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID,
                  let display = content.displays.first(where: { $0.displayID == mainDisplayID }) else { return }
            
            let configuration = SCStreamConfiguration()
            configuration.captureResolution = .best
            configuration.sourceRect = CGRect(x: 400, y: 400, width: 800, height: 800)
            configuration.width = 3840 * 2
            configuration.height = 2160 * 2
            configuration.pixelFormat = kCVPixelFormatType_32BGRA
            configuration.preservesAspectRatio = true
            configuration.capturesAudio = false
            configuration.scalesToFit = false

            let filter = SCContentFilter(display: display, excludingWindows: [])
            
            let capturedImage = try await SCScreenshotManager.captureImage(contentFilter: filter, configuration: configuration)

            let nsImage = NSImage(cgImage: capturedImage, size: NSZeroSize)
            self.imageView.image = nsImage

        } catch {
            print("Error capturing screen: \(error)")
        }
    }
}

Upvotes: 3

Views: 469

Answers (3)

Marek H
Marek H

Reputation: 5576

Use contentRect and pointPixelScale property of SCContentFilter to capture full screen screenshot.

let filter : SCContentFilter 
...
let configuration = SCStreamConfiguration()
configuration.width = Int(filter.contentRect.width * filter.pointPixelScale)
configuration.height = Int(filter.contentRect.height * filter.pointPixelScale)

Upvotes: 1

Maxim Kuzmenko
Maxim Kuzmenko

Reputation: 1

Yup it's a bit frustrating. I found that proportionally scaling width and height doesn't help either -- there's always a little bit of blurriness.

A pointer for improvement in your case though, I see that you do:

configuration.sourceRect = CGRect(x: 400, y: 400, width: 800, height: 800)
configuration.width = 3840 * 2
configuration.height = 2160 * 2

You should set the width and height according to the sourceRect dimensions (that way you avoid potential issues by not having the same dimensions in your sourceRect and config) like so:

let configSourceRect = CGRect(x: 400, y: 400, width: 800, height: 800)
configuration.sourceRect = configSourceRect
configuration.width = configSourceRect.width * 2
configuration.height = configSourceRect.height * 2

Upvotes: 0

Hylas
Hylas

Reputation: 21

Same problem here.
I found that it will become blurred if sourceRect is set.
So I replace sourceRect with image cropping.

Upvotes: 0

Related Questions