缩放图像OSX Swift

缩放图像OSX Swift,swift,image,macos,cocoa,nsimage,Swift,Image,Macos,Cocoa,Nsimage,我正在尝试使用swift缩放图像。这个不应该是一个困难的任务,因为我已经在C#中在30分钟内实现了一个缩放解决方案-然而,我已经被困了2天了 我试过用谷歌搜索/爬行堆栈帖子,但没用。我看到人们使用的两种主要解决方案是: 及 因此,我更愿意使用最高效/cpu密集度最低的解决方案,根据我的研究,这是选项2。由于选项2使用了NSImage.lockfocus()和NSImage.unlockFocus,因此图像在非视网膜Mac上的缩放效果良好,但在视网膜Mac上的缩放大小是前者的两倍。我知道这是

我正在尝试使用swift缩放图像。这个不应该是一个困难的任务,因为我已经在C#中在30分钟内实现了一个缩放解决方案-然而,我已经被困了2天了

我试过用谷歌搜索/爬行堆栈帖子,但没用。我看到人们使用的两种主要解决方案是:

因此,我更愿意使用最高效/cpu密集度最低的解决方案,根据我的研究,这是选项2。由于选项2使用了
NSImage.lockfocus()
NSImage.unlockFocus
,因此图像在非视网膜Mac上的缩放效果良好,但在视网膜Mac上的缩放大小是前者的两倍。我知道这是由于视网膜Mac的像素密度造成的,这是意料之中的,但我需要一个忽略HiDPI规范的缩放解决方案,只执行正常的缩放操作

这让我对选项1做了更多的研究。它看起来像一个声音函数,但是它实际上并不缩放输入图像,然后在保存返回图像时将文件大小加倍(可能是由于像素密度)。我发现另一个stack post与其他人有完全相同的问题,使用完全相同的实现()。在两个建议的答案中,第一个不起作用,第二个是我一直尝试使用的另一个实现

如果人们能迅速给出答案,而不是Obj C,我将非常感激

编辑: 这是我实现的第一个解决方案的副本-我将其分为两个功能:

func getSizeProportions(oWidth: CGFloat, oHeight: CGFloat) -> NSSize {

    var ratio:Float = 0.0
    let imageWidth = Float(oWidth)
    let imageHeight = Float(oHeight)

    var maxWidth = Float(0)
    var maxHeight = Float(600)

    if ( maxWidth == 0 ) {
      maxWidth = imageWidth
    }

    if(maxHeight == 0) {
      maxHeight = imageHeight
    }

    // Get ratio (landscape or portrait)
    if (imageWidth > imageHeight) {
      // Landscape
      ratio = maxWidth / imageWidth;
    }
    else {
      // Portrait
      ratio = maxHeight / imageHeight;
    }

    // Calculate new size based on the ratio
    let newWidth = imageWidth * ratio
    let newHeight = imageHeight * ratio

    return NSMakeSize(CGFloat(newWidth), CGFloat(newHeight))
}


func resizeImage(image:NSImage) -> NSImage {
    print("original: ", image.size.width, image.size.height )

    // Cast the NSImage to a CGImage
    var imageRect:CGRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
    let imageRef = image.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)

    // Create a new NSSize object with the newly calculated size
    let newSize = NSSize(width: CGFloat(450), height: CGFloat(600))
    //let newSize = getSizeProportions(oWidth: CGFloat(image.size.width), oHeight: CGFloat(image.size.height))

    // Create NSImage from the CGImage using the new size
    let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize)

    print("scaled: ", imageWithNewSize.size.width, imageWithNewSize.size.height )

    return NSImage(data: imageWithNewSize.tiffRepresentation!)!
}
编辑2:

正如Zneak所指出的:我需要将返回的映像保存到磁盘上——使用这两种实现,我的save函数会成功地将文件写入磁盘。虽然我不认为我的保存功能会影响我当前的大小调整实现,但我还是附加了它,以防万一:

func saveAction(image: NSImage, url: URL) {

    if let tiffdata = image.tiffRepresentation,
    let bitmaprep = NSBitmapImageRep(data: tiffdata) {

    let props = [NSImageCompressionFactor: Appearance.imageCompressionFactor]
    if let bitmapData = NSBitmapImageRep.representationOfImageReps(in: [bitmaprep], using: .JPEG, properties: props) {

        let path: NSString = "~/Desktop/out.jpg"
        let resolvedPath = path.expandingTildeInPath

        try! bitmapData.write(to: URL(fileURLWithPath: resolvedPath), options: [])

        print("Your image has been saved to \(resolvedPath)")
    }
}

对于其他遇到这个问题的人-我花了无数个小时试图找到一种方法来解决这个问题,结果只是得到了屏幕的比例因子(正常Mac为1,视网膜为2)。。。代码如下所示:

func getScaleFactor() -> CGFloat {
    return NSScreen.main()!.backingScaleFactor
}
一旦你有了比例因子,你就可以正常缩放或者将视网膜的尺寸缩小一半:

if (scaleFactor == 2) {
    //halve size proportions for saving on Retina Macs
    return NSMakeSize(CGFloat(oWidth*ratio)/2, CGFloat(oHeight*ratio)/2)
} else {
    return NSMakeSize(CGFloat(oWidth*ratio), CGFloat(oHeight*ratio))
}

“应该”还是“不应该”?琐碎意味着容易。另外,您这样做是为了在屏幕上显示它,还是为了将它写回磁盘或其他什么?缩放到更大或更小的大小?编辑OP:)和im向下缩放以写回磁盘将
CGFloat
转换为
Float
然后再转换回
CGFloat
的目的是什么?你不需要在Swift中的
if
表达式周围加括号。完全忘了在post中更改括号。。。最初它们都是浮点数,但我改变了很多不同的部分,试图让它工作而不是检查特定的比例因子,你应该用它来除:
CGFloat(oWidth*ratio)/scaleFactor
。这样,如果苹果引入支持比例因子为其他值的设备/模式,代码将继续正常工作。但一定要先检查0!这将是一个很好的方法,虽然我很高兴它能正常工作,但目前来说:P