缩放图像OSX Swift

时间:2017-04-13 04:05:15

标签: swift image macos cocoa nsimage

我目前正尝试使用swift缩放图像。这 不应该 是一项艰巨的任务,因为我已经在30分钟内在C#中实施了扩展解决方案 - 但是,我已经被困了2天了。

我尝试使用谷歌搜索/抓取堆栈帖子,但无济于事。我见过人们使用的两个主要解决方案是:

A function written in Swift to resize an NSImage proportionately

resizeNSImage.swift

An Obj C Implementation of the above link

所以我更喜欢使用效率最高/最少cpu的解决方案,根据我的研究选项2.由于选项2使用QPoint pos(line_edit->width()-5, 5); QMouseEvent e(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0); qApp->sendEvent(line_edit, &e); QMouseEvent f(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); qApp->sendEvent(line_edit, &f); NSImage.lockfocus(),图像将在非视网膜Mac,但视网膜macs的缩放尺寸加倍。我知道这是由于Retina macs的像素密度,并且是可以预期的,但我需要一个忽略HiDPI规范并只执行正常缩放操作的缩放解决方案。

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

如果人们可以发布 Swift 认证答案,而不是Obj C,我会非常感激!

修改 这是我对第一个解决方案的实现的副本 - 我把它分成了两个函数:

NSImage.unlockFocus

编辑2:

正如Zneak所指出的:我需要将返回的图像保存到磁盘 - 使用这两种实现,我的保存功能将文件成功写入磁盘。虽然我不认为我的保存功能可以搞砸我当前的调整大小实现,但我还是附加它以防万一:

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!)!
}

1 个答案:

答案 0 :(得分:0)

对于遇到此问题的其他人 - 我最终花费了无数个小时试图找到一种方法来做到这一点,最终得到了屏幕的缩放因子(普通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))
}