How to convert pixel dimension to CG Size in Swift?

1.5k views Asked by At

I have large images uploaded by users in Swift and I need to resize them all to 100x100px to create thumbnails to store in my server. So far I have found that this resizes an image given a CGSize:

func resizedImage(image: UIImage, size: CGSize) -> UIImage? {
    let renderer = UIGraphicsImageRenderer(size: size)
    return renderer.image { (context) in
        image.draw(in: CGRect(origin: .zero, size: size))
    }
}

Is there any way to create a CGSize knowing that my target size is strictly 100x100px?

2

There are 2 answers

4
Rage On

Got this to work:

extension UIImage {
    func resizedImage(pixelSize: (width: Int, height: Int)) -> UIImage? {
            var size = CGSize(width: CGFloat(pixelSize.width) / UIScreen.main.scale, height: CGFloat(pixelSize.height) / UIScreen.main.scale)

            let rect = AVMakeRect(aspectRatio: self.size, insideRect: CGRect(x:0, y:0, width: size.width, height: size.height))
    
            let renderer = UIGraphicsImageRenderer(size: size)
            return renderer.image { (context) in
                self.draw(in: rect)
            }
        }
}
0
Leo Dabus On

You should initialize your render based on the user device scale and multiply its width and height instead of dividing it:

extension UIImage {
    func aspectFitScaled(to size: CGSize) -> UIImage {
        let format = imageRendererFormat
        format.opaque = false
        format.scale = UIScreen.main.scale
        let isLandscape = self.size.width > self.size.height
        let ratio = isLandscape ? size.width / self.size.width : size.height / self.size.height
        let drawSize = self.size.scaled(by: ratio)
        let x = (size.width - drawSize.width) / 2
        let y = (size.height - drawSize.height) / 2
        let origin = CGPoint(x: x, y: y)
        return UIGraphicsImageRenderer(size: size, format: format).image { _ in
            draw(in: CGRect(origin: origin, size: drawSize))
        }
    }
}

usage:

class ViewController: UIViewController {
    // imageView frame is 200 x 200
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()

        // original image size is (719.0, 808.0)
        let image = UIImage(data: try! Data(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!))!
        imageView.backgroundColor = .gray
        
        let ivImage = image.aspectFitScaled(to: imageView.frame.size)
        imageView.image = ivImage
        print("ivImage.size", ivImage.size)   // (200.0, 200.0)
        print("ivImage.scale", ivImage.scale) // screen scale 3.0 iPhone 8 Plus

        // lets check the real image dimension
        let data = ivImage.jpegData(compressionQuality: 1)!
        let savedSize = UIImage(data: data)!.size
        print("savedSize", savedSize) // savedSize (600.0, 600.0)
    }
}