简体   繁体   English

如何调整 Swift 中的图像大小?

[英]How to Resize image in Swift?

I am making an app for iOS, using Swift and Parse.com我正在为 iOS 制作一个应用程序,使用Swift和 Parse.com

I am trying to let the user select a picture from an image picker and then resize the selected image to 200x200 pixels before uploading to my backend.我试图让用户 select 从图像选择器中获取图片,然后在上传到我的后端之前将所选图像调整为 200x200 像素。

Parse.com have a tutorial for an Instagram copy app called "AnyPic" which gives this code for resizing images, but it is in Objective-C.... Parse.com 有一个名为“AnyPic”的 Instagram 复制应用程序的教程,它提供了用于调整图像大小的代码,但它位于 Objective-C ....

// Resize the image to be square (what is shown in the preview)
UIImage *resizedImage = [anImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
        bounds:CGSizeMake(560.0f, 560.0f)
        interpolationQuality:kCGInterpolationHigh];
// Create a thumbnail and add a corner radius for use in table views
UIImage *thumbnailImage = [anImage thumbnailImage:86.0f
        transparentBorder:0.0f
        cornerRadius:10.0f
        interpolationQuality:kCGInterpolationDefault];

How would I create a 200x200px version of the selected picture (to then upload) in Swift?我如何在 Swift 中创建所选图片的 200x200px 版本(然后上传)?

And, what is the thumbnailImage function doing?而且,thumbnailImage function 在做什么?

See my blog post, Resize image in swift and objective C , for further details.有关更多详细信息,请参阅我的博客文章Resize image in swift andobjective C

Image resize function in swift as below.快速调整图像大小功能,如下所示。

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
    let size = image.size
    
    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height
    
    // Figure out what our orientation is, and use that to form the rectangle
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
    }
    
    // This is the rect that we've calculated out and this is what is actually used below
    let rect = CGRect(origin: .zero, size: newSize)
    
    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return newImage
}

Use the above function and resize image with 200*200 as below code使用上面的函数并用 200*200 调整图像大小,如下代码

self.resizeImage(UIImage(named: "yourImageName")!, targetSize: CGSizeMake(200.0, 200.0))

swift3 updated swift3 更新

 func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    let size = image.size
    
    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height
    
    // Figure out what our orientation is, and use that to form the rectangle
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
    }
    
    // This is the rect that we've calculated out and this is what is actually used below
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
    
    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return newImage!
}

For Swift 4.0 and iOS 10适用于 Swift 4.0 和 iOS 10

    extension UIImage {
        func resizeImage(_ dimension: CGFloat, opaque: Bool, contentMode: UIViewContentMode = .scaleAspectFit) -> UIImage {
            var width: CGFloat
            var height: CGFloat
            var newImage: UIImage

            let size = self.size
            let aspectRatio =  size.width/size.height

            switch contentMode {
                case .scaleAspectFit:
                    if aspectRatio > 1 {                            // Landscape image
                        width = dimension
                        height = dimension / aspectRatio
                    } else {                                        // Portrait image
                        height = dimension
                        width = dimension * aspectRatio
                    }

            default:
                fatalError("UIIMage.resizeToFit(): FATAL: Unimplemented ContentMode")
            }

            if #available(iOS 10.0, *) {
                let renderFormat = UIGraphicsImageRendererFormat.default()
                renderFormat.opaque = opaque
                let renderer = UIGraphicsImageRenderer(size: CGSize(width: width, height: height), format: renderFormat)
                newImage = renderer.image {
                    (context) in
                    self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
                }
            } else {
                UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), opaque, 0)
                    self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
                    newImage = UIGraphicsGetImageFromCurrentImageContext()!
                UIGraphicsEndImageContext()
            }

            return newImage
        }
    }

Since @KiritModi 's answer is from 2015, this is the Swift 3.0's version:由于@KiritModi 的回答是从 2015 年开始的,因此这是 Swift 3.0 的版本:

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    let size = image.size

    let widthRatio  = targetSize.width  / image.size.width
    let heightRatio = targetSize.height / image.size.height

    // Figure out what our orientation is, and use that to form the rectangle
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
    }

    // This is the rect that we've calculated out and this is what is actually used below
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
}

Details细节

  • Xcode 10.2.1 (10E1001), Swift 5 Xcode 10.2.1 (10E1001),Swift 5

Links链接

Solution解决方案

import UIKit
import CoreGraphics
import Accelerate

extension UIImage {

    public enum ResizeFramework {
        case uikit, coreImage, coreGraphics, imageIO, accelerate
    }

    /// Resize image with ScaleAspectFit mode and given size.
    ///
    /// - Parameter dimension: width or length of the image output.
    /// - Parameter resizeFramework: Technique for image resizing: UIKit / CoreImage / CoreGraphics / ImageIO / Accelerate.
    /// - Returns: Resized image.

    func resizeWithScaleAspectFitMode(to dimension: CGFloat, resizeFramework: ResizeFramework = .coreGraphics) -> UIImage? {

        if max(size.width, size.height) <= dimension { return self }

        var newSize: CGSize!
        let aspectRatio = size.width/size.height

        if aspectRatio > 1 {
            // Landscape image
            newSize = CGSize(width: dimension, height: dimension / aspectRatio)
        } else {
            // Portrait image
            newSize = CGSize(width: dimension * aspectRatio, height: dimension)
        }

        return resize(to: newSize, with: resizeFramework)
    }

    /// Resize image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Parameter resizeFramework: Technique for image resizing: UIKit / CoreImage / CoreGraphics / ImageIO / Accelerate.
    /// - Returns: Resized image.
    public func resize(to newSize: CGSize, with resizeFramework: ResizeFramework = .coreGraphics) -> UIImage? {
        switch resizeFramework {
            case .uikit: return resizeWithUIKit(to: newSize)
            case .coreGraphics: return resizeWithCoreGraphics(to: newSize)
            case .coreImage: return resizeWithCoreImage(to: newSize)
            case .imageIO: return resizeWithImageIO(to: newSize)
            case .accelerate: return resizeWithAccelerate(to: newSize)
        }
    }

    // MARK: - UIKit

    /// Resize image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Returns: Resized image.
    private func resizeWithUIKit(to newSize: CGSize) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(newSize, true, 1.0)
        self.draw(in: CGRect(origin: .zero, size: newSize))
        defer { UIGraphicsEndImageContext() }
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    // MARK: - CoreImage

    /// Resize CI image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Returns: Resized image.
    // https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html
    private func resizeWithCoreImage(to newSize: CGSize) -> UIImage? {
        guard let cgImage = cgImage, let filter = CIFilter(name: "CILanczosScaleTransform") else { return nil }

        let ciImage = CIImage(cgImage: cgImage)
        let scale = (Double)(newSize.width) / (Double)(ciImage.extent.size.width)

        filter.setValue(ciImage, forKey: kCIInputImageKey)
        filter.setValue(NSNumber(value:scale), forKey: kCIInputScaleKey)
        filter.setValue(1.0, forKey: kCIInputAspectRatioKey)
        guard let outputImage = filter.value(forKey: kCIOutputImageKey) as? CIImage else { return nil }
        let context = CIContext(options: [.useSoftwareRenderer: false])
        guard let resultCGImage = context.createCGImage(outputImage, from: outputImage.extent) else { return nil }
        return UIImage(cgImage: resultCGImage)
    }

    // MARK: - CoreGraphics

    /// Resize image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Returns: Resized image.
    private func resizeWithCoreGraphics(to newSize: CGSize) -> UIImage? {
        guard let cgImage = cgImage, let colorSpace = cgImage.colorSpace else { return nil }

        let width = Int(newSize.width)
        let height = Int(newSize.height)
        let bitsPerComponent = cgImage.bitsPerComponent
        let bytesPerRow = cgImage.bytesPerRow
        let bitmapInfo = cgImage.bitmapInfo

        guard let context = CGContext(data: nil, width: width, height: height,
                                      bitsPerComponent: bitsPerComponent,
                                      bytesPerRow: bytesPerRow, space: colorSpace,
                                      bitmapInfo: bitmapInfo.rawValue) else { return nil }
        context.interpolationQuality = .high
        let rect = CGRect(origin: CGPoint.zero, size: newSize)
        context.draw(cgImage, in: rect)

        return context.makeImage().flatMap { UIImage(cgImage: $0) }
    }

    // MARK: - ImageIO

    /// Resize image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Returns: Resized image.
    private func resizeWithImageIO(to newSize: CGSize) -> UIImage? {
        var resultImage = self

        guard let data = jpegData(compressionQuality: 1.0) else { return resultImage }
        let imageCFData = NSData(data: data) as CFData
        let options = [
            kCGImageSourceCreateThumbnailWithTransform: true,
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceThumbnailMaxPixelSize: max(newSize.width, newSize.height)
            ] as CFDictionary
        guard   let source = CGImageSourceCreateWithData(imageCFData, nil),
                let imageReference = CGImageSourceCreateThumbnailAtIndex(source, 0, options) else { return resultImage }
        resultImage = UIImage(cgImage: imageReference)

        return resultImage
    }

    // MARK: - Accelerate

    /// Resize image from given size.
    ///
    /// - Parameter newSize: Size of the image output.
    /// - Returns: Resized image.
    private func resizeWithAccelerate(to newSize: CGSize) -> UIImage? {
        var resultImage = self

        guard let cgImage = cgImage, let colorSpace = cgImage.colorSpace else { return nil }

        // create a source buffer
        var format = vImage_CGImageFormat(bitsPerComponent: numericCast(cgImage.bitsPerComponent),
                                          bitsPerPixel: numericCast(cgImage.bitsPerPixel),
                                          colorSpace: Unmanaged.passUnretained(colorSpace),
                                          bitmapInfo: cgImage.bitmapInfo,
                                          version: 0,
                                          decode: nil,
                                          renderingIntent: .absoluteColorimetric)
        var sourceBuffer = vImage_Buffer()
        defer {
            sourceBuffer.data.deallocate()
        }

        var error = vImageBuffer_InitWithCGImage(&sourceBuffer, &format, nil, cgImage, numericCast(kvImageNoFlags))
        guard error == kvImageNoError else { return resultImage }

        // create a destination buffer
        let destWidth = Int(newSize.width)
        let destHeight = Int(newSize.height)
        let bytesPerPixel = cgImage.bitsPerPixel
        let destBytesPerRow = destWidth * bytesPerPixel
        let destData = UnsafeMutablePointer<UInt8>.allocate(capacity: destHeight * destBytesPerRow)
        defer {
            destData.deallocate()
        }
        var destBuffer = vImage_Buffer(data: destData, height: vImagePixelCount(destHeight), width: vImagePixelCount(destWidth), rowBytes: destBytesPerRow)

        // scale the image
        error = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, numericCast(kvImageHighQualityResampling))
        guard error == kvImageNoError else { return resultImage }

        // create a CGImage from vImage_Buffer
        let destCGImage = vImageCreateCGImageFromBuffer(&destBuffer, &format, nil, nil, numericCast(kvImageNoFlags), &error)?.takeRetainedValue()
        guard error == kvImageNoError else { return resultImage }

        // create a UIImage
        if let scaledImage = destCGImage.flatMap({ UIImage(cgImage: $0) }) {
            resultImage = scaledImage
        }

        return resultImage
    }
}

Usage用法

Get image size获取图像大小

import UIKit

// https://stackoverflow.com/a/55765409/4488252
extension UIImage {
    func getFileSizeInfo(allowedUnits: ByteCountFormatter.Units = .useMB,
                         countStyle: ByteCountFormatter.CountStyle = .memory,
                         compressionQuality: CGFloat = 1.0) -> String? {
        // https://developer.apple.com/documentation/foundation/bytecountformatter
        let formatter = ByteCountFormatter()
        formatter.allowedUnits = allowedUnits
        formatter.countStyle = countStyle
        return getSizeInfo(formatter: formatter, compressionQuality: compressionQuality)
    }

    func getSizeInfo(formatter: ByteCountFormatter, compressionQuality: CGFloat = 1.0) -> String? {
        guard let imageData = jpegData(compressionQuality: compressionQuality) else { return nil }
        return formatter.string(fromByteCount: Int64(imageData.count))
    }
}

Test function测试功能

private func test() {
    guard let img = UIImage(named: "img") else { return }
    printInfo(of: img, title: "original image |")
    let dimension: CGFloat = 2000

    var framework: UIImage.ResizeFramework = .accelerate
    var startTime = Date()
    if let img = img.resizeWithScaleAspectFitMode(to: dimension, resizeFramework: framework) {
        printInfo(of: img, title: "resized image |", with: framework, startedTime: startTime)
    }

    framework = .coreGraphics
    startTime = Date()
    if let img = img.resizeWithScaleAspectFitMode(to: dimension, resizeFramework: framework) {
        printInfo(of: img, title: "resized image |", with: framework, startedTime: startTime)
    }

    framework = .coreImage
    startTime = Date()
    if let img = img.resizeWithScaleAspectFitMode(to: dimension, resizeFramework: framework) {
        printInfo(of: img, title: "resized image |", with: framework, startedTime: startTime)
    }

    framework = .imageIO
    startTime = Date()
    if let img = img.resizeWithScaleAspectFitMode(to: dimension, resizeFramework: framework) {
        printInfo(of: img, title: "resized image |", with: framework, startedTime: startTime)
    }

    framework = .uikit
    startTime = Date()
    if let img = img.resizeWithScaleAspectFitMode(to: dimension, resizeFramework: framework) {
        printInfo(of: img, title: "resized image |", with: framework, startedTime: startTime)
    }
}

private func printInfo(of image: UIImage, title: String, with resizeFramework: UIImage.ResizeFramework? = nil, startedTime: Date? = nil) {
    var description = "\(title) \(image.size)"
    if let startedTime = startedTime { description += ", execution time: \(Date().timeIntervalSince(startedTime))" }
    if let fileSize = image.getFileSizeInfo(compressionQuality: 0.9) { description += ", size: \(fileSize)" }
    if let resizeFramework = resizeFramework { description += ", framework: \(resizeFramework)" }
    print(description)
}

Output输出

original image | (5790.0, 8687.0), size: 17.1 MB
resized image | (1333.0, 2000.0), execution time: 0.8192930221557617, size: 1.1 MB, framework: accelerate
resized image | (1333.0, 2000.0), execution time: 0.44696998596191406, size: 1 MB, framework: coreGraphics
resized image | (1334.0, 2000.0), execution time: 54.172922015190125, size: 1.1 MB, framework: coreImage
resized image | (1333.0, 2000.0), execution time: 1.8765920400619507, size: 1.1 MB, framework: imageIO
resized image | (1334.0, 2000.0), execution time: 0.4638739824295044, size: 1 MB, framework: uikit

For Swift 4 I would just make an extension on UIImage with referencing to self.对于 Swift 4,我只会在 UIImage 上进行扩展,并引用 self.

import UIKit
extension UIImage {
  func resizeImage(targetSize: CGSize) -> UIImage {
    let size = self.size
    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height
    let newSize = widthRatio > heightRatio ?  CGSize(width: size.width * heightRatio, height: size.height * heightRatio) : CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    self.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
  }
}

It's also possible to use AlamofireImage ( https://github.com/Alamofire/AlamofireImage )也可以使用 AlamofireImage ( https://github.com/Alamofire/AlamofireImage )

let size = CGSize(width: 30.0, height: 30.0)
let aspectScaledToFitImage = image.af_imageAspectScaled(toFit: size)

The function in the previous post gave me a blurry result.上一篇文章中的函数给了我一个模糊的结果。

For Swift 5.0 and iOS 12适用于 Swift 5.0 和 iOS 12

extension UIImage {
    func imageResized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

use:用:

let image = #imageLiteral(resourceName: "ic_search")
cell!.search.image = image.imageResized(to: cell!.search.frame.size)

Swift 3 Version and Extension style Swift 3 版本和扩展风格

This answer come from @Kirit Modi.这个答案来自@Kirit Modi。

extension UIImage {

    func resizeImage(targetSize: CGSize) -> UIImage {
        let size = self.size

        let widthRatio  = targetSize.width  / size.width
        let heightRatio = targetSize.height / size.height

        // Figure out what our orientation is, and use that to form the rectangle
        var newSize: CGSize
        if(widthRatio > heightRatio) {
            newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
        } else {
            newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
        }

        // This is the rect that we've calculated out and this is what is actually used below
        let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

        // Actually do the resizing to the rect using the ImageContext stuff
        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        self.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

Swift 4, extension version, NO WHITE LINE ON EDGES. Swift 4,扩展版,边缘无白线。

Nobody seems to be mentioning that if image.draw() is called with non-integer values, resulting image could show a white line artifact at the right or bottom edge.似乎没有人提到如果使用非整数值调用image.draw() ,则生成的图像可能会在右侧或底部边缘显示白线伪影。

extension UIImage {

    func scaled(with scale: CGFloat) -> UIImage? {
        // size has to be integer, otherwise it could get white lines
        let size = CGSize(width: floor(self.size.width * scale), height: floor(self.size.height * scale))
        UIGraphicsBeginImageContext(size)
        draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

Swift 4 Version斯威夫特 4 版本

extension UIImage {
    func resizeImage(_ newSize: CGSize) -> UIImage? {
        func isSameSize(_ newSize: CGSize) -> Bool {
            return size == newSize
        }

        func scaleImage(_ newSize: CGSize) -> UIImage? {
            func getScaledRect(_ newSize: CGSize) -> CGRect {
                let ratio   = max(newSize.width / size.width, newSize.height / size.height)
                let width   = size.width * ratio
                let height  = size.height * ratio
                return CGRect(x: 0, y: 0, width: width, height: height)
            }

            func _scaleImage(_ scaledRect: CGRect) -> UIImage? {
                UIGraphicsBeginImageContextWithOptions(scaledRect.size, false, 0.0);
                draw(in: scaledRect)
                let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
                UIGraphicsEndImageContext()
                return image
            }
            return _scaleImage(getScaledRect(newSize))
        }

        return isSameSize(newSize) ? self : scaleImage(newSize)!
    }
}

Updated Swift 5 version that uses the latest UIGraphicsImageRenderer API.更新的Swift 5版本使用最新的UIGraphicsImageRenderer API。

extension UIImage {
    public func resized(to target: CGSize) -> UIImage {
        let ratio = min(
            target.height / size.height, target.width / size.width
        )
        let new = CGSize(
            width: size.width * ratio, height: size.height * ratio
        )
        let renderer = UIGraphicsImageRenderer(size: new)
        return renderer.image { _ in
            self.draw(in: CGRect(origin: .zero, size: new))
        }
    }
}

UIImage Extension Swift 5 UIImage 扩展Swift 5

extension UIImage {
    func resize(_ width: CGFloat, _ height:CGFloat) -> UIImage? {
        let widthRatio  = width / size.width
        let heightRatio = height / size.height
        let ratio = widthRatio > heightRatio ? heightRatio : widthRatio
        let newSize = CGSize(width: size.width * ratio, height: size.height * ratio)
        let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        self.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}


Use : UIImage().resize(200, 300)使用: UIImage().resize(200, 300)

All of the listed answers so far seem to result in an image of a reduced size, however the size isn't measured in pixels.到目前为止,所有列出的答案似乎都会导致图像尺寸缩小,但是尺寸不是以像素为单位测量的。 Here's a Swift 5, pixel-based resize .这是一个Swift 5,基于像素的 resize

extension UIImage {
    func resize(_ max_size: CGFloat) -> UIImage {
        // adjust for device pixel density
        let max_size_pixels = max_size / UIScreen.main.scale
        // work out aspect ratio
        let aspectRatio =  size.width/size.height
        // variables for storing calculated data
        var width: CGFloat
        var height: CGFloat
        var newImage: UIImage
        if aspectRatio > 1 {
            // landscape
            width = max_size_pixels
            height = max_size_pixels / aspectRatio
        } else {
            // portrait
            height = max_size_pixels
            width = max_size_pixels * aspectRatio
        }
        // create an image renderer of the correct size
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: width, height: height), format: UIGraphicsImageRendererFormat.default())
        // render the image
        newImage = renderer.image {
            (context) in
            self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
        }
        // return the image
        return newImage
    }
} 

Usage:用法:

image.resize(500)

Swift 4 Solution- Swift 4 解决方案-

Use this function使用这个功能

func image(with image: UIImage, scaledTo newSize: CGSize) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    drawingImageView.image = newImage
    return newImage ?? UIImage()
}

Calling a function:-调用函数:-

image(with: predictionImage, scaledTo: CGSize(width: 28.0, height: 28.0)

here 28.0 is the pixel size that you want to set这里 28.0 是您要设置的像素大小

Swift 4.2 version of @KiritModi answer Swift 4.2 版本的@KiritModi 答案

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    let size = image.size

    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height

    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio, height: size.height *      widthRatio)
    }

    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
}

Here's a general method (in Swift 5) for downscaling an image to fit a size.这是缩小图像以适应尺寸的通用方法(在 Swift 5 中)。 The resulting image can have the same aspect ratio as the original, or it can be the target size with the original image centered in it.生成的图像可以与原始图像具有相同的纵横比,也可以是目标尺寸,原始图像居中。 If the image is smaller than the target size, it is not resized.如果图像小于目标尺寸,则不会调整其大小。

extension UIImage {
    func scaledDown(into size:CGSize, centered:Bool = false) -> UIImage {
        var (targetWidth, targetHeight) = (self.size.width, self.size.height)
        var (scaleW, scaleH) = (1 as CGFloat, 1 as CGFloat)
        if targetWidth > size.width {
            scaleW = size.width/targetWidth
        }
        if targetHeight > size.height {
            scaleH = size.height/targetHeight
        }
        let scale = min(scaleW,scaleH)
        targetWidth *= scale; targetHeight *= scale
        let sz = CGSize(width:targetWidth, height:targetHeight)
        if !centered {
            return UIGraphicsImageRenderer(size:sz).image { _ in
                self.draw(in:CGRect(origin:.zero, size:sz))
            }
        }
        let x = (size.width - targetWidth)/2
        let y = (size.height - targetHeight)/2
        let origin = CGPoint(x:x,y:y)
        return UIGraphicsImageRenderer(size:size).image { _ in
            self.draw(in:CGRect(origin:origin, size:sz))
        }
    }
}

Here you have two simple functions of UIImage extension:这里有两个简单的UIImage扩展功能:

func scaledWithMaxWidthOrHeightValue(value: CGFloat) -> UIImage? {

    let width = self.size.width
    let height = self.size.height

    let ratio = width/height

    var newWidth = value
    var newHeight = value

    if ratio > 1 {
        newWidth = width * (newHeight/height)
    } else {
        newHeight = height * (newWidth/width)
    }

    UIGraphicsBeginImageContextWithOptions(CGSize(width: newWidth, height: newHeight), false, 0)

    draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
}

func scaled(withScale scale: CGFloat) -> UIImage? {

    let size = CGSize(width: self.size.width * scale, height: self.size.height * scale)

    UIGraphicsBeginImageContextWithOptions(size, false, 0)

    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

    let image = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

calling of resizeimage method调用resizeimage方法

let image1 = resizeimage(image: myimage.image!, withSize: CGSize(width:200, height: 200))

method for resizeing image调整图像大小的方法

func resizeimage(image:UIImage,withSize:CGSize) -> UIImage {
        var actualHeight:CGFloat = image.size.height
        var actualWidth:CGFloat = image.size.width
        let maxHeight:CGFloat = withSize.height
        let maxWidth:CGFloat = withSize.width
        var imgRatio:CGFloat = actualWidth/actualHeight
        let maxRatio:CGFloat = maxWidth/maxHeight
        let compressionQuality = 0.5
        if (actualHeight>maxHeight||actualWidth>maxWidth) {
            if (imgRatio<maxRatio){
                //adjust width according to maxHeight
                imgRatio = maxHeight/actualHeight
                actualWidth = imgRatio * actualWidth
                actualHeight = maxHeight
            }else if(imgRatio>maxRatio){
                // adjust height according to maxWidth
                imgRatio = maxWidth/actualWidth
                actualHeight = imgRatio * actualHeight
                actualWidth = maxWidth
            }else{
                actualHeight = maxHeight
                actualWidth = maxWidth
            }
        }
        let rec:CGRect = CGRect(x:0.0,y:0.0,width:actualWidth,height:actualHeight)
        UIGraphicsBeginImageContext(rec.size)
        image.draw(in: rec)
        let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        let imageData = UIImageJPEGRepresentation(image, CGFloat(compressionQuality))
        UIGraphicsEndImageContext()
        let resizedimage = UIImage(data: imageData!)
        return resizedimage!
    }

Swift 5 version respecting ratio (scaleToFill) and centering image: Swift 5 版本尊重比例(scaleToFill)和居中图像:

extension UIImage {
    func resized(to newSize: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: newSize).image { _ in
            let hScale = newSize.height / size.height
            let vScale = newSize.width / size.width
            let scale = max(hScale, vScale) // scaleToFill
            let resizeSize = CGSize(width: size.width*scale, height: size.height*scale)
            var middle = CGPoint.zero
            if resizeSize.width > newSize.width {
                middle.x -= (resizeSize.width-newSize.width)/2.0
            }
            if resizeSize.height > newSize.height {
                middle.y -= (resizeSize.height-newSize.height)/2.0
            }
            
            draw(in: CGRect(origin: middle, size: resizeSize))
        }
    }
}

Example is for image minimize to 1024 and less示例是将图像最小化到 1024 及更少

func resizeImage(image: UIImage) -> UIImage { func resizeImage(image: UIImage) -> UIImage {

    if image.size.height >= 1024 && image.size.width >= 1024 {

        UIGraphicsBeginImageContext(CGSize(width:1024, height:1024))
        image.draw(in: CGRect(x:0, y:0, width:1024, height:1024))

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!

    }
    else if image.size.height >= 1024 && image.size.width < 1024
    {

        UIGraphicsBeginImageContext(CGSize(width:image.size.width, height:1024))
        image.draw(in: CGRect(x:0, y:0, width:image.size.width, height:1024))

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!

    }
    else if image.size.width >= 1024 && image.size.height < 1024
    {

        UIGraphicsBeginImageContext(CGSize(width:1024, height:image.size.height))
        image.draw(in: CGRect(x:0, y:0, width:1024, height:image.size.height))

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!

    }
    else
    {
        return image
    }

}

You can use this for fit image at Swift 3 ;您可以在Swift 3 中将其用于适合图像;

extension UIImage {
    func resizedImage(newSize: CGSize) -> UIImage {
        // Guard newSize is different
        guard self.size != newSize else { return self }

        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
        self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }

    func resizedImageWithinRect(rectSize: CGSize) -> UIImage {
        let widthFactor = size.width / rectSize.width
        let heightFactor = size.height / rectSize.height

        var resizeFactor = widthFactor
        if size.height > size.width {
            resizeFactor = heightFactor
        }

        let newSize = CGSize(width: size.width/resizeFactor, height: size.height/resizeFactor)
        let resized = resizedImage(newSize: newSize)
        return resized
    }
}

Usage;用法;

let resizedImage = image.resizedImageWithinRect(rectSize: CGSize(width: 1900, height: 1900))

SWIFT 5 - XCODE 12 -- RESIZE IMAGE & No White line SWIFT 5 - XCODE 12 - 调整图像大小和无白线

I used a wonderful solution above for Swift 5. And I changed one bit to include the term "floor" as I was getting a white line around my resized images.我在上面为 Swift 5 使用了一个很好的解决方案。我改变了一点以包含术语“地板”,因为我在调整大小的图像周围出现了一条白线。 This rounds it to the nearest pixel or something so it looks great!这会将它四舍五入到最近的像素或其他东西,所以它看起来很棒! I also had to change the syntax around the image name when the function is called (last line).我还必须在调用函数时更改图像名称周围的语法(最后一行)。

//method for resizing image //调整图片大小的方法

func resizeimage(image:UIImage,withSize:CGSize) -> UIImage {
    var actualHeight:CGFloat = image.size.height
    var actualWidth:CGFloat = image.size.width
    let maxHeight:CGFloat = withSize.height
    let maxWidth:CGFloat = withSize.width
    var imgRatio:CGFloat = actualWidth/actualHeight
    let maxRatio:CGFloat = maxWidth/maxHeight
    let compressionQuality = 0.5
    if (actualHeight>maxHeight||actualWidth>maxWidth) {
        if (imgRatio<maxRatio){
            //adjust width according to maxHeight
            imgRatio = maxHeight/actualHeight
            actualWidth = floor(imgRatio * actualWidth)
            actualHeight = maxHeight
        }else if(imgRatio>maxRatio){
            // adjust height according to maxWidth
            imgRatio = maxWidth/actualWidth
            actualHeight = imgRatio * actualHeight
            actualWidth = maxWidth
        }else{
            actualHeight = maxHeight
            actualWidth = maxWidth
        }
    }
    let rec:CGRect = CGRect(x:0.0,y:0.0,width:actualWidth,height:actualHeight)
    UIGraphicsBeginImageContext(rec.size)
    image.draw(in: rec)
    let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    let imageData = UIImageJPEGRepresentation(image, CGFloat(compressionQuality))
    UIGraphicsEndImageContext()
    let resizedimage = UIImage(data: imageData!)
    return resizedimage!
}

//calling of resizeimage method: //调用resizeimage方法:

let myimage = UIImage(named: "imagename")让 myimage = UIImage(named: "imagename")

let image1 = resizeimage(image: myimage!, withSize: CGSize(width:50, height: 50)).withRenderingMode(.alwaysOriginal)让 image1 = resizeimage(image: myimage!, withSize: CGSize(width:50, height: 50)).withRenderingMode(.alwaysOriginal)

I am making an app for iOS, using Swift and Parse.com我正在使用Swift和Parse.com开发适用于iOS的应用程序

I am trying to let the user select a picture from an image picker and then resize the selected image to 200x200 pixels before uploading to my backend.我试图让用户从图像选择器中选择一张图片,然后将所选图像的大小调整为200x200像素,然后再上传到我的后端。

Parse.com have a tutorial for an Instagram copy app called "AnyPic" which gives this code for resizing images, but it is in Objective-C.... Parse.com有一个用于Instagram复制应用程序的教程,名为“ AnyPic”,其中提供了用于调整图像大小的代码,但它位于Objective-C中。

// Resize the image to be square (what is shown in the preview)
UIImage *resizedImage = [anImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
        bounds:CGSizeMake(560.0f, 560.0f)
        interpolationQuality:kCGInterpolationHigh];
// Create a thumbnail and add a corner radius for use in table views
UIImage *thumbnailImage = [anImage thumbnailImage:86.0f
        transparentBorder:0.0f
        cornerRadius:10.0f
        interpolationQuality:kCGInterpolationDefault];

How would I create a 200x200px version of the selected picture (to then upload) in Swift?如何在Swift中为所选图片创建200x200px版本(然后上传)?

And, what is the thumbnailImage function doing?而且,thumbnailImage函数在做什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM