문제

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;
}
도움이 되었습니까?

해결책

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;
}

다른 팁

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.

Swift3 version of fumoboy007's code..

     func squareImage(img: UIImage, scaledToSize newSize: CGFloat) -> UIImage {
    var scaleTransform: CGAffineTransform
    var origin: CGPoint
    var image = img
    if image.size.width > image.size.height {
        let scaleRatio: CGFloat = newSize / image.size.height
        scaleTransform = CGAffineTransform(scaleX: scaleRatio, y: scaleRatio)
        origin = CGPoint(x: -(image.size.width - image.size.height) / 2.0, y: 0)
    }
    else {
        let scaleRatio: CGFloat = newSize / image.size.width
        scaleTransform = CGAffineTransform(scaleX: scaleRatio, y: scaleRatio)
        origin = CGPoint(x: 0, y: -(image.size.height - image.size.width) / 2.0)
    }
    let size = CGSize(width: newSize, height: newSize)
    if image.size.width > image.size.height {
        UIGraphicsBeginImageContextWithOptions(size, true, 0)
    }
    else {
        UIGraphicsBeginImageContext(size)
    }

    let context: CGContext? = UIGraphicsGetCurrentContext()
    context?.concatenate(scaleTransform)
    image.draw(at: origin)
    image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top