nemesis
nemesis

Reputation: 1351

Cropping and scaling a UIImage properly

I'm trying to crop a image into a square shape, and then scale it to a size 200x200. Here's the code I use, but it's not really working for me. The image I get is sometimes in a different orientation, or isn't cropped from the center, or is wider than it should be.

float scale = _avatar.image.scale;
UIImageOrientation orientation = _avatar.image.imageOrientation;

if(_avatar.image.size.width < _avatar.image.size.height){ // avatar is a UIImageView
    float startingY = (_avatar.image.size.height-_avatar.image.size.width)/2; // image is taller, determine the origin of the width-sized square, which will be the new image
    CGImageRef imageRef = CGImageCreateWithImageInRect([_avatar.image CGImage], CGRectMake(0, startingY, _avatar.image.size.width, _avatar.image.size.width));
    _avatar.image = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
    CGImageRelease(imageRef);
} else {
    float startingX = (_avatar.image.size.width-_avatar.image.size.height)/2; // image is wider, determine the origin of the height-sized square, which will be the new image
    CGImageRef imageRef = CGImageCreateWithImageInRect([_avatar.image CGImage], CGRectMake(startingX, 0, _avatar.image.size.height, _avatar.image.size.height));
    _avatar.image = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
    CGImageRelease(imageRef);
}

UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), YES, 0.0);
[_avatar.image drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

How it must be done to achieve the correct result?

Upvotes: 2

Views: 4151

Answers (2)

liuyaodong
liuyaodong

Reputation: 2567

The UIImage has done all the coordinate and orientation tricks for you. So you should not use the width and height from an UIImage object to caculate the square's coordinate. You can take advantages of the UIKit to crop an image.

CGFloat startingX = 0;
CGFloat startingY = 0;
CGFloat squareWidth;
if(_avatar.image.size.width < _avatar.image.size.height){ // avatar is a UIImageView  
    startingY = (_avatar.image.size.height-_avatar.image.size.width)/2; // image is taller, determine the origin of the width-sized square, which will be the new image  
    squareWidth = _avatar.image.size.width;
} else {
    startingX = (_avatar.image.size.width-_avatar.image.size.height)/2; // image is wider, determine the origin of the height-sized square, which will be the new image
    squareWidth = _avatar.image.size.height;
}  

UIGraphicsBeginImageContextWithOptions(CGSizeMake(squareWidth, squareWidth), YES, 0.0);
[_avatar.image drawAtPoint:CGPointMake(-startingX, -startingY)]; // Make an offset to draw part of the image
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();

UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), YES, 0.0);
[croppedImage  drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Upvotes: 3

Andrea
Andrea

Reputation: 26383

I would suggest you to use this category for UIImage posted on github. They are also really simple classes and you can also use them to learn what is under the hood.

Upvotes: 5

Related Questions