{"id":18283854,"url":"https://github.com/ruslanskorb/rskimagecropper","last_synced_at":"2025-05-13T17:08:28.511Z","repository":{"id":20024422,"uuid":"23292312","full_name":"ruslanskorb/RSKImageCropper","owner":"ruslanskorb","description":"An image / photo crop view controller for iOS like in the Contacts app with support for landscape orientation.","archived":false,"fork":false,"pushed_at":"2024-12-15T09:54:05.000Z","size":135551,"stargazers_count":2449,"open_issues_count":1,"forks_count":471,"subscribers_count":65,"default_branch":"master","last_synced_at":"2025-05-10T01:36:01.521Z","etag":null,"topics":["contacts-app","crop","cropper","cropping","edit","editor","image","photo","trimming"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruslanskorb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-24T20:44:47.000Z","updated_at":"2025-04-14T09:41:50.000Z","dependencies_parsed_at":"2023-02-12T08:30:17.412Z","dependency_job_id":"35331763-3aba-4692-bf2a-426e738a0be4","html_url":"https://github.com/ruslanskorb/RSKImageCropper","commit_stats":{"total_commits":375,"total_committers":17,"mean_commits":"22.058823529411764","dds":"0.45333333333333337","last_synced_commit":"f6fb28b240e1d67228488c51865c7df480c910ff"},"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruslanskorb%2FRSKImageCropper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruslanskorb%2FRSKImageCropper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruslanskorb%2FRSKImageCropper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruslanskorb%2FRSKImageCropper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruslanskorb","download_url":"https://codeload.github.com/ruslanskorb/RSKImageCropper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253990467,"owners_count":21995774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contacts-app","crop","cropper","cropping","edit","editor","image","photo","trimming"],"created_at":"2024-11-05T13:11:10.074Z","updated_at":"2025-05-13T17:08:23.496Z","avatar_url":"https://github.com/ruslanskorb.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"## RSKImageCropper ![CI](https://github.com/ruslanskorb/RSKImageCropper/actions/workflows/main.yml/badge.svg) ![Swift Package Manager](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat) ![CocoaPods](https://img.shields.io/cocoapods/v/RSKImageCropper.svg?style=flat) ![Carthage](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"Screenshot.png\" alt=\"Sample\"\u003e\n\u003c/p\u003e\n\nAn image cropper for iOS like in the Contacts app with support for landscape orientation.\n\n## Installation\n*RSKImageCropper requires iOS 12.0 or later.*\n\n### Using [Swift Package Manager](https://swift.org/package-manager/)\n\n1. To add the `RSKImageCropper` package to your Xcode project, select File \u003e Swift Packages \u003e Add Package Dependency and enter the repository URL. \n    \n        https://github.com/ruslanskorb/RSKImageCropper.git\n\n### Using [CocoaPods](http://cocoapods.org)\n\n1.  Add the pod `RSKImageCropper` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html).\n\n        pod 'RSKImageCropper'\n\n2.  Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode.\n3.  Import the `RSKImageCropper.h` header. Typically, this should be written as `#import \u003cRSKImageCropper/RSKImageCropper.h\u003e`\n\n### Using [Carthage](https://github.com/Carthage/Carthage)\n\n1.  Add the `ruslanskorb/RSKImageCropper` project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile).\n\n        github \"ruslanskorb/RSKImageCropper\"\n\n2.  Run `carthage update`, then follow the [additional steps required](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add the iOS and/or Mac frameworks into your project.\n3.  Import the RSKImageCropper framework/module.\n    *  Using Modules: `@import RSKImageCropper`\n    *  Without Modules: `#import \u003cRSKImageCropper/RSKImageCropper.h\u003e`\n\n## Basic Usage\n\nImport the class header.\n\n``` objective-c\n#import \u003cRSKImageCropper/RSKImageCropper.h\u003e\n```\n\nJust create a view controller for image cropping and set the delegate.\n\n``` objective-c\n- (IBAction)onButtonTouch:(UIButton *)sender\n{\n    UIImage *image = [UIImage imageNamed:@\"image\"];\n    RSKImageCropViewController *imageCropViewController = [[RSKImageCropViewController alloc] initWithImage:image];\n    imageCropViewController.delegate = self;\n    [self.navigationController pushViewController:imageCropViewController animated:YES];\n}\n```\n\n## Delegate\n\n`RSKImageCropViewControllerDelegate` provides three delegate methods. To use them, implement the delegate in your view controller.\n\n```objective-c\n@interface ViewController () \u003cRSKImageCropViewControllerDelegate\u003e\n```\n\nThen implement the delegate functions.\n\n```objective-c\n// Crop image has been canceled.\n- (void)imageCropViewControllerDidCancelCrop:(RSKImageCropViewController *)controller\n{\n    [self.navigationController popViewControllerAnimated:YES];\n}\n\n// The original image has been cropped. Additionally provides a rotation angle used to produce image.\n- (void)imageCropViewController:(RSKImageCropViewController *)controller\n                   didCropImage:(UIImage *)croppedImage\n                  usingCropRect:(CGRect)cropRect\n                  rotationAngle:(CGFloat)rotationAngle\n{\n    self.imageView.image = croppedImage;\n    [self.navigationController popViewControllerAnimated:YES];\n}\n\n// The original image will be cropped.\n- (void)imageCropViewController:(RSKImageCropViewController *)controller\n                  willCropImage:(UIImage *)originalImage\n{\n    // Use when `applyMaskToCroppedImage` set to YES.\n    [SVProgressHUD show];\n}\n```\n\n## DataSource\n\n`RSKImageCropViewControllerDataSource` provides three data source methods. The method `imageCropViewControllerCustomMaskRect:` asks the data source for a custom rect for the mask. The method `imageCropViewControllerCustomMaskPath:` asks the data source for a custom path for the mask. The method `imageCropViewControllerCustomMovementRect:` asks the data source for a custom rect in which the image can be moved. To use them, implement the data source in your view controller.\n\n```objective-c\n@interface ViewController () \u003cRSKImageCropViewControllerDataSource\u003e\n```\n\nThen implement the data source functions.\n\n```objective-c\n// Returns a custom rect for the mask.\n- (CGRect)imageCropViewControllerCustomMaskRect:(RSKImageCropViewController *)controller\n{\n    CGSize aspectRatio = CGSizeMake(16.0f, 9.0f);\n    \n    CGFloat viewWidth = CGRectGetWidth(controller.view.frame);\n    CGFloat viewHeight = CGRectGetHeight(controller.view.frame);\n    \n    CGFloat maskWidth;\n    if ([controller isPortraitInterfaceOrientation]) {\n        maskWidth = viewWidth;\n    } else {\n        maskWidth = viewHeight;\n    }\n    \n    CGFloat maskHeight;\n    do {\n        maskHeight = maskWidth * aspectRatio.height / aspectRatio.width;\n        maskWidth -= 1.0f;\n    } while (maskHeight != floor(maskHeight));\n    maskWidth += 1.0f;\n    \n    CGSize maskSize = CGSizeMake(maskWidth, maskHeight);\n    \n    CGRect maskRect = CGRectMake((viewWidth - maskSize.width) * 0.5f,\n                                 (viewHeight - maskSize.height) * 0.5f,\n                                 maskSize.width,\n                                 maskSize.height);\n    \n    return maskRect;\n}\n\n// Returns a custom path for the mask.\n- (UIBezierPath *)imageCropViewControllerCustomMaskPath:(RSKImageCropViewController *)controller\n{\n    CGRect rect = controller.maskRect;\n    CGPoint point1 = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));\n    CGPoint point2 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));\n    CGPoint point3 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));\n    CGPoint point4 = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));\n    \n    UIBezierPath *rectangle = [UIBezierPath bezierPath];\n    [rectangle moveToPoint:point1];\n    [rectangle addLineToPoint:point2];\n    [rectangle addLineToPoint:point3];\n    [rectangle addLineToPoint:point4];\n    [rectangle closePath];\n    \n    return rectangle;\n}\n\n// Returns a custom rect in which the image can be moved.\n- (CGRect)imageCropViewControllerCustomMovementRect:(RSKImageCropViewController *)controller\n{\n    if (controller.rotationAngle == 0) {\n        return controller.maskRect;\n    } else {\n        CGRect maskRect = controller.maskRect;\n        CGFloat rotationAngle = controller.rotationAngle;\n        \n        CGRect movementRect = CGRectZero;\n        \n        movementRect.size.width = CGRectGetWidth(maskRect) * fabs(cos(rotationAngle)) + CGRectGetHeight(maskRect) * fabs(sin(rotationAngle));\n        movementRect.size.height = CGRectGetHeight(maskRect) * fabs(cos(rotationAngle)) + CGRectGetWidth(maskRect) * fabs(sin(rotationAngle));\n        \n        movementRect.origin.x = CGRectGetMinX(maskRect) + (CGRectGetWidth(maskRect) - CGRectGetWidth(movementRect)) * 0.5f;\n        movementRect.origin.y = CGRectGetMinY(maskRect) + (CGRectGetHeight(maskRect) - CGRectGetHeight(movementRect)) * 0.5f;\n        \n        movementRect.origin.x = floor(CGRectGetMinX(movementRect));\n        movementRect.origin.y = floor(CGRectGetMinY(movementRect));\n        movementRect = CGRectIntegral(movementRect);\n        \n        return movementRect;\n    }\n}\n```\n\n## Coming Soon\n\n- If you would like to request a new feature, feel free to raise an issue.\n\n## Demo\n\nBuild and run the `RSKImageCropperExample` project in Xcode to see `RSKImageCropper` in action.\nHave fun. Fork and send pull requests. Figure out hooks for customization.\n\n## Privacy\n\n`RSKImageCropper` doesn't require a privacy manifest. According to [information received from Apple](https://developer.apple.com/forums/thread/746481?answerId=782256022#782256022), we should avoid adding an empty privacy manifest to our frameworks.\n\n## Contact\n\nRuslan Skorb\n\n- http://github.com/ruslanskorb\n- http://twitter.com/ruslanskorb\n- ruslan.skorb@gmail.com\n\n## License\n\nThis project is available under the MIT license. See the LICENSE file for more info. Attribution by linking to the [project page](https://github.com/ruslanskorb/RSKImageCropper) is appreciated.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruslanskorb%2Frskimagecropper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruslanskorb%2Frskimagecropper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruslanskorb%2Frskimagecropper/lists"}