Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making square crop of UIImage causing image to stretch

When attempting to perform a center crop of an UIImage, I get the following results (left is the original image at 640*1136, and the right is the cropped image fitted to a square UIImageView at 320*320):

enter image description here turns to: enter image description here

I have tinkered quite a bit with the ratio element so that it could correctly detect the amount to trim: using the shorter side of of the image, constructing a ratio based on short_side/width_of_desired_rect, but it does not appear to be working in this case. Help appreciated!

- (UIImage *)squareImageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    double ratio;
    double delta;
    CGPoint offset;

    //make a new square size, that is the resized imaged width
    CGSize sz = CGSizeMake(newSize.width, newSize.width);

    //figure out if the picture is landscape or portrait, then
    //calculate scale factor and offset
    if (image.size.width > image.size.height) {
        ratio = newSize.width / image.size.width;
        delta = (ratio*image.size.width - ratio*image.size.height);
        offset = CGPointMake(delta/2, 0);
    } else {
        ratio = newSize.width / image.size.height;
        delta = (ratio*image.size.height - ratio*image.size.width);
        offset = CGPointMake(0, delta/2);
    }

    //make the final clipping rect based on the calculated values
    CGRect clipRect = CGRectMake(-offset.x, -offset.y,
                                 (ratio * image.size.width) + delta,
                                 (ratio * image.size.height) + delta);

    //for retina consideration
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0);
    } else {
        UIGraphicsBeginImageContext(sz);
    }
    UIRectClip(clipRect);
    [image drawInRect:clipRect];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}
like image 272
daspianist Avatar asked May 02 '14 23:05

daspianist


2 Answers

Try this:

- (UIImage *)squareImageFromImage:(UIImage *)image scaledToSize:(CGFloat)newSize {
    CGAffineTransform scaleTransform;
    CGPoint origin;

    if (image.size.width > image.size.height) {
        CGFloat scaleRatio = newSize / image.size.height;
        scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);

        origin = CGPointMake(-(image.size.width - image.size.height) / 2.0f, 0);
    } else {
        CGFloat scaleRatio = newSize / image.size.width;
        scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);

        origin = CGPointMake(0, -(image.size.height - image.size.width) / 2.0f);
    }

    CGSize size = CGSizeMake(newSize, newSize);
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(size, YES, 0);
    } else {
        UIGraphicsBeginImageContext(size);
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextConcatCTM(context, scaleTransform);

    [image drawAtPoint:origin];

    image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}
like image 149
fumoboy007 Avatar answered Nov 21 '22 21:11

fumoboy007


Use this code to resize your image

// Returns image resized to the desired CGSize
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

Edit: you are basically redrawing here too. If you are reusing the same image over and over, it might be a good idea to call this once and save the result as a file. Load that instead of the original instead in later calls.

Edit 2: Okay so what you want to do is keep the aspect ratio while fitting the image into a square. The above code basically fits the image into a square by resizing it but it does not keep the aspect ratio. A way of also keeping the aspect ratio would be to find the factor by which you shrink the larger of the two dimensions of the image and then shrink the other dimension by the same factor. Let me know if you have trouble with it.

like image 25
Zia Avatar answered Nov 21 '22 21:11

Zia