How to scale down a UIImage and make it crispy / sharp at the same time instead of blurry? How to scale down a UIImage and make it crispy / sharp at the same time instead of blurry? ios ios

How to scale down a UIImage and make it crispy / sharp at the same time instead of blurry?


Merely using imageWithCGImage is not sufficient. It will scale, but the result will be blurry and suboptimal whether scaling up or down.

If you want to get the aliasing right and get rid of the "jaggies" you need something like this: http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/.

My working test code looks something like this, which is Trevor's solution with one small adjustment to work with my transparent PNGs:

- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));    CGImageRef imageRef = image.CGImage;    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);    CGContextRef context = UIGraphicsGetCurrentContext();    // Set the quality level to use when rescaling    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);    CGContextConcatCTM(context, flipVertical);      // Draw into the context; this scales the image    CGContextDrawImage(context, newRect, imageRef);    // Get the resized image from the context and a UIImage    CGImageRef newImageRef = CGBitmapContextCreateImage(context);    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];    CGImageRelease(newImageRef);    UIGraphicsEndImageContext();        return newImage;}


For those using Swift here is the accepted answer in Swift:

func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {    let newRect = CGRectIntegral(CGRectMake(0,0, newSize.width, newSize.height))    let imageRef = image.CGImage    UIGraphicsBeginImageContextWithOptions(newSize, false, 0)    let context = UIGraphicsGetCurrentContext()    // Set the quality level to use when rescaling    CGContextSetInterpolationQuality(context, kCGInterpolationHigh)    let flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height)    CGContextConcatCTM(context, flipVertical)    // Draw into the context; this scales the image    CGContextDrawImage(context, newRect, imageRef)    let newImageRef = CGBitmapContextCreateImage(context) as CGImage    let newImage = UIImage(CGImage: newImageRef)    // Get the resized image from the context and a UIImage    UIGraphicsEndImageContext()    return newImage}


If someone is looking for Swift version, here is the Swift version of @Dan Rosenstark's accepted answer:

func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {    let scale = newHeight / image.size.height    let newWidth = image.size.width * scale    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))    let newImage = UIGraphicsGetImageFromCurrentImageContext()    UIGraphicsEndImageContext()    return newImage}