diff --git a/Example/RSKImageCropperExample.xcodeproj/project.pbxproj b/Example/RSKImageCropperExample.xcodeproj/project.pbxproj index eb9f6eb..2f64234 100755 --- a/Example/RSKImageCropperExample.xcodeproj/project.pbxproj +++ b/Example/RSKImageCropperExample.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 89BB37728461FC8C20D81A2B /* libPods-RSKImageCropperExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74203A87984840A534E55F6C /* libPods-RSKImageCropperExampleTests.a */; }; B803F69E1AAB0A1F004141CF /* CGGeometry+RSKImageCropper.m in Sources */ = {isa = PBXBuildFile; fileRef = B803F69D1AAB0A1F004141CF /* CGGeometry+RSKImageCropper.m */; }; + B8182F2E1ABC998B00601E43 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B8182F2D1ABC998B00601E43 /* LaunchScreen.xib */; }; B87A99F019A4D2CD00D12CD4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87A99EF19A4D2CD00D12CD4 /* Foundation.framework */; }; B87A99F219A4D2CD00D12CD4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87A99F119A4D2CD00D12CD4 /* CoreGraphics.framework */; }; B87A99F419A4D2CD00D12CD4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87A99F319A4D2CD00D12CD4 /* UIKit.framework */; }; @@ -43,6 +44,7 @@ 74203A87984840A534E55F6C /* libPods-RSKImageCropperExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RSKImageCropperExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B803F69C1AAB0A1F004141CF /* CGGeometry+RSKImageCropper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CGGeometry+RSKImageCropper.h"; sourceTree = ""; }; B803F69D1AAB0A1F004141CF /* CGGeometry+RSKImageCropper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CGGeometry+RSKImageCropper.m"; sourceTree = ""; }; + B8182F2D1ABC998B00601E43 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; B87A99EC19A4D2CD00D12CD4 /* RSKImageCropperExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RSKImageCropperExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; B87A99EF19A4D2CD00D12CD4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; B87A99F119A4D2CD00D12CD4 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -139,6 +141,7 @@ B87A9A2119A4D31A00D12CD4 /* Controllers */, B87A9A0119A4D2CD00D12CD4 /* Images.xcassets */, B87A99F619A4D2CD00D12CD4 /* Supporting Files */, + B8182F2D1ABC998B00601E43 /* LaunchScreen.xib */, ); name = Classes; path = RSKImageCropperExample; @@ -299,6 +302,7 @@ files = ( B87A99FA19A4D2CD00D12CD4 /* InfoPlist.strings in Resources */, B87A9A0219A4D2CD00D12CD4 /* Images.xcassets in Resources */, + B8182F2E1ABC998B00601E43 /* LaunchScreen.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/RSKImageCropperExample/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/RSKImageCropperExample/Images.xcassets/AppIcon.appiconset/Contents.json index 91bf9c1..b7f3352 100755 --- a/Example/RSKImageCropperExample/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/RSKImageCropperExample/Images.xcassets/AppIcon.appiconset/Contents.json @@ -15,6 +15,11 @@ "size" : "60x60", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/Example/RSKImageCropperExample/Images.xcassets/photo.imageset/Contents.json b/Example/RSKImageCropperExample/Images.xcassets/photo.imageset/Contents.json index 46d099f..42e78d4 100755 --- a/Example/RSKImageCropperExample/Images.xcassets/photo.imageset/Contents.json +++ b/Example/RSKImageCropperExample/Images.xcassets/photo.imageset/Contents.json @@ -8,6 +8,10 @@ { "idiom" : "universal", "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/Example/RSKImageCropperExample/LaunchScreen.xib b/Example/RSKImageCropperExample/LaunchScreen.xib new file mode 100644 index 0000000..bf086ff --- /dev/null +++ b/Example/RSKImageCropperExample/LaunchScreen.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist b/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist index 81c7237..84a3af7 100755 --- a/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist +++ b/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist @@ -17,13 +17,15 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.0 + 1.1.1 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS + UILaunchStoryboardName + LaunchScreen UIRequiredDeviceCapabilities armv7 diff --git a/README.md b/README.md index a46bb21..c04055c 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,8 @@ Then implement the data source functions. // Returns a custom rect in which the image can be moved. - (CGRect)imageCropViewControllerCustomMovementRect:(RSKImageCropViewController *)controller { - return [self imageCropViewControllerCustomMaskRect:controller]; + // If the image is not rotated, then the movement rect coincides with the mask rect. + return controller.maskRect; } ``` diff --git a/RSKImageCropper.podspec b/RSKImageCropper.podspec index 137ddde..d0f72d0 100644 --- a/RSKImageCropper.podspec +++ b/RSKImageCropper.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RSKImageCropper' - s.version = '1.1.0' + s.version = '1.1.1' s.summary = 'An image cropper for iOS like in the Contacts app with support for landscape orientation.' s.homepage = 'https://github.com/ruslanskorb/RSKImageCropper' s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/RSKImageCropper/CGGeometry+RSKImageCropper.h b/RSKImageCropper/CGGeometry+RSKImageCropper.h index e016353..5004058 100644 --- a/RSKImageCropper/CGGeometry+RSKImageCropper.h +++ b/RSKImageCropper/CGGeometry+RSKImageCropper.h @@ -49,6 +49,9 @@ __tg_promote2((__x), (__y))(__y)) #undef fabs #define fabs(__x) __tg_fabs(__tg_promote1((__x))(__x)) +#undef ceil +#define ceil(__x) __tg_ceil(__tg_promote1((__x))(__x)) + #ifdef CGFLOAT_IS_DOUBLE #define RSK_EPSILON DBL_EPSILON #else diff --git a/RSKImageCropper/RSKImageCropViewController.m b/RSKImageCropper/RSKImageCropViewController.m index 5815484..b7460ff 100644 --- a/RSKImageCropper/RSKImageCropViewController.m +++ b/RSKImageCropper/RSKImageCropViewController.m @@ -752,13 +752,17 @@ - (UIImage *)croppedImage:(UIImage *)image cropMode:(RSKImageCropMode)cropMode c cropRect.origin.y = round(imageSize.height - CGRectGetHeight(cropRect) - y); } + CGFloat imageScale = image.scale; + cropRect = CGRectApplyAffineTransform(cropRect, CGAffineTransformMakeScale(imageScale, imageScale)); + // Step 2: create an image using the data contained within the specified rect. CGImageRef croppedCGImage = CGImageCreateWithImageInRect(image.CGImage, cropRect); - UIImage *croppedImage = [UIImage imageWithCGImage:croppedCGImage scale:1.0f orientation:imageOrientation]; + UIImage *croppedImage = [UIImage imageWithCGImage:croppedCGImage scale:imageScale orientation:imageOrientation]; CGImageRelease(croppedCGImage); // Step 3: fix orientation of the cropped image. croppedImage = [croppedImage fixOrientation]; + imageOrientation = croppedImage.imageOrientation; // Step 4: If current mode is `RSKImageCropModeSquare` and the image is not rotated // or mask should not be applied to the image after cropping and the image is not rotated, @@ -770,8 +774,9 @@ - (UIImage *)croppedImage:(UIImage *)image cropMode:(RSKImageCropMode)cropMode c } else { // Step 5: create a new context. CGSize maskSize = CGRectIntegral(maskPath.bounds).size; - CGSize contextSize = CGSizeMake(maskSize.width / zoomScale, maskSize.height / zoomScale); - UIGraphicsBeginImageContext(contextSize); + CGSize contextSize = CGSizeMake(ceil(maskSize.width / zoomScale), + ceil(maskSize.height / zoomScale)); + UIGraphicsBeginImageContextWithOptions(contextSize, NO, imageScale); // Step 6: apply the mask if needed. if (applyMaskToCroppedImage) { @@ -779,7 +784,7 @@ - (UIImage *)croppedImage:(UIImage *)image cropMode:(RSKImageCropMode)cropMode c UIBezierPath *maskPathCopy = [maskPath copy]; CGFloat scale = 1 / zoomScale; [maskPathCopy applyTransform:CGAffineTransformMakeScale(scale, scale)]; - + // 6b: move the mask to the top-left. CGPoint translation = CGPointMake(-CGRectGetMinX(maskPathCopy.bounds), -CGRectGetMinY(maskPathCopy.bounds)); @@ -805,7 +810,7 @@ - (UIImage *)croppedImage:(UIImage *)image cropMode:(RSKImageCropMode)cropMode c // Step 10: remove the context. UIGraphicsEndImageContext(); - croppedImage = [UIImage imageWithCGImage:croppedImage.CGImage]; + croppedImage = [UIImage imageWithCGImage:croppedImage.CGImage scale:imageScale orientation:imageOrientation]; // Step 11: return the cropped image affter processing. return croppedImage;