1

In my app I need to upload photos on server, so before that, I want to resize and compress them to acceptable size. I tried to resize them in two ways, and the first way is:

    // image is an instance of original UIImage that I want to resize
    let width : Int = 640
    let height : Int = 640
    let bitsPerComponent = CGImageGetBitsPerComponent(image.CGImage)
    let bytesPerRow = CGImageGetBytesPerRow(image.CGImage)
    let colorSpace = CGImageGetColorSpace(image.CGImage)
    let bitmapInfo = CGImageGetBitmapInfo(image.CGImage)

    let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo)
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
    CGContextDrawImage(context, CGRect(origin: CGPointZero, size: CGSize(width: CGFloat(width), height: CGFloat(height))), image.CGImage)

    image = UIImage(CGImage: CGBitmapContextCreateImage(context))

The other way:

image = RBResizeImage(image, targetSize: CGSizeMake(640, 640))

func RBResizeImage(image: UIImage?, targetSize: CGSize) -> UIImage? {
        if let image = image {
            let size = image.size

            let widthRatio  = targetSize.width  / image.size.width
            let heightRatio = targetSize.height / image.size.height

            // Figure out what our orientation is, and use that to form the rectangle
            var newSize: CGSize
            if(widthRatio > heightRatio) {
                newSize = CGSizeMake(size.width  heightRatio, size.height  heightRatio)
            } else {
                newSize = CGSizeMake(size.width  widthRatio,  size.height  widthRatio)
            }

            // This is the rect that we've calculated out and this is what is actually used below
            let rect = CGRectMake(0, 0, newSize.width, newSize.height)

            // Actually do the resizing to the rect using the ImageContext stuff
            UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
            image.drawInRect(rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            return newImage
        } else {
            return nil
        }
    }

After that, I use UIImageJPEGRepresentation to compress UIImage, but even if compressionQuality is 1, photo is still blurry (that's visible on object edges mostly, maybe it's not a big deal, but photo is three to five times larger than same photo from Instagram, e.g. but doesn't have same sharpness). For 0.5 is even worse, of course, and photo is still larger (in KB) than same photo from Instagram.

Photo from my app, compressionQuality is 1, edges are blurry, and size is 341 KB Photo from my app, compressionQuality is 1, edges are blurry, and size is 341 KB

Photo from Instagram, edges are sharp, and size is 136 KB Photo from Instagram, edges are sharp, and size is 136 KB

EDIT:

Ok, but I'm little confused right now, I'm not sure what to do, to maintain aspect ratio? This is how I crop image (scrollView has UIImageView, so I can move and zoom image, and on the end, I'm able to crop visible part of scrollView which is sqare). Anyway, image from above was originally 2048x2048, but it's still blurry.

 var scale  = 1/scrollView.zoomScale
 var visibleRect : CGRect = CGRect()

 visibleRect.origin.x = scrollView.contentOffset.x * scale
 visibleRect.origin.y = scrollView.contentOffset.y * scale
 visibleRect.size.width = scrollView.bounds.size.width * scale
 visibleRect.size.height = scrollView.bounds.size.height * scale
 image = crop(image!, rect: visibleRect)


func crop(srcImage : UIImage, rect : CGRect) -> UIImage? {
     var imageRef = CGImageCreateWithImageInRect(srcImage.CGImage, rect)
     var cropped = UIImage(CGImage: imageRef)

     return cropped
}
Marko
  • 2,021
  • 4
  • 16
  • 18
  • http://stackoverflow.com/questions/28809355/resize-uiimage-not-give-me-exact-new-size-after-resize-it/28809573#28809573 – user4261201 Apr 22 '15 at 09:47
  • I've just tried that too, but I'm getting the same result. Photo from above is 341 KB again, and every pixel stays the same. – Marko Apr 22 '15 at 10:13

1 Answers1

0

Your given code is wright but problem is u don't maintain the aspect ratio of image
as in your code you create a new rect as

let rect = CGRectMake(0, 0, newSize.width, newSize.height) 

if your given image of same height and width it will give smooth resize image but if height and width are different your image is blur . so try to maintain the aspect ratio
Reply to Edit question :
make height or width of crop image constant
For example if you make width as constant than use the following code

 visibleRect.size.height = orignalImg.size.height *  visibleRect.size.width / orignalImg.size.width     

image = crop(image!, rect: visibleRect)
Rizwan Shaikh
  • 2,824
  • 2
  • 27
  • 49
  • Actually I do that, just didn't write that part of code. I always crop image to square first, so if I have 3264x2448 image, I crop it to 2448x2448 before resizing to 640x640. – Marko Apr 22 '15 at 10:32
  • there is same problem of aspect ratio as your given image of size 3264 * 2448 has aspect ratio 1.33 and when you crop it to 2448 * 2448 its aspect ratio become 1 – Rizwan Shaikh Apr 22 '15 at 10:37
  • just open this link and see the photos you get the idea what is missing http://en.wikipedia.org/wiki/Cropping_(image) – Rizwan Shaikh Apr 22 '15 at 10:42
  • Ok, thanks, but now I'm not sure what to do to fix that? I've edited my question, so you can see what's going on before resizing. – Marko Apr 22 '15 at 11:06