Reputation: 1361
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.
Upvotes: 0
Views: 597
Reputation: 80781
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
.
Upvotes: 1
Reputation: 3838
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()
Upvotes: 0