iphone - UIImage: Resize, then Crop

ID : 20420

viewed : 21

Tags : iphoneiosimage-processingcore-graphicsiphone

Top 5 Answer for iphone - UIImage: Resize, then Crop

vote vote

92

I needed the same thing - in my case, to pick the dimension that fits once scaled, and then crop each end to fit the rest to the width. (I'm working in landscape, so might not have noticed any deficiencies in portrait mode.) Here's my code - it's part of a categeory on UIImage. Target size in my code is always set to the full screen size of the device.

@implementation UIImage (Extras)  #pragma mark - #pragma mark Scale and crop image  - (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize {     UIImage *sourceImage = self;     UIImage *newImage = nil;         CGSize imageSize = sourceImage.size;     CGFloat width = imageSize.width;     CGFloat height = imageSize.height;     CGFloat targetWidth = targetSize.width;     CGFloat targetHeight = targetSize.height;     CGFloat scaleFactor = 0.0;     CGFloat scaledWidth = targetWidth;     CGFloat scaledHeight = targetHeight;     CGPoint thumbnailPoint = CGPointMake(0.0,0.0);      if (CGSizeEqualToSize(imageSize, targetSize) == NO)      {         CGFloat widthFactor = targetWidth / width;         CGFloat heightFactor = targetHeight / height;          if (widthFactor > heightFactor)          {             scaleFactor = widthFactor; // scale to fit height         }         else         {             scaleFactor = heightFactor; // scale to fit width         }          scaledWidth  = width * scaleFactor;         scaledHeight = height * scaleFactor;          // center the image         if (widthFactor > heightFactor)         {             thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;          }         else         {             if (widthFactor < heightFactor)             {                 thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;             }         }     }         UIGraphicsBeginImageContext(targetSize); // this will crop      CGRect thumbnailRect = CGRectZero;     thumbnailRect.origin = thumbnailPoint;     thumbnailRect.size.width  = scaledWidth;     thumbnailRect.size.height = scaledHeight;      [sourceImage drawInRect:thumbnailRect];      newImage = UIGraphicsGetImageFromCurrentImageContext();      if(newImage == nil)     {         NSLog(@"could not scale image");     }      //pop the context to get back to the default     UIGraphicsEndImageContext();      return newImage; } 
vote vote

87

An older post contains code for a method to resize your UIImage. The relevant portion is as follows:

+ (UIImage*)imageWithImage:(UIImage*)image                 scaledToSize:(CGSize)newSize; {    UIGraphicsBeginImageContext( newSize );    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();     return newImage; } 

As far as cropping goes, I believe that if you alter the method to use a different size for the scaling than for the context, your resulting image should be clipped to the bounds of the context.

vote vote

70

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {     //If scaleFactor is not touched, no scaling will occur           CGFloat scaleFactor = 1.0;      //Deciding which factor to use to scale the image (factor = targetSize / imageSize)     if (image.size.width > targetSize.width || image.size.height > targetSize.height)         if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or             scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.      UIGraphicsBeginImageContext(targetSize);       //Creating the rect where the scaled image is drawn in     CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2,                              (targetSize.height -  image.size.height * scaleFactor) / 2,                              image.size.width * scaleFactor, image.size.height * scaleFactor);      //Draw the image into the rect     [image drawInRect:rect];      //Saving the image, ending image context     UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();     UIGraphicsEndImageContext();      return scaledImage; } 

I propose this one. Isn't she a beauty? ;)

vote vote

70

There's a great piece of code related to the resizing of images + several other operations. I came around this one when trying to figure ou how to resize images... http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

vote vote

51

Here you go. This one is perfect ;-)

EDIT: see below comment - "Does not work with certain images, fails with: CGContextSetInterpolationQuality: invalid context 0x0 error"

// Resizes the image according to the given content mode, taking into account the image's orientation - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode imageToScale:(UIImage*)imageToScale bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality {     //Get the size we want to scale it to     CGFloat horizontalRatio = bounds.width / imageToScale.size.width;     CGFloat verticalRatio = bounds.height / imageToScale.size.height;     CGFloat ratio;      switch (contentMode) {         case UIViewContentModeScaleAspectFill:             ratio = MAX(horizontalRatio, verticalRatio);             break;          case UIViewContentModeScaleAspectFit:             ratio = MIN(horizontalRatio, verticalRatio);             break;          default:             [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode];     }      //...and here it is     CGSize newSize = CGSizeMake(imageToScale.size.width * ratio, imageToScale.size.height * ratio);       //start scaling it     CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));     CGImageRef imageRef = imageToScale.CGImage;     CGContextRef bitmap = CGBitmapContextCreate(NULL,                                                 newRect.size.width,                                                 newRect.size.height,                                                 CGImageGetBitsPerComponent(imageRef),                                                 0,                                                 CGImageGetColorSpace(imageRef),                                                 CGImageGetBitmapInfo(imageRef));      CGContextSetInterpolationQuality(bitmap, quality);      // Draw into the context; this scales the image     CGContextDrawImage(bitmap, newRect, imageRef);      // Get the resized image from the context and a UIImage     CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);     UIImage *newImage = [UIImage imageWithCGImage:newImageRef];      // Clean up     CGContextRelease(bitmap);     CGImageRelease(newImageRef);      return newImage; } 

Top 3 video Explaining iphone - UIImage: Resize, then Crop

Related QUESTION?