In my app the user selects an image or take a picture using UIImagePickerViewController. Once the image was selected I want to display its thumbnail on a square UIImageView
Swift version of Clever Error's answer above: Updated to swift 4.1
func resizeImageToCenter(image: UIImage) -> UIImage {
let size = CGSize(width: 100, height: 100)
// Define rect for thumbnail
let scale = max(size.width/image.size.width, size.height/image.size.height)
let width = image.size.width * scale
let height = image.size.height * scale
let x = (size.width - width) / CGFloat(2)
let y = (size.height - height) / CGFloat(2)
let thumbnailRect = CGRect.init(x: x, y: y, width: width, height: height)
// Generate thumbnail from image
UIGraphicsBeginImageContextWithOptions(size, false, 0)
image.draw(in: thumbnailRect)
let thumbnail = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return thumbnail!
}
Here is a link you can refer to:
1) UIImage+Resize
2) UIImage+ProportionalFill
Here you can resize the view and also add proportional fill so that proportionately the aspect ratio and other functions like crop, scale, etc.
You can use -(UIImage*)resizedImageToSize:(CGSize*)size
method under reference link UIImage+Resize above just to reize the image.
Hope this helps you.
Let me know if you want more help.
Another way to do this - ran into an issue the other day and other people might have the same issue when using the apple sample code which is best for large images.
As mentioned in the accepted answer, this has the problem of loading the entire image into memory and iOS can kill your app if it's too large. CGImageSourceCreateThumbnailAtIndex in Apple's example code is more efficient, however there is a bug in the example. The 3rd parameter in the CFDictionaryCreate is the "numValues" to copy. Needs to be 3 not 2.
myOptions = CFDictionaryCreate(NULL, (const void **) myKeys,
(const void **) myValues,
3, //Changed to 3
&kCFTypeDictionaryKeyCallBacks,
& kCFTypeDictionaryValueCallBacks);
The easiest thing to do would be to set the contentMode
on your imageView to be UIViewContentModeScaleAspectFill
instead. However, this may not be ideal since it would keep the whole image in memory.
Here is some code that I use to resize images.
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
This version will keep the image from being distorted if the size is not the same aspect ratio as the image.
+ (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size
{
CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height);
CGFloat width = image.size.width * scale;
CGFloat height = image.size.height * scale;
CGRect imageRect = CGRectMake((size.width - width)/2.0f,
(size.height - height)/2.0f,
width,
height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[image drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Often you want just the top square of an image (rather than the center). And you want the final image to be of a certain size, say 128x128, like in the example below.
- (UIImage *)squareAndSmall // as a category (so, 'self' is the input image)
{
// fromCleverError's original
// http://stackoverflow.com/questions/17884555
CGSize finalsize = CGSizeMake(128,128);
CGFloat scale = MAX(
finalsize.width/self.size.width,
finalsize.height/self.size.height);
CGFloat width = self.size.width * scale;
CGFloat height = self.size.height * scale;
CGRect rr = CGRectMake( 0, 0, width, height);
UIGraphicsBeginImageContextWithOptions(finalsize, NO, 0);
[self drawInRect:rr];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}