Cropping center square of UIImage

后端 未结 18 605
日久生厌
日久生厌 2020-12-07 23:09

So here\'s where I\'ve made it so far. I am using a UIImage captured from the camera and can crop the center square when in landscape. For some reason this doesn\'t transl

相关标签:
18条回答
  • 2020-12-07 23:29

    Solution based on Swift 2 extension. Improvised from @Geoffrey and @Nirav Dangi. Note that we set newCropWidth and newCropHeight to image's width or height when they are lesser than the given width or height.

    extension UIImage {
        func imageByCroppingImage(size: CGSize) -> UIImage {
            let newCropWidth, newCropHeight : CGFloat;
    
            if(self.size.width < self.size.height) {
                if (self.size.width < size.width) {
                    newCropWidth = self.size.width;
                }
                else {
                    newCropWidth = size.width;
                }
                newCropHeight = (newCropWidth * size.height)/size.width;
            } else {
                if (self.size.height < size.height) {
                    newCropHeight = self.size.height;
                }
                else {
                    newCropHeight = size.height;
                }
                newCropWidth = (newCropHeight * size.width)/size.height;
            }
    
            let x = self.size.width / 2 - newCropWidth / 2;
            let y = self.size.height / 2 - newCropHeight / 2;
    
            let cropRect = CGRectMake(x, y, newCropWidth, newCropHeight);
            let imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect);
    
            let croppedImage : UIImage = UIImage(CGImage: imageRef!, scale: 0, orientation: self.imageOrientation);
    
            return croppedImage;
        }
    }
    
    0 讨论(0)
  • 2020-12-07 23:31

    There is the swift version for the checked solution :

    private func imageByCroppingImage(image : UIImage, size : CGSize) -> UIImage{
            var refWidth : CGFloat = CGFloat(CGImageGetWidth(image.CGImage))
            var refHeight : CGFloat = CGFloat(CGImageGetHeight(image.CGImage))
    
            var x = (refWidth - size.width) / 2
            var y = (refHeight - size.height) / 2
    
            let cropRect = CGRectMake(x, y, size.height, size.width)
            let imageRef = CGImageCreateWithImageInRect(image.CGImage, cropRect)
    
            let cropped : UIImage = UIImage(CGImage: imageRef, scale: 0, orientation: image.imageOrientation)!
    
    
            return cropped
        }
    
    0 讨论(0)
  • 2020-12-07 23:32

    This works with different orientations. Both portrait and landscape orientations works correctly.

    - (UIImage *)imageByCroppingImage:(UIImage *)image toSize:(CGSize)size
    {
        // not equivalent to image.size (which depends on the imageOrientation)!
        double refWidth = CGImageGetWidth(image.CGImage);
        double refHeight = CGImageGetHeight(image.CGImage);
    
        double x = (refWidth - size.width) / 2.0;
        double y = (refHeight - size.height) / 2.0;
    
        CGRect cropRect = CGRectMake(x, y, size.height, size.width);
        CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
    
        UIImage *cropped = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:self.imageOrientation];
        CGImageRelease(imageRef);
    
        return cropped;
    }
    
    0 讨论(0)
  • 2020-12-07 23:32
    func cropImage() -> UIImage? {
        let size = min(self.size.width, self.size.height)
        UIGraphicsBeginImageContextWithOptions(CGSize(width: size, height: size), true, 1.0)
        defer { UIGraphicsEndImageContext() }
        self.draw(in: CGRect(x: (size - self.size.width) / 2.0,
                              y: (size - self.size.height) / 2.0,
                              width: self.size.width,
                              height: self.size.height))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
    
    0 讨论(0)
  • 2020-12-07 23:32

    Here is the Swift 5 version of cropping the image according to given size from center.

    extension UIImage {
    
         func imageByCroppingImage(size : CGSize) -> UIImage{
            let refWidth : CGFloat = CGFloat(self.cgImage!.width)
            let refHeight : CGFloat = CGFloat(self.cgImage!.height)
            let x = (refWidth - size.width) / 2
            let y = (refHeight - size.height) / 2
            let cropRect = CGRect(x: x, y: y, width: size.width, height: size.height)
            let imageRef = self.cgImage!.cropping(to: cropRect)
            let cropped : UIImage = UIImage(cgImage: imageRef!, scale: 0, orientation: self.imageOrientation)
            return cropped
        }
        }
    
    0 讨论(0)
  • 2020-12-07 23:33

    This is an old question, but none of the answers are really correct (even the accepted answer). The important thing to understand is that UIImageOrientation (image.imageOrientation) is actually correct, but it's definition of UP and our definition of UP are different. For us, UP is the top of the device (where the power button is). For UIImageOrientation, UP is the side opposite of the volume control buttons. So if the device takes a picture with the volume controls down, this is UIImageOrientationUp. If you take a picture in portrait mode (with the home button down), this is UIImageOrientationLeft.

    So you can calculate the center in portrait, then you can apply the following transform to the image so that the crop is in the correct place.

    - (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {
        CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
            return deg / 180.0f * (CGFloat) M_PI;
        };
    
        // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position
        CGAffineTransform rectTransform;
        switch (image.imageOrientation) {
            case UIImageOrientationLeft:
                rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
                break;
            case UIImageOrientationRight:
                rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
                break;
            case UIImageOrientationDown:
                rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
                break;
            default:
                rectTransform = CGAffineTransformIdentity;
        };
    
        // adjust the transformation scale based on the image scale
        rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);
    
        // apply the transformation to the rect to create a new, shifted rect
        CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
        // use the rect to crop the image
        CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
        // create a new UIImage and set the scale and orientation appropriately
        UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
        // memory cleanup
        CGImageRelease(imageRef);
    
        return result;
    }
    

    This code shifts the crop square so that it is in the correct relative position.

    0 讨论(0)
提交回复
热议问题