How to convert pixel dimension to CG Size in Swift?

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 answers

  • answered 2020-07-05 04:48 Rage

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

  • answered 2020-07-05 05:29 Leo Dabus

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