2

I have a UIImage that I put in a UIImageView which has a pinch gesture recognizer attached to it which I use to scale the image. When I scale the image in the UIImageView, there is no distortion and it scales perfectly. However, I need to resize the UIImage while not in the UIImageView, and when I do this using the following code, the result is slightly skewed:

CGFloat width = self.imageView.frame.size.width;
CGFloat height = self.imageView.frame.size.height;

UIGraphicsBeginImageContext(CGSizeMake(width, height));
[self.image drawInRect:CGRectMake(0, 0, width, height)];
UIImage *resizedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];    
UIGraphicsEndImageContext();

As you can see I'm taking the height and width from the imageView, because that is what the image needs to be scaled to.

I know that it has to be possible to scale it perfectly if the imageView is able to do this, does anyone happen to know what I'm doing incorrectly?

UPDATE: I attached a before / after of an image (which has been rescaled by the user in an imageview) and how it looks after I resized it using the above method.BeforeAfter

Ser Pounce
  • 14,196
  • 18
  • 84
  • 169

2 Answers2

1

Try this:

+ (UIImage*)rescaleImage:(UIImage *)image scaledToSize:(CGRect)newSize {
    UIGraphicsBeginImageContext(newSize.size);
    [image drawInRect:newSize];
    UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resImage;
}
TigerCoding
  • 8,710
  • 10
  • 47
  • 72
  • You should probably use `UIGraphicsBeginImageContextWithOptions`. It takes a scale argument which allows it to adapt for the retina display. – Mark Adams Nov 17 '11 at 21:22
  • How would this be different though? This is nearly the exact same code as I have posted above. – Ser Pounce Nov 17 '11 at 21:24
  • Not sure, but this code works for me - no skewing. @MarkAdams agreed, thanks for the tip. – TigerCoding Nov 17 '11 at 21:29
  • Have you removed the UIImage from the UIImageView before apply the scale? – TigerCoding Nov 17 '11 at 21:49
  • @Javy Yeah I did try that, didn't make a difference. – Ser Pounce Nov 17 '11 at 21:59
  • @MarkAdams tried playing with that a little with all sorts of different scale values, nothing really worked – Ser Pounce Nov 17 '11 at 22:00
  • Mark was referring to allowing it to handle the double size images for retina devices. There would have to be an additional check for "respondsToSelector:" to see if it a retina display, but that's not really the problem here. I think it's something else in your code that's causing the skewing. Perhaps the UIImageView was not set to nil? Maybe something else in the method is affecting the image? AsI said, my code works fine and doesn't skew images for me, so it must be something else going on. Perhaps post an image your trying to scale and I can give it a run through? – TigerCoding Nov 17 '11 at 22:32
  • @Javy Appreciate your willingness to help. Sorry I didn't respond sooner I was away for the holidays. I posted some photos to show the difference. BTW: Why is it necessary to set the imageview to nil? – Ser Pounce Nov 29 '11 at 08:55
  • I thought you were referring to the image being skewed out of proportions. I'm going to guess that when you scale with the image view, the quality is lost a little, but when you scale back, it's okay int he image view? If you scale with the method above, then scale back, there will be quality loss. You will need to maintain a ref to the original UIImage to put it back to normal. This is my best guess, anyways. Regarding setting to nil, I was wondering if you were performing multiple conversions on the image and it was all adding up to bigger distortions, but that's unlikely. – TigerCoding Nov 29 '11 at 09:07
1

I had this same issue, I used the following code to help fix it:

    CGFloat scale = 1.0;
if([[UIScreen mainScreen]respondsToSelector:@selector(scale)]) {        
    CGFloat tmp = [[UIScreen mainScreen]scale];
    if (tmp > 1.5) {
        scale = 2.0;    
    }
} 

if(scale > 1.5) {
    UIGraphicsBeginImageContextWithOptions(targetSize, NO, scale);
} else {
    UIGraphicsBeginImageContext(targetSize);
}
  • 1
    A slightly better solution might be to pass 0.0 into the scale, as then the function inserts the scale from the main screen by itself. That will turn the 12 lines of code above into 1. – rickerbh Oct 27 '12 at 03:46