How to crop the UIImage?

后端 未结 7 1448
南笙
南笙 2020-11-30 01:50

I develop an application in which i process the image using its pixels but in that image processing it takes a lot of time. Therefore i want to crop UIImage (Only middle par

相关标签:
7条回答
  • 2020-11-30 02:11

    I wanted to be able to crop from a region based on an aspect ratio, and scale to a size based on a outer bounding extent. Here is my variation:

    import AVFoundation
    import ImageIO
    
    class Image {
    
        class func crop(image:UIImage, source:CGRect, aspect:CGSize, outputExtent:CGSize) -> UIImage {
    
            let sourceRect = AVMakeRectWithAspectRatioInsideRect(aspect, source)
            let targetRect = AVMakeRectWithAspectRatioInsideRect(aspect, CGRect(origin: CGPointZero, size: outputExtent))
    
            let opaque = true, deviceScale:CGFloat = 0.0 // use scale of device's main screen
            UIGraphicsBeginImageContextWithOptions(targetRect.size, opaque, deviceScale)
    
            let scale = max(
                targetRect.size.width / sourceRect.size.width,
                targetRect.size.height / sourceRect.size.height)
    
            let drawRect = CGRect(origin: -sourceRect.origin * scale, size: image.size * scale)
            image.drawInRect(drawRect)
    
            let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return scaledImage
        }
    }
    

    There are a couple things that I found confusing, the separate concerns of cropping and resizing. Cropping is handled with the origin of the rect that you pass to drawInRect, and scaling is handled by the size portion. In my case, I needed to relate the size of the cropping rect on the source, to my output rect of the same aspect ratio. The scale factor is then output / input, and this needs to be applied to the drawRect (passed to drawInRect).

    One caveat is that this approach effectively assumes that the image you are drawing is larger than the image context. I have not tested this, but I think you can use this code to handle cropping / zooming, but explicitly defining the scale parameter to be the aforementioned scale parameter. By default, UIKit applies a multiplier based on the screen resolution.

    Finally, it should be noted that this UIKit approach is higher level than CoreGraphics / Quartz and Core Image approaches, and seems to handle image orientation issues. It is also worth mentioning that it is pretty fast, second to ImageIO, according to this post here: http://nshipster.com/image-resizing/

    0 讨论(0)
  • 2020-11-30 02:13

    Try something like this:

    CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
    image = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef);
    

    Note: cropRect is smaller rectangle with middle part of the image...

    0 讨论(0)
  • 2020-11-30 02:13

    Because I needed it just now, here is M-V 's code in Swift 4:

    func imageWithImage(image: UIImage, croppedTo rect: CGRect) -> UIImage {
    
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
    
        let drawRect = CGRect(x: -rect.origin.x, y: -rect.origin.y, 
                              width: image.size.width, height: image.size.height)
    
        context?.clip(to: CGRect(x: 0, y: 0, 
                                 width: rect.size.width, height: rect.size.height))
    
        image.draw(in: drawRect)
    
        let subImage = UIGraphicsGetImageFromCurrentImageContext()
    
        UIGraphicsEndImageContext()
        return subImage!
    }
    
    0 讨论(0)
  • 2020-11-30 02:18

    I was looking for a way to get an arbitrary rectangular crop (ie., sub-image) of a UIImage.

    Most of the solutions I tried do not work if the orientation of the image is anything but UIImageOrientationUp.

    For example:

    http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/

    Typically if you use your iPhone camera, you will have other orientations like UIImageOrientationLeft, and you will not get a correct crop with the above. This is because of the use of CGImageRef/CGContextDrawImage which differ in the coordinate system with respect to UIImage.

    The code below uses UI* methods (no CGImageRef), and I have tested this with up/down/left/right oriented images, and it seems to work great.

    
    // get sub image
    - (UIImage*) getSubImageFrom: (UIImage*) img WithRect: (CGRect) rect {
    
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        // translated rectangle for drawing sub image 
        CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y, img.size.width, img.size.height);
    
        // clip to the bounds of the image context
        // not strictly necessary as it will get clipped anyway?
        CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
    
        // draw image
        [img drawInRect:drawRect];
    
        // grab image
        UIImage* subImage = UIGraphicsGetImageFromCurrentImageContext();
    
        UIGraphicsEndImageContext();
    
        return subImage;
    }
    
    
    0 讨论(0)
  • 2020-11-30 02:18

    It would ultimately be faster, with a lot less image creation from sprite atlases, if you could set not only the image for a UIImageView, but also the top-left offset to display within that UIImage. Maybe this is possible. It would certainly eliminate a lot of effort!

    Meanwhile, I created these useful functions in a utility class that I use in my apps. It creates a UIImage from part of another UIImage, with options to rotate, scale, and flip using standard UIImageOrientation values to specify. The pixel scaling is preserved from the original image.

    My app creates a lot of UIImages during initialization, and this necessarily takes time. But some images aren't needed until a certain tab is selected. To give the appearance of quicker load I could create them in a separate thread spawned at startup, then just wait till it's done when that tab is selected.

    This code is also posted at Most efficient way to draw part of an image in iOS

    + (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)aperture {
        return [ChordCalcController imageByCropping:imageToCrop toRect:aperture withOrientation:UIImageOrientationUp];
    }
    
    // Draw a full image into a crop-sized area and offset to produce a cropped, rotated image
    + (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)aperture withOrientation:(UIImageOrientation)orientation {
    
                // convert y coordinate to origin bottom-left
        CGFloat orgY = aperture.origin.y + aperture.size.height - imageToCrop.size.height,
                orgX = -aperture.origin.x,
                scaleX = 1.0,
                scaleY = 1.0,
                rot = 0.0;
        CGSize size;
    
        switch (orientation) {
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                size = CGSizeMake(aperture.size.height, aperture.size.width);
                break;
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                size = aperture.size;
                break;
            default:
                assert(NO);
                return nil;
        }
    
    
        switch (orientation) {
            case UIImageOrientationRight:
                rot = 1.0 * M_PI / 2.0;
                orgY -= aperture.size.height;
                break;
            case UIImageOrientationRightMirrored:
                rot = 1.0 * M_PI / 2.0;
                scaleY = -1.0;
                break;
            case UIImageOrientationDown:
                scaleX = scaleY = -1.0;
                orgX -= aperture.size.width;
                orgY -= aperture.size.height;
                break;
            case UIImageOrientationDownMirrored:
                orgY -= aperture.size.height;
                scaleY = -1.0;
                break;
            case UIImageOrientationLeft:
                rot = 3.0 * M_PI / 2.0;
                orgX -= aperture.size.height;
                break;
            case UIImageOrientationLeftMirrored:
                rot = 3.0 * M_PI / 2.0;
                orgY -= aperture.size.height;
                orgX -= aperture.size.width;
                scaleY = -1.0;
                break;
            case UIImageOrientationUp:
                break;
            case UIImageOrientationUpMirrored:
                orgX -= aperture.size.width;
                scaleX = -1.0;
                break;
        }
    
        // set the draw rect to pan the image to the right spot
        CGRect drawRect = CGRectMake(orgX, orgY, imageToCrop.size.width, imageToCrop.size.height);
    
        // create a context for the new image
        UIGraphicsBeginImageContextWithOptions(size, NO, imageToCrop.scale);
        CGContextRef gc = UIGraphicsGetCurrentContext();
    
        // apply rotation and scaling
        CGContextRotateCTM(gc, rot);
        CGContextScaleCTM(gc, scaleX, scaleY);
    
        // draw the image to our clipped context using the offset rect
        CGContextDrawImage(gc, drawRect, imageToCrop.CGImage);
    
        // pull the image from our cropped context
        UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();
    
        // pop the context to get back to the default
        UIGraphicsEndImageContext();
    
        // Note: this is autoreleased
        return cropped;
    }
    
    0 讨论(0)
  • 2020-11-30 02:21

    If you want a portrait crop down the center of every photo.

    Use @M-V solution, & replace cropRect.

    CGFloat height = imageTaken.size.height;
    CGFloat width = imageTaken.size.width;
    
    CGFloat newWidth = height * 9 / 16;
    CGFloat newX = abs((width - newWidth)) / 2;
    
    CGRect cropRect = CGRectMake(newX,0, newWidth ,height);
    
    0 讨论(0)
提交回复
热议问题