【问题标题】:How to Resize image in Swift?如何在 Swift 中调整图像大小?
【发布时间】:2015-09-27 15:31:49
【问题描述】:

我正在使用 Swift 和 Parse.com

为 iOS 制作应用程序

我试图让用户从图像选择器中选择一张图片,然后将所选图像的大小调整为 200x200 像素,然后再上传到我的后端。

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];

如何在 Swift 中创建所选图片的 200x200px 版本(然后上传)?

还有,thumbnailImage 函数在做什么?

【问题讨论】:

    标签: ios swift uiimage


    【解决方案1】:

    请参阅我的博文Resize image in swift and objective C,了解更多详情。

    swift中的图像调整功能如下。

    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
    }
    

    使用上面的函数,用 200*200 调整图片大小,如下代码

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

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

    【讨论】:

    • 您可以直接在 UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0) 中传递目标尺寸。
    • 通常你希望UIGraphicsBeginImageContextWithOptions最后一个参数是0.0,因为这将是我们设备的规模。
    • 您可以通过在 AVFoundation 中使用 AVMakeRect 来简化计算。用原点 (0,0) 和大小 targetSize 创建一个 targetRect,然后 rect = AVMakeRect(aspectRatio: image.size, insideRect:targetRect)
    • 您可以通过在图形上下文 UIGraphicsGetCurrentContext()?.interpolationQuality = .high 上设置插值质量来提高放大时的质量
    • 如果您收到“GCSizeMake 在 Swift 中不可用”,请使用 CGSize(width:200.0, height:200.0)
    【解决方案2】:

    适用于 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
            }
        }
    

    【讨论】:

    • 我该如何调用这个函数?
    • @DavidDelMonte 您可以在 UIImage 对象上调用此方法。 myImage.resizeImage(...).
    • 如何调整这些图像的大小?使用了哪些插值方法?可以选择插值方法吗?
    【解决方案3】:

    详情

    • Xcode 10.2.1 (10E1001)、Swift 5

    链接

    解决方案

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

    用法

    获取图片大小

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

    测试功能

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

    输出

    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
    

    【讨论】:

    • 在什么设备上运行了测试?
    • @JuanBoero iPhone 7 plus,iPhone X
    【解决方案4】:

    由于@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!
    }
    

    【讨论】:

    • 例如你如何调用这个函数?
    • 让 thumbnail = resizeImage(image: fullsizeImage, CGSize.init(width: 70, height: 70))
    • 我建议将 1.0 比例替换为 UIScreen.main.scale 以避免图像模糊
    • 如何调整这些图像的大小?使用了哪些插值方法?可以选择插值方法吗?
    【解决方案5】:

    对于 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!
      }
    }
    

    【讨论】:

      【解决方案6】:

      也可以使用 AlamofireImage (https://github.com/Alamofire/AlamofireImage)

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

      上一篇文章中的函数给了我一个模糊的结果。

      【讨论】:

      • 谢谢。在 swift 3 self.yourimageview.sizeThatFits(size) 工作中。
      • 为自己节省一些时间,不要使用它。您指定的大小基于设备比例,而不是您想要的像素:stackoverflow.com/questions/55930320/…
      【解决方案7】:

      适用于 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))
              }
          }
      }
      

      使用:

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

      【讨论】:

      • 看起来很不错,小巧高效!但它(还)不尊重比率,这通常是一个问题;)
      • 我在 11 个新行中添加了 scaleToFill,但由于这里有很多解决方案,所以暂时不发布。如果有人有兴趣 ping 我
      【解决方案8】:

      Swift 3 版本和扩展风格

      这个答案来自@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!
          }
      }
      

      【讨论】:

        【解决方案9】:

        更新了 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))
                }
            }
        }
        

        【讨论】:

          【解决方案10】:

          Swift 4,扩展版本,边缘没有白线。

          似乎没有人提到如果使用非整数值调用 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
              }
          

          【讨论】:

          • 太棒了。肯定有这个问题,这解决了它。谢谢!
          【解决方案11】:

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

          【讨论】:

            【解决方案12】:

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

            【讨论】:

            • 不错的补充!有没有办法让图像不剪辑到边界,同时保持比例填充模式?
            【解决方案13】:

            到目前为止,所有列出的答案似乎都导致图像尺寸减小,但尺寸不是以像素为单位测量的。这是 Swift 5,基于像素的调整大小

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

            用法:

            image.resize(500)
            

            【讨论】:

            • 目前这是唯一正确的答案。其他函数不根据像素密度调整大小,导致图像的实际大小为传递参数的 2 倍或 3 倍(Retina 或 Super Retina)。
            【解决方案14】:

            Swift 4 解决方案-

            使用此功能

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

            调用函数:-

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

            这里 28.0 是您要设置的像素大小

            【讨论】:

            • 函数返回上面的赋值是多余的,应该删除:
            【解决方案15】:

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

            【讨论】:

              【解决方案16】:

              这是一种缩小图像以适应尺寸的通用方法(在 Swift 5 中)。生成的图像可以具有与原始图像相同的纵横比,也可以是目标大小,原始图像居中。如果图像小于目标大小,则不会调整大小。

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

              【讨论】:

                【解决方案17】:

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

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

                【讨论】:

                • 它有帮助。谢谢。
                【解决方案18】:

                resizeimage方法的调用

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

                调整图片大小的方法

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

                【讨论】:

                  【解决方案19】:

                  这里有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
                  }
                  

                  【讨论】:

                  • 你不应该强制解开返回中的可选参数,因为你的声明是可选的UIimage
                  【解决方案20】:

                  示例是将图像最小化到 1024 及以下

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

                  【讨论】:

                    【解决方案21】:

                    您可以在 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
                        }
                    }
                    

                    用法;

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

                    【讨论】:

                      【解决方案22】:

                      SWIFT 5 - XCODE 12 -- 调整图像大小并且没有白线

                      我在上面为 Swift 5 使用了一个很棒的解决方案。我做了一点改动,将“地板”一词包括在内,因为我在调整大小的图像周围出现了一条白线。这会将它四舍五入到最近的像素或其他东西,所以它看起来很棒!调用函数时,我还必须更改图像名称周围的语法(最后一行)。

                      //调整图片大小的方法

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

                      //resizeimage方法的调用:

                      让 myimage = UIImage(named: "imagename")

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

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-05-24
                        • 2020-10-02
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-05-16
                        相关资源
                        最近更新 更多