【问题标题】:How to resize - resample - change file size - NSImage如何调整大小 - 重新采样 - 更改文件大小 - NSImage
【发布时间】:2017-01-16 13:43:44
【问题描述】:

我在google上做了很多搜索,跟踪了很多GitHub代码,没有成功。

我需要读取一个 jpeg 文件,例如 DPI = 72,大小 = 16000x1096 然后,我需要调整它的大小,以保存 72 DPI、800x548 像素的 jpeg 文件 这个,在 OSX 下,所以我可以使用 NSIMAGE,而不是 UIImage !

我不在乎我是否失去了一些品质!

最后,在多次尝试之后,我把我最新的代码放在这里,请大家帮忙:

    // get source image, jpeg, 1600x1196, 72 dpi
    let sourceImage = NSImage(contentsOfFile: source)

    // compute the scale, to have the longest size = 800 pixels. 72 DPI
    let width = CGFloat(sourceImage!.size.width)
    let height = CGFloat(sourceImage!.size.height)
    var scale = CGFloat( 800.0 / width)
    if width < height {
        scale = 800.0 / height
    }
    let newSize:NSSize = NSSize(width: Int(width * scale), height: Int(height * scale))
    print ("new size : " + String(describing: newSize) )

    // create a new image, with the "small" size
    let newImage = NSImage(size: NSSize(width: newSize.width, height: newSize.height))
    // lockfocus : draw will be done in this image
    newImage.lockFocus()
    // interpolation = low, because I don't care of quality
    NSGraphicsContext.current()?.imageInterpolation = NSImageInterpolation.low
    // draw the big image, into the small one
    sourceImage!.draw(in: NSMakeRect(0, 0, newSize.width, newSize.height), from: NSMakeRect(0, 0, width, height), operation: NSCompositingOperation.copy, fraction: CGFloat(1.0))
    newImage.unlockFocus()

    print("newImage size: " + String(describing: newImage.size))
    // display : newImage size: 800 x 598

    let cgRef = newImage.cgImage(forProposedRect: nil, context: nil, hints: nil)
    let newRep = NSBitmapImageRep(cgImage: cgRef!)
    newRep.size = newSize

    let jfifProperties = NSDictionary(dictionary: [kCGImagePropertyJFIFIsProgressive:kCFBooleanTrue])
    let properties = NSDictionary(dictionary: [kCGImageDestinationLossyCompressionQuality:1.0,
                                               kCGImagePropertyJFIFDictionary:jfifProperties,
                                               kCGImagePropertyDPIHeight: 72.0,
                                               kCGImagePropertyDPIWidth:72.0,
                                               kCGImagePropertyPixelHeight: 1.0,
                                               kCGImagePropertyPixelWidth: 1.0
                                               ])

    let data = newRep.representation(using: .JPEG, properties: properties as! [String : Any]) //[:])
    do {
        let url = URL(string: "file://" + destination)
        try data?.write(to: url!) //, options: false)
    }
    catch let error as NSError {
        resizeError = error.localizedDescription
        return false
    }

此代码无法正常工作。我得到一个文件,它是 144 DPI 和 1600 x 1096 !

如果我在调试器下打印变量 newImage,它会显示:

newImage的打印说明: \n\t\n\t\twidth = 1600, height = 1196, bpc = 8, bpp = 32, row bytes = 6400 \n\t\tkCGImageAlphaPremultipliedFirst | kCGImageByteOrder32Little \n\t\tis 掩码?不,有口罩吗?不,有哑光吗?不,应该插值吗?是>”

如我们所见,内容似乎与原版大小相同,不是吗?

我真的需要一些帮助,请,我被阻止了,没有找到任何解决方案。

感谢任何可以帮助我的答案。

最好的问候 奥利维尔

【问题讨论】:

  • 我不知道,但是:144 = 72+72(可能是一个提示,除以 2),你把 1.0 放在高度/宽度上,它们是比例吗?你可以在properties dict 中使用newHeight/oldHeight 吗?

标签: swift macos swift3 jpeg nsimage


【解决方案1】:

我自己找到了解决方案,但我很感激人们试图帮助我。 谢谢你。

这是我修复它的方法:

    // get source image, jpeg, 1600x1196, 72 dpi
    let sourceImage = NSImage(contentsOfFile: source)

    // compute the scale, to have the longest size = 800 pixels. 72 DPI
    let width = CGFloat(sourceImage!.size.width)
    let height = CGFloat(sourceImage!.size.height)
    var scale = CGFloat( resizedLongestSize / width)
    if width < height {
        scale = resizedLongestSize / height
    }
    let newSize:NSSize = NSSize(width: Int(width * scale), height: Int(height * scale))

    // create NSBitmapRep manually, if using cgImage, the resulting size is wrong
    let rep = NSBitmapImageRep(bitmapDataPlanes: nil,
                               pixelsWide: Int(newSize.width),
                               pixelsHigh: Int(newSize.height),
                               bitsPerSample: 8,
                               samplesPerPixel: 4,
                               hasAlpha: true,
                               isPlanar: false,
                               colorSpaceName: NSDeviceRGBColorSpace,
                               bytesPerRow: Int(newSize.width * 4),
                               bitsPerPixel: 32)

    let ctx = NSGraphicsContext(bitmapImageRep: rep!)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.setCurrent( ctx )
    sourceImage!.draw(in: NSMakeRect(0, 0, newSize.width, newSize.height))
    ctx?.flushGraphics()
    NSGraphicsContext.restoreGraphicsState()

    // Get NSData, and save it
    let data = rep?.representation(using: .JPEG, properties: [:]) // properties as! [String : Any]) //
    do {
        let url = URL(string: "file://" + destination)
        try data?.write(to: url!) //, options: false)
    }
    catch let error as NSError {
        resizeError = error.localizedDescription
        return false
    }

此代码运行良好,并在文件中提供了一张图片,调整了大小,并带有一组有限的 EXIF 数据,如果需要,很容易填充。

谢谢 奥利维尔

【讨论】:

    猜你喜欢
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 2015-06-28
    • 2012-10-29
    • 2015-06-04
    • 1970-01-01
    相关资源
    最近更新 更多