Given the UIImage of any dimension, I want to generate a square version of the โiconโ size, px pixels to the side, without any distortion (stretching). However, I come across a little grip. Not quite sure where the problem is. Here is what I am doing so far.
First, given the UImage size , I define three things: ratio to use when reducing the image; a delta (difference between the desired icon size and the longest side) and offset (which is used to determine the coordinates of the origin when clipping the image):
if (size.width > size.height) { ratio = px / size.width; delta = (ratio*size.width - ratio*size.height); offset = CGPointMake(delta/2, 0); } else { ratio = px / size.height; delta = (ratio*size.height - ratio*size.width); offset = CGPointMake(0, delta/2); }
Now let's say that you have an image of 640 pixels in height and 480 pixels, and we want to get a 50 pixels x 50 pixels icon. Width is greater than height, so our calculations are:
ratio = 50px / 640px = 0.078125 delta = (ratio * 640px) - (ratio * 480px) = 50px - 37.5px = 12.5px offset = {x=6.25, y=0}
Next, I create a CGRect rect , which is large enough to crop the icon to the desired size without distortion, plus clipRect for clipping:
CGRect rect = CGRectMake(0.0, 0.0, (ratio * size.width) + delta, (ratio * size.height) + delta); CGRect clipRect = CGRectMake(offset.x, offset.y, px, px);
Substituting our values โโabove, we get:
rect = origin {x=0.0, y=0.0}, size {width=62.5, height=50.0} clipRect = origin {x=6.25, y=0}, size {width=50.0, height=50.0}
So, now we have 62.5px 50px wide with a high rectangle for working with it and a clipping rectangle that captures the "middle" part of 50x50.
At the home site! Then we create the image context, draw the UIImage (called myImage here) into the rectangle, set the cropping rectangle, get the (presumably now cropped) image, use it, and finally clear our image context:
UIGraphicsBeginImageContext(rect.size); [myImage drawInRect:rect]; UIRectClip(clipRect); UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();
Only one problem: pruning never occurs! I get an image that is 63px wide x 50px wide. :(
Perhaps I am abusing / misunderstanding UIRectClip ? I tried shuffling different things: replacing rect and clipRect , moving UIRectClip to drawInRect:. No dice.
I also tried to find an example of this method on the Internet, but to no avail. For recording, UIRectClip is defined as:
Changes the current cropping path to crossing it with the specified rectangle.
Stirring things around us is a little closer:
UIGraphicsBeginImageContext(clipRect.size); UIRectClip(rect); [myImage drawInRect:rect];
Now we have no distortion, but the cropped image is not focused on the original, as I expected. However, at least the image is 50x50, although the variable names are now dirty due to the shuffle mentioned. (I respectfully leave renaming as an exercise for the reader.)