UIImage: Resize, then Crop

后端 未结 16 2281
夕颜
夕颜 2020-11-22 11:51

I\'ve been bashing my face into this one for literally days now and even though I feel constantly that I am right on the edge of revelation, I simply cannot achieve my goal.

相关标签:
16条回答
  • 2020-11-22 12:29

    I found that the Swift 3 posted by Evgenii Kanvets does not uniformly scale the image.

    Here is my Swift 4 version of the function that does not squish the image:

    static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {
    
        // This function returns a newImage, based on image
        // - image is scaled uniformaly to fit into a rect of size newSize
        // - if the newSize rect is of a different aspect ratio from the source image
        //     the new image is cropped to be in the center of the source image
        //     (the excess source image is removed)
    
        var ratio: CGFloat = 0
        var delta: CGFloat = 0
        var drawRect = CGRect()
    
        if newSize.width > newSize.height {
    
            ratio = newSize.width / image.size.width
            delta = (ratio * image.size.height) - newSize.height
            drawRect = CGRect(x: 0, y: -delta / 2, width: newSize.width, height: newSize.height + delta)
    
        } else {
    
            ratio = newSize.height / image.size.height
            delta = (ratio * image.size.width) - newSize.width
            drawRect = CGRect(x: -delta / 2, y: 0, width: newSize.width + delta, height: newSize.height)
    
        }
    
        UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
        image.draw(in: drawRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        return newImage
    } 
    
    0 讨论(0)
  • 2020-11-22 12:30

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 12:30

    Swift version:

        static func imageWithImage(image:UIImage, newSize:CGSize) ->UIImage {
        UIGraphicsBeginImageContextWithOptions(newSize, true, UIScreen.mainScreen().scale);
        image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    
        let newImage = UIGraphicsGetImageFromCurrentImageContext();
    
        UIGraphicsEndImageContext();
        return newImage
    }
    
    0 讨论(0)
  • 2020-11-22 12:33

    Here is a Swift 3 version of Sam Wirch's guide to swift posted by William T.

    extension UIImage {
    
        static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {
            var ratio: CGFloat = 0
            var delta: CGFloat = 0
            var offset = CGPoint.zero
    
            if image.size.width > image.size.height {
                ratio = newSize.width / image.size.width
                delta = (ratio * image.size.width) - (ratio * image.size.height)
                offset = CGPoint(x: delta / 2, y: 0)
            } else {
                ratio = newSize.width / image.size.height
                delta = (ratio * image.size.height) - (ratio * image.size.width)
                offset = CGPoint(x: 0, y: delta / 2)
            }
    
            let clipRect = CGRect(x: -offset.x, y: -offset.y, width: (ratio * image.size.width) + delta, height: (ratio * image.size.height) + delta)
            UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
            UIRectClip(clipRect)
            image.draw(in: clipRect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return newImage
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题