วิธีปรับขนาดภาพใน Swift


94

ฉันกำลังสร้างแอปสำหรับ iOS โดยใช้Swiftและ Parse.com

ฉันกำลังพยายามให้ผู้ใช้เลือกรูปภาพจากตัวเลือกรูปภาพจากนั้นปรับขนาดรูปภาพที่เลือกเป็น 200x200 พิกเซลก่อนที่จะอัปโหลดไปยังแบ็กเอนด์ของฉัน

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

ฉันจะสร้างรูปภาพที่เลือกเวอร์ชัน 200x200px (จากนั้นอัปโหลด) ใน Swift ได้อย่างไร

และฟังก์ชันภาพขนาดย่อมีไว้ทำอะไร?

คำตอบ:


206

ดูโพสต์บล็อกของฉันปรับขนาดภาพด้วยความรวดเร็วและมีวัตถุประสงค์ Cสำหรับรายละเอียดเพิ่มเติม

ฟังก์ชั่นปรับขนาดภาพได้อย่างรวดเร็วดังต่อไปนี้

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 = CGSizeMake(size.width * heightRatio, size.height * heightRatio)
    } else {
        newSize = CGSizeMake(size.width * widthRatio,  size.height * widthRatio)
    }

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

    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.drawInRect(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) ได้โดยตรง
Kirit Modi

2
โดยปกติคุณต้องการให้UIGraphicsBeginImageContextWithOptionsพารามิเตอร์สุดท้ายเป็น0.0เช่นนี้จะเป็นขนาดของอุปกรณ์
vikingosegundo

คุณสามารถลดความซับซ้อนของการคำนวณได้โดยใช้ AVMakeRect ใน AVFoundation สร้าง targetRect ด้วยจุดเริ่มต้น (0,0) และขนาด targetSize จากนั้น rect = AVMakeRect (มุมมอง: image.size, insideRect: targetRect)
Dale

1
คุณสามารถปรับปรุงคุณภาพเมื่อขยายขนาดโดยการตั้งค่าคุณภาพการแก้ไขในบริบทกราฟิก UIGraphicsGetCurrentContext () ?. interpolationQuality = .high
Dale

5
หากคุณได้รับ "GCSizeMake ไม่พร้อมใช้งานใน Swift" ให้ใช้ CGSize (กว้าง: 200.0 สูง: 200.0)
Islam Abdalla

38

สำหรับ 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
        }
    }

ฉันจะเรียกฟังก์ชันนี้ว่าอย่างไร?
ICT1901

2
@DavidDelMonte คุณสามารถเรียกเมธอดนี้บนวัตถุ UIImage myImage.resizeImage(...).
Aweda

ภาพเหล่านี้ถูกปรับขนาดอย่างไร? ใช้วิธีการแก้ไขแบบใด คุณสามารถเลือกวิธีการแก้ไขได้หรือไม่?
Moondra

32

เนื่องจากคำตอบของ @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!
}

และคุณเรียกใช้ฟังก์ชันนี้อย่างไร?
Konstantinos Natsios

2
ให้ขนาดย่อ = resizeImage (ภาพ: fullsizeImage, CGSize.init (กว้าง: 70, สูง: 70))
arjavlad

2
ฉันอยากจะแนะนำให้แทนที่ 1.0 ในมาตราส่วนด้วย UIScreen.main.scale เพื่อหลีกเลี่ยงภาพที่ไม่ชัด
PSchuette

ภาพเหล่านี้ถูกปรับขนาดอย่างไร? ใช้วิธีการแก้ไขแบบใด คุณสามารถเลือกวิธีการแก้ไขได้หรือไม่?
Moondra

23

สำหรับ Swift 4 ฉันจะสร้างส่วนขยายบน UIImage โดยอ้างถึงตัวเอง

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

22

รายละเอียด

  • 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

ทำการทดสอบบนอุปกรณ์ใด
Juan Boero

1
@JuanBoero iPhone 7 plus, iPhone X
Vasily Bodnarchuk

19

นอกจากนี้ยังสามารถใช้ AlamofireImage ( https://github.com/Alamofire/AlamofireImage )

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

ฟังก์ชั่นในโพสต์ก่อนหน้านี้ให้ผลลัพธ์ที่ไม่ชัดเจน


1
ขอบคุณในตัวเองที่รวดเร็ว 3 ภาพของคุณview.sizeThatFits (ขนาด) ทำงาน
BHAVIK PANCHAL

ประหยัดเวลาและไม่ใช้สิ่งนี้ ขนาดที่คุณระบุขึ้นอยู่กับขนาดของอุปกรณ์ไม่ใช่พิกเซลที่คุณต้องการ: stackoverflow.com/questions/55930320/…
Alex Ritter

11

เวอร์ชัน 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!
    }
}

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)

6

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
    }

5

เวอร์ชัน 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)!
    }
}

3

คำตอบ @KiritModi เวอร์ชัน Swift 4.2

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

2

การเรียกวิธีการปรับขนาดภาพ

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

2

โซลูชัน 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 นี่คือขนาดพิกเซลที่คุณต้องการตั้งค่า


การกำหนดด้านบนการส่งคืนฟังก์ชันไม่เกี่ยวข้องและควรลบออก:
BlueskyMed

2

นี่เป็นวิธีการทั่วไป (ใน 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))
        }
    }
}

2

คำตอบทั้งหมดในรายการจนถึงตอนนี้ดูเหมือนจะทำให้ภาพมีขนาดลดลง แต่ขนาดไม่ได้วัดเป็นพิกเซล นี่คือสวิฟท์ 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)

1

ตัวอย่างสำหรับย่อรูปภาพให้เหลือ 1024 และน้อยกว่า

func resizeImage (รูปภาพ: 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
    }

}

1

คุณสามารถใช้สิ่งนี้เพื่อให้พอดีกับภาพที่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))

1

ที่นี่คุณมีฟังก์ชั่นการ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คุณไม่ควรบังคับให้แกะตัวเลือกในการตอบแทนตั้งแต่การประกาศของคุณเป็นตัวเลือก
Andy Ibanez

1

การโยนคำตอบที่ได้รับการยอมรับในเวอร์ชันของฉันมาที่นี่เพื่อให้ทำงานได้ดีกับ Swift 5 โซลูชันนี้ไม่ได้บังคับให้แกะรูปภาพที่ได้ออกมาทำให้เป็นโซลูชันที่ปลอดภัยและสะอาดกว่าเล็กน้อย

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
        )
        UIGraphicsBeginImageContextWithOptions(new, false, 1.0)
        draw(in: CGRect(origin: .zero, size: new))
        defer { UIGraphicsEndImageContext() }
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

1

ส่วนขยาย 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 () ปรับขนาด (200, 300)


-1

SWIFT 5 กับ newImage = UIImage(cgImage: cgImage)

func scaleImage(toSize newSize: CGSize) -> UIImage? {
            var newImage: UIImage?
            let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
            UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
            if let context = UIGraphicsGetCurrentContext(), let cgImage = self.cgImage {
                context.interpolationQuality = .high
                let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height)
                context.concatenate(flipVertical)
                context.draw(cgImage, in: newRect)
                newImage = UIImage(cgImage: cgImage)
                UIGraphicsEndImageContext()

            }

            return newImage
   }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.