Scale down a very large sized image to very small sized image without distortion and quality loss

854 views Asked by At

I am receiving an image from backend that is of a large size as i have to place the same image as profile picture and show the same image on bottom bar in tab bar of size 30x30. I tried to scale down image in various ways but nothing is working.

Tried Alamofire's method which also didn't worked(the image appears to be blurred and distorted):

func resizeImageWithoutDistortion(image: UIImage, size : CGSize) -> UIImage{


    // 1. Scale image to size disregarding aspect ratio
    let scaledImage = image.af_imageScaled(to: size)

    // 2. Scale image to fit within specified size while maintaining aspect ratio
    let aspectScaledToFitImage = image.af_imageAspectScaled(toFit: size)

    // 3. Scale image to fill specified size while maintaining aspect ratio
    let aspectScaledToFillImage = image.af_imageAspectScaled(toFill: size)

    return scaledImage.roundImage()
}

Also tried as follows which also didn't worked:

func resizeImage(_ newWidth: CGFloat) -> UIImage {

        let ratio = size.width / size.height
        if ratio > 1 {
            UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newWidth))
            draw(in: CGRect(x: newWidth * ratio / 2 - newWidth, y: 0, width: newWidth * ratio, height: newWidth))
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            return newImage!.roundImage()
        } else {
            UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newWidth))
            draw(in: CGRect(x: 0, y: (newWidth / ratio - newWidth) / 2 * (-1), width: newWidth, height: newWidth / ratio))
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            return newImage!.roundImage()
        }
    }

In the screenshot the image in bottom is very distorted.enter image description here

1

There are 1 answers

2
AudioBubble On

Ishika, your problem is not the quality loss. Your problem is that you don't take the iOS Scaling into consideration.

Points and Pixels are not the same thing.

If you have an UIImageView in W: 30 H: 30 (points) to calculate your Image in pixels to show it clearly without affecting the quality, you need to have an Image pixel size of:

30 * UIScreen.main.scale = 60 pixels (if 2X scale)

or

30 * UIScreen.main.scale = 90 pixels (if 3x scales)

This is also the same reason why you need to provide iOS with @2x and @3x scaled images.

So if you want to resize your UIImage to a smaller size you need to take scaling into consideration. Otherwise your Images will be scaled to fill out your UIImageView and they will become blurry because the UIImageView is bigger than the UIImage size.

A good way to see this is if you set your yourImageView.contentMode = .Center you will notice the UIImage is smaller than the UIImageView itself.

I don't code in Swift, so I cant provide you with direct code ( to tired to translate) but if you look at other threads:

scale image to smaller size in swift3

You see that your UIGraphicsBeginImageContext is for example missing the scale input.

scale

The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.

Edit: In your case, something like this:

newWidth = newWidth / UIScreen.main.scale

UIGraphicsBeginImageContextWithOptions(CGSize(width: newWidth, height: newWidth), true, 0)