0

I'm using the answer from this question to scale down an image and make it not blurry. However, that is not working for me. I'm using Swift. I do everything like in the answer. This is the code of the function that I use :

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, CGInterpolationQuality.High)
        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
    }

And this is where I call it :

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {

        let identifier = "mypin"

        if annotation.isKindOfClass(MKUserLocation) {
            return nil
        }

        let detailButton: UIButton = UIButton(type: UIButtonType.DetailDisclosure)

        var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)

        if annotationView == nil
        {
            annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
            annotationView!.canShowCallout = true
            let pinImage = UIImage(named: "Pin.png")
            let resizedImage = resizeImage(pinImage!, newSize: CGSize(width: 12, height: 20))
            annotationView?.image = resizedImage
            annotationView!.rightCalloutAccessoryView = detailButton
        }
        else
        {
            annotationView!.annotation = annotation
        }

        return annotationView
    }

If anybody knows why this could be happening I would really appreciate it if you could let me know. Thanks in advance.

Community
  • 1
  • 1
Giulio Colleluori
  • 1,261
  • 2
  • 10
  • 16
  • 1
    What's the size of your original image? If you're scaling down the image drastically, then you can't expect perfect results. Seeing as it looks like your new size is fixed, creating your own scaled down version would be best for quality. Also you should use `UIGraphicsGetImageFromCurrentImageContext()` to get your resultant image. – Hamish May 06 '16 at 09:03
  • @originaluser2 the original image is 297 × 500 px. `UIGraphicsGetImageFromCurrentImageContext()` fixed it perfectly. If you want to write it as an answer I'd be more than happy to select it as the correct answer! Thanks! – Giulio Colleluori May 06 '16 at 17:05
  • Really? That's interesting – didn't actually expect `UIGraphicsGetImageFromCurrentImageContext()` to fix the problem, only make your code more concise! Let me try and figure out exactly why that fixes the problem (I suspect it's due to `CGBitmapContextCreateImage` ignoring the scale), and I'll write up and answer with my findings :) – Hamish May 06 '16 at 17:09
  • Haha that is interesting. Sounds good, thanks a lot again. – Giulio Colleluori May 06 '16 at 17:13

2 Answers2

1

As I suspected in my comment, it's due to the fact that CGBitmapContextCreateImage will ignore the scale that you input into UIGraphicsBeginImageContextWithOptions – and instead always create an image with a scale of 1.0.

For example if you have a 50 x 50 image context at a 3x scale:

  • CGBitmapContextCreateImage will return a 150 x 150 image at 1x scale

  • UIGraphicsGetImageFromCurrentImageContext will return a 50 x 50 image at 3x scale

Usually this shouldn't actually make a difference when displaying the image on-screen, unless you rely on the size to be specified in points rather than pixels. However, for an MKAnnotationView, the documentation says:

Assigning a new image to this property also changes the size of the view’s frame so that it matches the width and height of the new image.

Therefore if you assign it an image with a 1x scale (and your screen's scale is higher than 1x) – it will be unnecessarily scaled up, therefore losing quality. The fix therefore is to use UIGraphicsGetImageFromCurrentImageContext.

Hamish
  • 78,605
  • 19
  • 187
  • 280
0

Is this any better? Yes it skips a lot, but for my annotations it works fine.

func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
 let scale: CGFloat = 0.0 //whatever

 UIGraphicsBeginImageContextWithOptions(newSize, true, scale)
 image.drawInRect(CGRect(origin: CGPointZero, size: newSize))

 let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
 UIGraphicsEndImageContext()
Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36