Cocoa:在 Swift 中保存时捕获屏幕并缩放图像
Posted
技术标签:
【中文标题】Cocoa:在 Swift 中保存时捕获屏幕并缩放图像【英文标题】:Cocoa: Capture Screen and scale image on saving in Swift 【发布时间】:2021-12-09 20:25:36 【问题描述】:下面的代码我用来在 macOS 应用程序中捕获屏幕,
let img = CGDisplayCreateImage(CGMainDisplayID())
guard let destination = FileManager.default.urls(for: .downloadsDirectory,
in: .userDomainMask).first?.appendingPathComponent("shot.jpg", isDirectory: false)
else
print("Unable to save captured image!")
return
let properties: CFDictionary = [
kCGImagePropertyPixelWidth: "900",
kCGImagePropertyPixelHeight: "380"
] as CFDictionary
if let dest = CGImageDestinationCreateWithURL(destination as CFURL, kUTTypeJPEG, 1, properties)
CGImageDestinationAddImage(dest, img!, properties)
CGImageDestinationFinalize(dest)
else
print("Unable to create captured image to the destination!")
我必须在保存时将图像缩放到特定大小。所以,我使用了CFDictionary
和图像的width, heigh
属性。但似乎我做错了。请帮我找出正确的解决方案。谢谢!
【问题讨论】:
提示:NSImge
draw(in:from:operation:fraction:)
@ElTomato 如果我将 CGImage 转换为 NSImage ,则 NSImage 容量的 JPEG 表示将高于存储中原始未缩放的图像容量。这就是问题所在。
“看来我做错了”并不能真正描述您面临的问题。如果您不想调整图像大小,那么您要解决的问题是什么?
@ElTomato,我正在寻找解决方案来调整图像大小,同时通过设置properties
或任何其他方式将其从 CGImage 中保存。 developer.apple.com/documentation/imageio/cgimageproperties/…
再一次,“看来我做错了”并不能真正描述您面临的问题。
【参考方案1】:
首先,您不能使用CGImageDestinationCreateWithURL
或CGImageDestinationAddImage
调整大小。如果您查看文档here 和here,您会注意到kCGImagePropertyPixelWidth
或kCGImagePropertyPixelHeight
均不受支持。
您需要手动调整大小。如果您觉得它有帮助,您可以使用此工具或对其进行修改。它支持填充(拉伸)和适合(在保持原始纵横比的同时缩放)内容模式。如果您指定.fit
,它将使绘图在结果图像中居中。如果您指定.fill
,它将填充整个空间并拉伸它需要的任何维度。
enum ImageResizer
enum ContentMode
case fill
case fit
enum Error: Swift.Error
case badOriginal
case resizeFailed
static func resize(_ source: CGImage, to targetSize: CGSize, mode: ContentMode) throws -> CGImage
let context = CGContext(
data: nil,
width: Int(targetSize.width),
height: Int(targetSize.height),
bitsPerComponent: source.bitsPerComponent,
bytesPerRow: 0,
space: source.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!,
bitmapInfo: source.bitmapInfo.rawValue
)
guard let context = context else
throw Error.badOriginal
let drawingSize: CGSize
switch mode
case .fill:
drawingSize = targetSize
case .fit:
drawingSize = CGSize(width: source.width, height: source.height)
.scaledToFit(target: targetSize)
let drawRect = CGRect(origin: .zero, size: targetSize)
.makeCenteredRect(withSize: drawingSize)
context.interpolationQuality = .high
context.draw(source, in: drawRect)
guard let result = context.makeImage() else
throw Error.resizeFailed
return result
ImageResizer
依赖于这些 CG 扩展来缩放源图像和居中缩放图像:
extension CGSize
var maxDimension: CGFloat
Swift.max(width, height)
var minDimension: CGFloat
Swift.min(width, height)
func scaled(by scalar: CGFloat) -> CGSize
CGSize(width: width * scalar, height: height * scalar)
func scaleFactors(to target: CGSize) -> CGSize
CGSize(
width: target.width / width,
height: target.height / height
)
func scaledToFit(target: CGSize) -> CGSize
return scaled(by: scaleFactors(to: target).minDimension)
extension CGRect
func makeCenteredRect(withSize size: CGSize) -> CGRect
let origin = CGPoint(
x: midX - size.width / 2.0,
y: midY - size.height / 2.0
)
return CGRect(origin: origin, size: size)
另外,如果您要保存到 .downloadsDirectory
,请确保设置了 permissions。
【讨论】:
以上是关于Cocoa:在 Swift 中保存时捕获屏幕并缩放图像的主要内容,如果未能解决你的问题,请参考以下文章