【问题标题】:Rendering a CALayer to an image with arbitrary size将 CALayer 渲染到任意大小的图像
【发布时间】:2019-03-17 13:59:48
【问题描述】:

我在我的 macOS 应用程序中使用以下 CALayer 扩展来将 CALayer 渲染到图像中:

extension CALayer {

    /// Get `Data` representation of the layer.
    ///
    /// - Parameters:
    ///   - fileType: The format of file. Defaults to PNG.
    ///   - properties: A dictionary that contains key-value pairs specifying image properties.
    ///
    /// - Returns: `Data` for image.

    func data(using fileType: NSBitmapImageRep.FileType = .png, properties: [NSBitmapImageRep.PropertyKey : Any] = [:]) -> Data {
        let width = Int(bounds.width * self.contentsScale)
        let height = Int(bounds.height * self.contentsScale)
        let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSColorSpaceName.deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
        imageRepresentation.size = bounds.size

        let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!

        render(in: context.cgContext)

        return imageRepresentation.representation(using: fileType, properties: properties)!
    }
}

我遇到的问题是,这个函数渲染的图像与图层本身具有相同的尺寸,就像在屏幕上渲染的那样。

如何修改它以指定要渲染的图像的大小并将图层扩展到图像的尺寸?

【问题讨论】:

    标签: swift macos core-graphics calayer


    【解决方案1】:

    您必须为所需大小添加一个附加参数并将内容缩放到该大小:

    func data(using fileType: NSBitmapImageRep.FileType = .png, size: CGSize, 
        properties: [NSBitmapImageRep.PropertyKey : Any] = [:]) -> Data {
        let width = bounds.width * self.contentsScale
        let height = bounds.height * self.contentsScale
        let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil,
            pixelsWide: Int(size.width), pixelsHigh: Int(size.height),
            bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, 
            isPlanar: false, colorSpaceName: NSColorSpaceName.deviceRGB,
            bytesPerRow: 0, bitsPerPixel: 0)!
        imageRepresentation.size = size
    
        let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!
    
        context.cgContext.scaleBy(x: size.width / width, y: size.height / height)
        render(in: context.cgContext)
    
        return imageRepresentation.representation(using: fileType,
            properties: properties)!
    }
    

    通过此修改,您可以像这样调用此方法:

    let theBounds = myView.bounds
    let theSize = CGSize(width: theBounds.width * 3.0, height: theBounds.height * 3.0)
    let theData = myView.layer?.data(using: .png, size: theSize, properties: [:])
    

    myView 的内容保存为原始大小的三倍放大到数据对象中。

    【讨论】:

    • 我非常希望这会起作用,但我将它注入到我的代码中,它会生成一个缩小的图像。我想要实现的是基于 UI 中的一组图层构建世界地图,然后将该组件的视图导出到可以设置为墙纸的图像中。我在我的公共项目中注入了您的代码:github.com/epseelon/scratchmap/blob/master/ScratchMap/… 并在这里使用它:github.com/epseelon/scratchmap/blob/master/ScratchMap/…
    • 如果你想创建一个放大的图像,只需在调用中更改大小。我改变了我的例子。
    • 我已经试过了,但由于某种原因,它似乎渲染了一个大小合适的图像,但图层只渲染在左下角的四分之一角。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多