调整NSImage大小会导致其起点偏移并产生错误结果。

4
我正在使用以下代码来调整图像大小(保持宽高比)。当我尝试将大小为2432X3648像素的图像调整为1800X2700像素时,输出图像的原点会发生偏移。
extension NSImage {   


  func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
    let ratioX = width / size.width
    let ratioY = height / size.height
    var ratio = ratioX < ratioY ? ratioX : ratioY
    let newHeight = size.height * ratio
    let newWidth = size.width * ratio
    let canvasSize = CGSize(width: newWidth, height: newHeight)
    let img = NSImage(size: canvasSize)
    img.lockFocus()
    let context = NSGraphicsContext.current()
    context?.imageInterpolation = .high
    draw(in: NSRect(origin: .zero, size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size) , operation: .copy, fraction: 1)
    img.unlockFocus()
    return img
    }


}

请查看调整大小后的示例图像。我已标记图像。调整大小的代码在其他情况下似乎运行良好。请给予建议。

enter image description here

更新: @LeoDabus 我使用了你的代码,对于输出尺寸为1084X2086像素,它产生了类似的结果。我不得不稍微修改你的代码 - 只有一行因为它无法编译。编译器自动建议了它。 NSGraphicsContext.current()?.imageInterpolation = .high

 func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
        let ratioX = width / size.width
        let ratioY = height / size.height
        let ratio = ratioX < ratioY ? ratioX : ratioY
        let newHeight = size.height * ratio
        let newWidth = size.width * ratio
        let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        let img = NSImage(size: canvasSize)
        img.lockFocus()
        NSGraphicsContext.current()?.imageInterpolation = .high
        draw(in: NSRect(origin: CGPoint(x: (canvasSize.width - (size.width * ratio)) / 2, y: (canvasSize.height - (size.height * ratio)) / 2), size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size), operation: .copy, fraction: 1)
        img.unlockFocus()
        return img

}

@LeoDabus 谢谢您的回复。是哪个原始方法? - techno
@LeoDabus,“resizedTo”方法似乎是一样的...我想我已经改变了,因为评论中提到的空格问题。 - techno
@LeoDabus 你看到更新了吗? - techno
我投票关闭此问题,因为作者删除了很多问题,使得问题的意图不明确。 - picciano
1个回答

2
实际上出现问题的只是画布大小,应该使用新的宽度和高度:
extension NSImage {
    func resizedTo(width: CGFloat, height: CGFloat) -> NSImage {
        let ratio = min(canvas.width/size.width, canvas.height/size.height)
        let canvasSize = NSSize(width: size.width * ratio, height: size.height * ratio)
        let img = NSImage(size: canvasSize)
        img.lockFocus()
        NSGraphicsContext.current?.imageInterpolation = .high
        draw(in: NSRect(origin: CGPoint(x: (canvasSize.width - (size.width * ratio)) / 2, y: (canvasSize.height - (size.height * ratio)) / 2), size: canvasSize), from: NSRect(origin: .zero, size: size), operation: .copy, fraction: 1)
        img.unlockFocus()
        return img
    }
}

我遇到了以下错误 Cannot use optional chaining on non-optional value of type '() -> NSGraphicsContext?,所以我按照编译器的自动更正方式将其更改为 NSGraphicsContext.current().imageInterpolation = .high ... 但是你的新代码产生了相同的错误,请给予建议。 - techno
第一条建议是将您的Swift / Xcode更新到最新版本。第二,我已经在这里测试了该方法,并且它可以很好地扩展。请确保您已正确设置图像视图约束,并且正在使用适当的图像对齐方式。 - Leo Dabus
如果您不发布您的代码,我只能猜测。https://developer.apple.com/documentation/appkit/nsimageview/1404963-imagealignment和https://developer.apple.com/documentation/appkit/nsimagealignment。 - Leo Dabus
我只得到了一张黑色的图像。 - Leo Dabus
我正在尝试使用您之前发布的代码来检测人脸并调整检测到的人脸大小。请查看更新,这是否会导致调整大小的问题? - techno
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接