Resize an image without distorting or cropping an image

Users upload an image of any size, and we need to resize it so that it becomes a square without distorting or cropping the image. Basically, it should do something similar to the Aspect Fit content mode in the image view. So, if we have a PNG image of 200x100 pixels in size, I want to make it 200x200px and get 100px high in transparent space. It should not crop the image to 200x200.

I tried using this image processor, but it does not do what I want. https://github.com/gavinbunney/Toucan . It only crop the image.

How can I do this quickly, and is there a structure that is better than the one I mentioned above to make it easier. Basically, I'm looking for the easiest way to do this.

+4
source share
1 answer

Putting this as an answer, as well as an example use ...

The scaling code is not mine, it is: https://gist.github.com/tomasbasham/10533743#gistcomment-1988471

Here is the code that you can run on the playground for testing:

import UIKit
import PlaygroundSupport

let container = UIView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))

container.backgroundColor = UIColor.blue

PlaygroundPage.current.liveView = container


// MARK: - Image Scaling.
extension UIImage {

    /// Represents a scaling mode
    enum ScalingMode {
        case aspectFill
        case aspectFit

        /// Calculates the aspect ratio between two sizes
        ///
        /// - parameters:
        ///     - size:      the first size used to calculate the ratio
        ///     - otherSize: the second size used to calculate the ratio
        ///
        /// - return: the aspect ratio between the two sizes
        func aspectRatio(between size: CGSize, and otherSize: CGSize) -> CGFloat {
            let aspectWidth  = size.width/otherSize.width
            let aspectHeight = size.height/otherSize.height

            switch self {
            case .aspectFill:
                return max(aspectWidth, aspectHeight)
            case .aspectFit:
                return min(aspectWidth, aspectHeight)
            }
        }
    }

    /// Scales an image to fit within a bounds with a size governed by the passed size. Also keeps the aspect ratio.
    ///
    /// - parameter:
    ///     - newSize:     the size of the bounds the image must fit within.
    ///     - scalingMode: the desired scaling mode
    ///
    /// - returns: a new scaled image.
    func scaled(to newSize: CGSize, scalingMode: UIImage.ScalingMode = .aspectFill) -> UIImage {

        let aspectRatio = scalingMode.aspectRatio(between: newSize, and: size)

        /* Build the rectangle representing the area to be drawn */
        var scaledImageRect = CGRect.zero

        scaledImageRect.size.width  = size.width * aspectRatio
        scaledImageRect.size.height = size.height * aspectRatio
        scaledImageRect.origin.x    = (newSize.width - size.width * aspectRatio) / 2.0
        scaledImageRect.origin.y    = (newSize.height - size.height * aspectRatio) / 2.0

        /* Draw and retrieve the scaled image */
        UIGraphicsBeginImageContext(newSize)

        draw(in: scaledImageRect)
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()

        return scaledImage!
    }
}

if let srcimg = UIImage(named: "flags") {

    let w = srcimg.size.width
    let h = srcimg.size.height

    // determine whether width or height is greater
    let longer = max(w, h)

    // create a Square size
    let sz = CGSize(width: longer, height: longer)

    // call scaling function to scale the image to the Square dimensions,
    // using "aspect fit"
    let newImage = srcimg.scaled(to: sz, scalingMode: .aspectFit)

    // create a UIImageView with the resulting image
    let v = UIImageView(image: newImage)
    v.backgroundColor = UIColor.white

    // add it to the container view
    container.addSubview(v)

}
0
source

Source: https://habr.com/ru/post/1678717/


All Articles