Swiftpack.co - Package - ruslanskorb/RSKImageCropper

RSKImageCropper Build Status Coverage Status Carthage compatible

Sample

An image cropper for iOS like in the Contacts app with support for landscape orientation.

Installation

RSKImageCropper requires iOS 6.0 or later.

Using CocoaPods

  1. Add the pod RSKImageCropper to your Podfile.

    pod 'RSKImageCropper'
    
  2. Run pod install from Terminal, then open your app's .xcworkspace file to launch Xcode.

  3. Import the RSKImageCropper.h header. Typically, this should be written as #import <RSKImageCropper/RSKImageCropper.h>

Using Carthage

  1. Add the ruslanskorb/RSKImageCropper project to your Cartfile.

    github "ruslanskorb/RSKImageCropper"
    
  2. Run carthage update, then follow the additional steps required to add the iOS and/or Mac frameworks into your project.

  3. Import the RSKImageCropper framework/module.

    • Using Modules: @import RSKImageCropper
    • Without Modules: #import <RSKImageCropper/RSKImageCropper.h>

Basic Usage

Import the class header.

#import <RSKImageCropper/RSKImageCropper.h>

Just create a view controller for image cropping and set the delegate.

- (IBAction)onButtonTouch:(UIButton *)sender
{
    UIImage *image = [UIImage imageNamed:@"image"];
    RSKImageCropViewController *imageCropVC = [[RSKImageCropViewController alloc] initWithImage:image];
    imageCropVC.delegate = self;
    [self.navigationController pushViewController:imageCropVC animated:YES];
}

Delegate

RSKImageCropViewControllerDelegate provides three delegate methods. To use them, implement the delegate in your view controller.

@interface ViewController () <RSKImageCropViewControllerDelegate>

Then implement the delegate functions.

// Crop image has been canceled.
- (void)imageCropViewControllerDidCancelCrop:(RSKImageCropViewController *)controller
{
    [self.navigationController popViewControllerAnimated:YES];
}

// The original image has been cropped. Additionally provides a rotation angle used to produce image.
- (void)imageCropViewController:(RSKImageCropViewController *)controller
                   didCropImage:(UIImage *)croppedImage
                  usingCropRect:(CGRect)cropRect
                  rotationAngle:(CGFloat)rotationAngle
{
    self.imageView.image = croppedImage;
    [self.navigationController popViewControllerAnimated:YES];
}

// The original image will be cropped.
- (void)imageCropViewController:(RSKImageCropViewController *)controller
                  willCropImage:(UIImage *)originalImage
{
    // Use when `applyMaskToCroppedImage` set to YES.
    [SVProgressHUD show];
}

DataSource

RSKImageCropViewControllerDataSource provides three data source methods. The method imageCropViewControllerCustomMaskRect: asks the data source a custom rect for the mask. The method imageCropViewControllerCustomMaskPath: asks the data source a custom path for the mask. The method imageCropViewControllerCustomMovementRect: asks the data source a custom rect in which the image can be moved. To use them, implement the data source in your view controller.

@interface ViewController () <RSKImageCropViewControllerDataSource>

Then implement the data source functions.

// Returns a custom rect for the mask.
- (CGRect)imageCropViewControllerCustomMaskRect:(RSKImageCropViewController *)controller
{
    CGSize aspectRatio = CGSizeMake(16.0f, 9.0f);
    
    CGFloat viewWidth = CGRectGetWidth(controller.view.frame);
    CGFloat viewHeight = CGRectGetHeight(controller.view.frame);
    
    CGFloat maskWidth;
    if ([controller isPortraitInterfaceOrientation]) {
        maskWidth = viewWidth;
    } else {
        maskWidth = viewHeight;
    }
    
    CGFloat maskHeight;
    do {
        maskHeight = maskWidth * aspectRatio.height / aspectRatio.width;
        maskWidth -= 1.0f;
    } while (maskHeight != floor(maskHeight));
    maskWidth += 1.0f;
    
    CGSize maskSize = CGSizeMake(maskWidth, maskHeight);
    
    CGRect maskRect = CGRectMake((viewWidth - maskSize.width) * 0.5f,
                                 (viewHeight - maskSize.height) * 0.5f,
                                 maskSize.width,
                                 maskSize.height);
    
    return maskRect;
}

// Returns a custom path for the mask.
- (UIBezierPath *)imageCropViewControllerCustomMaskPath:(RSKImageCropViewController *)controller
{
    CGRect rect = controller.maskRect;
    CGPoint point1 = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
    CGPoint point2 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
    CGPoint point3 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
    CGPoint point4 = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
    
    UIBezierPath *rectangle = [UIBezierPath bezierPath];
    [rectangle moveToPoint:point1];
    [rectangle addLineToPoint:point2];
    [rectangle addLineToPoint:point3];
    [rectangle addLineToPoint:point4];
    [rectangle closePath];
    
    return rectangle;
}

// Returns a custom rect in which the image can be moved.
- (CGRect)imageCropViewControllerCustomMovementRect:(RSKImageCropViewController *)controller
{
    if (controller.rotationAngle == 0) {
        return controller.maskRect;
    } else {
        CGRect maskRect = controller.maskRect;
        CGFloat rotationAngle = controller.rotationAngle;
        
        CGRect movementRect = CGRectZero;
        
        movementRect.size.width = CGRectGetWidth(maskRect) * fabs(cos(rotationAngle)) + CGRectGetHeight(maskRect) * fabs(sin(rotationAngle));
        movementRect.size.height = CGRectGetHeight(maskRect) * fabs(cos(rotationAngle)) + CGRectGetWidth(maskRect) * fabs(sin(rotationAngle));
        
        movementRect.origin.x = CGRectGetMinX(maskRect) + (CGRectGetWidth(maskRect) - CGRectGetWidth(movementRect)) * 0.5f;
        movementRect.origin.y = CGRectGetMinY(maskRect) + (CGRectGetHeight(maskRect) - CGRectGetHeight(movementRect)) * 0.5f;
        
        movementRect.origin.x = floor(CGRectGetMinX(movementRect));
        movementRect.origin.y = floor(CGRectGetMinY(movementRect));
        movementRect = CGRectIntegral(movementRect);
        
        return movementRect;
    }
}

Coming Soon

  • If you would like to request a new feature, feel free to raise as an issue.

Demo

Build and run the RSKImageCropperExample project in Xcode to see RSKImageCropper in action. Have fun. Fork and send pull requests. Figure out hooks for customization.

Contact

Ruslan Skorb

  • http://github.com/ruslanskorb
  • http://twitter.com/ruslanskorb
  • ruslan.skorb@gmail.com

License

This project is is available under the MIT license. See the LICENSE file for more info. Attribution by linking to the project page is appreciated.

Github

link
Stars: 2311

Dependencies

Used By

Total: 0

Releases

2.3.0: Add support for SPM. - 2020-09-06 12:01:10

2.2.3: Fix cropping image when `contentOffset` is not equal to zero. - 2019-07-25 07:26:10

Fixes #212.

2.2.2: Fix importing headers in Objective-C++ projects. - 2019-06-21 08:16:12

Fixes #210.

2.2.1: Fix position of the mask. - 2018-09-26 05:05:03

Fixes #200.

2.2.0: Add support for Xcode 10. - 2018-09-20 08:25:21

2.1.0: Add zoom to rect + fix `cropRect` for rotated images. - 2018-06-08 06:47:49

Resolves #194 and #179 and fixes #196.

Thanks @Discobanan and @iPhoNewsRO!

2.0.1: Use `prefersStatusBarHidden` instead of `setStatusBarHidden:`. - 2018-03-29 05:57:22

Fixes #186.

2.0.0: New requirements for the methods of `RSKImageCropViewControllerDelegate` and `RSKImageCropViewControllerDataSource`. - 2017-11-29 17:46:30

1.6.4: Fix transparent margins around the cropped image. - 2017-11-29 16:48:53

Fixes #182.

1.6.3: Fix UI API calls. - 2017-07-02 06:44:34

1.6.2: Fix the maximum zoom scale. - 2017-04-29 23:58:43

Thanks @nootfly!

1.6.1: Fix redefinition of module `RSKImageCropper`. - 2017-03-28 08:07:41

1.6.0: 14 additional languages. - 2017-01-28 12:19:09

Includes #129.

1.5.2: Fix rotation of the image. - 2016-12-01 05:34:19

1.5.1: More public headers in the Framework. - 2016-02-04 07:01:11

Fixes #94.

1.5.0: Support for animated images & More customization options. - 2016-01-29 13:12:11

Resolves #84, #86, #91, fixes #90.

1.4.1: Fix rect for stroked outline of the mask. - 2015-11-13 20:32:57

Fixes #78.

1.4.0: A customizable stroke of the mask & Nullability annotations. - 2015-11-12 12:14:21

Resolves #76.

1.3.2: Add missing resources to the framework. - 2015-10-20 07:21:01

1.3.1: Fix calculation of the crop rect for some cases. - 2015-09-14 16:20:22

1.3.0: Carthage, Framework, 30 new languages and more. - 2015-09-05 18:29:52

Includes #57 and #62, fixes #68.

1.2.1: Fix position of the crop mask on iPad in some cases. - 2015-07-08 04:17:34

Includes #59.

1.2.0: The powerful subclasses. - 2015-06-12 20:54:57

Extracts and exposes some internal methods for subclasses.

1.1.5: Small fixes. - 2015-05-27 07:46:18

  • [x] fix the condition of displaying an image (after setting a new original image)
  • [x] update test of displaying an image (after setting a new original image)
  • [x] add support for the navigation bar with the custom shadow image

1.1.3: Fix for preferred status bar state. - 2015-04-17 21:17:43

Fixes #48.

1.1.2: Support for App Extension. - 2015-03-28 19:01:01

Fixes #44.

1.1.1: Handle scale of images. - 2015-03-20 21:25:20

Fixes #41.

1.1.0: Support for rotation. - 2015-03-11 16:39:17

1.0.0: Initial stable API release. - 2015-02-26 11:12:35

Includes the main functionality.