├── .DS_Store
├── .gitignore
├── Info.plist
├── LICENSE
├── PureCamera.podspec
├── PureCamera
├── LLSimpleCamera+Helper.h
├── LLSimpleCamera+Helper.m
├── LLSimpleCamera.h
├── LLSimpleCamera.m
├── PureCamera.bundle
│ ├── camera-flash.png
│ ├── camera-flash@2x.png
│ ├── cameraButton.png
│ ├── cameraButton@2x.png
│ ├── cameraButton@3x.png
│ ├── closeButton.png
│ ├── closeButton@2x.png
│ ├── closeButton@3x.png
│ ├── en.lproj
│ │ └── Root.strings
│ ├── swapButton.png
│ ├── swapButton@2x.png
│ └── swapButton@3x.png
├── PureCamera.h
├── PureCamera.m
├── PureCropVC.h
├── PureCropVC.m
├── TOActivityCroppedImageProvider.h
├── TOActivityCroppedImageProvider.m
├── TOCropOverlayView.h
├── TOCropOverlayView.m
├── TOCropScrollView.h
├── TOCropScrollView.m
├── TOCropToolbar.h
├── TOCropToolbar.m
├── TOCropView.h
├── TOCropView.m
├── TOCropViewController.h
├── TOCropViewController.m
├── TOCropViewControllerLocalizable.strings
├── TOCropViewControllerTransitioning.h
├── TOCropViewControllerTransitioning.m
├── TOCroppedImageAttributes.h
├── TOCroppedImageAttributes.m
├── UIImage+CropRotate.h
├── UIImage+CropRotate.m
├── UIImage+FixOrientation.h
└── UIImage+FixOrientation.m
├── PureCamerademo.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ ├── shiyue.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ └── sunkaifeng.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcuserdata
│ ├── shiyue.xcuserdatad
│ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ │ └── xcschememanagement.plist
│ └── sunkaifeng.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ └── xcschememanagement.plist
├── PureCamerademo
└── PureCamerademo
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── 1.imageset
│ │ ├── C8AECEE3EC242CAA4442358F3D912F9A.jpg
│ │ └── Contents.json
│ ├── 2.imageset
│ │ ├── Contents.json
│ │ └── FE00349D152834B01E38D3F64A9D1217.jpg
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── KModel.h
│ ├── KModel.m
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── README.md
└── azure-pipelines.yml
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /PureCamerademo.xcodeproj/xcuserdata
2 | /PureCamerademo.xcodeproj/project.xcworkspace/xcuserdata
3 | Podfile.lock
4 | /Pods
5 | /PureCamerademo.xcworkspace
6 | .DS_Store
7 |
8 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.6.3
19 | CFBundleVersion
20 | 180508
21 | LSRequiresIPhoneOS
22 |
23 | NSCameraUsageDescription
24 | 使用相机
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 wubianxiaoxian
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/PureCamera.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint Purecamera.podspec' to ensure this is a
3 | # valid spec and to remove all comments including this before submitting the spec.
4 | #
5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 | Pod::Spec.new do |s|
9 | s.name = 'PureCamera'
10 | s.version = '1.6.3'
11 | s.summary = "This one can customize the camera to take pictures of the page of the library, but also to support the cutting of the photo when the camera is completed."
12 | s.license = "MIT"
13 | s.description = 'This one can customize the camera to take pictures of the page of the library, but also to support the cutting of the photo when the camera is completed.thanyou'
14 | s.homepage = "https://github.com/wubianxiaoxian/PureCamera-Demo"
15 | s.screenshots = "http://i1.piimg.com/4851/0071da17a0c177d6.gif"
16 | s.author = { 'Kaifeng Sun' => 'sunkaifengdiyi@163.com' }
17 | s.platform = :ios, "8.1"
18 | s.source_files = 'PureCamera/**/*'
19 | s.resource = "PureCamera/PureCamera.bundle"
20 | s.requires_arc = true
21 | s.framework = "UIKit"
22 | s.source = { :git => "https://github.com/wubianxiaoxian/PureCamera-Demo.git", :tag =>s.version }
23 | end
24 |
25 |
--------------------------------------------------------------------------------
/PureCamera/LLSimpleCamera+Helper.h:
--------------------------------------------------------------------------------
1 | //
2 | // LLSimpleCamera+Helper.h
3 | // LLSimpleCameraExample
4 | //
5 | // Created by Ömer Faruk Gül on 20/02/16.
6 | // Copyright © 2016 Ömer Faruk Gül. All rights reserved.
7 | //
8 |
9 | #import "LLSimpleCamera.h"
10 |
11 | @interface LLSimpleCamera (Helper)
12 |
13 | - (CGPoint)convertToPointOfInterestFromViewCoordinates:(CGPoint)viewCoordinates
14 | previewLayer:(AVCaptureVideoPreviewLayer *)previewLayer
15 | ports:(NSArray *)ports;
16 |
17 | - (UIImage *)cropImage:(UIImage *)image usingPreviewLayer:(AVCaptureVideoPreviewLayer *)previewLayer;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/PureCamera/LLSimpleCamera+Helper.m:
--------------------------------------------------------------------------------
1 | //
2 | // LLSimpleCamera+Helper.m
3 | // LLSimpleCameraExample
4 | //
5 | // Created by Ömer Faruk Gül on 20/02/16.
6 | // Copyright © 2016 Ömer Faruk Gül. All rights reserved.
7 | //
8 |
9 | #import "LLSimpleCamera+Helper.h"
10 |
11 | @implementation LLSimpleCamera (Helper)
12 |
13 | - (CGPoint)convertToPointOfInterestFromViewCoordinates:(CGPoint)viewCoordinates
14 | previewLayer:(AVCaptureVideoPreviewLayer *)previewLayer
15 | ports:(NSArray *)ports
16 | {
17 | CGPoint pointOfInterest = CGPointMake(.5f, .5f);
18 | CGSize frameSize = previewLayer.frame.size;
19 |
20 | if ( [previewLayer.videoGravity isEqualToString:AVLayerVideoGravityResize] ) {
21 | pointOfInterest = CGPointMake(viewCoordinates.y / frameSize.height, 1.f - (viewCoordinates.x / frameSize.width));
22 | } else {
23 | CGRect cleanAperture;
24 | for (AVCaptureInputPort *port in ports) {
25 | if (port.mediaType == AVMediaTypeVideo) {
26 | cleanAperture = CMVideoFormatDescriptionGetCleanAperture([port formatDescription], YES);
27 | CGSize apertureSize = cleanAperture.size;
28 | CGPoint point = viewCoordinates;
29 |
30 | CGFloat apertureRatio = apertureSize.height / apertureSize.width;
31 | CGFloat viewRatio = frameSize.width / frameSize.height;
32 | CGFloat xc = .5f;
33 | CGFloat yc = .5f;
34 |
35 | if ( [previewLayer.videoGravity isEqualToString:AVLayerVideoGravityResizeAspect] ) {
36 | if (viewRatio > apertureRatio) {
37 | CGFloat y2 = frameSize.height;
38 | CGFloat x2 = frameSize.height * apertureRatio;
39 | CGFloat x1 = frameSize.width;
40 | CGFloat blackBar = (x1 - x2) / 2;
41 | if (point.x >= blackBar && point.x <= blackBar + x2) {
42 | xc = point.y / y2;
43 | yc = 1.f - ((point.x - blackBar) / x2);
44 | }
45 | } else {
46 | CGFloat y2 = frameSize.width / apertureRatio;
47 | CGFloat y1 = frameSize.height;
48 | CGFloat x2 = frameSize.width;
49 | CGFloat blackBar = (y1 - y2) / 2;
50 | if (point.y >= blackBar && point.y <= blackBar + y2) {
51 | xc = ((point.y - blackBar) / y2);
52 | yc = 1.f - (point.x / x2);
53 | }
54 | }
55 | } else if ([previewLayer.videoGravity isEqualToString:AVLayerVideoGravityResizeAspectFill]) {
56 | if (viewRatio > apertureRatio) {
57 | CGFloat y2 = apertureSize.width * (frameSize.width / apertureSize.height);
58 | xc = (point.y + ((y2 - frameSize.height) / 2.f)) / y2;
59 | yc = (frameSize.width - point.x) / frameSize.width;
60 | } else {
61 | CGFloat x2 = apertureSize.height * (frameSize.height / apertureSize.width);
62 | yc = 1.f - ((point.x + ((x2 - frameSize.width) / 2)) / x2);
63 | xc = point.y / frameSize.height;
64 | }
65 | }
66 |
67 | pointOfInterest = CGPointMake(xc, yc);
68 | break;
69 | }
70 | }
71 | }
72 |
73 | return pointOfInterest;
74 | }
75 |
76 | - (UIImage *)cropImage:(UIImage *)image usingPreviewLayer:(AVCaptureVideoPreviewLayer *)previewLayer
77 | {
78 | CGRect previewBounds = previewLayer.bounds;
79 | CGRect outputRect = [previewLayer metadataOutputRectOfInterestForRect:previewBounds];
80 |
81 | CGImageRef takenCGImage = image.CGImage;
82 | size_t width = CGImageGetWidth(takenCGImage);
83 | size_t height = CGImageGetHeight(takenCGImage);
84 | CGRect cropRect = CGRectMake(outputRect.origin.x * width, outputRect.origin.y * height,
85 | outputRect.size.width * width, outputRect.size.height * height);
86 |
87 | CGImageRef cropCGImage = CGImageCreateWithImageInRect(takenCGImage, cropRect);
88 | image = [UIImage imageWithCGImage:cropCGImage scale:1 orientation:image.imageOrientation];
89 | CGImageRelease(cropCGImage);
90 |
91 | return image;
92 | }
93 |
94 | @end
95 |
--------------------------------------------------------------------------------
/PureCamera/LLSimpleCamera.h:
--------------------------------------------------------------------------------
1 | //
2 | // CameraViewController.h
3 | // LLSimpleCamera
4 | //
5 | // Created by Ömer Faruk Gül on 24/10/14.
6 | // Copyright (c) 2014 Ömer Farul Gül. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | typedef enum : NSUInteger {
13 | LLCameraPositionRear,
14 | LLCameraPositionFront
15 | } LLCameraPosition;
16 |
17 | typedef enum : NSUInteger {
18 | // The default state has to be off
19 | LLCameraFlashOff,
20 | LLCameraFlashOn,
21 | LLCameraFlashAuto
22 | } LLCameraFlash;
23 |
24 | typedef enum : NSUInteger {
25 | // The default state has to be off
26 | LLCameraMirrorOff,
27 | LLCameraMirrorOn,
28 | LLCameraMirrorAuto
29 | } LLCameraMirror;
30 |
31 | extern NSString *const LLSimpleCameraErrorDomain;
32 | typedef enum : NSUInteger {
33 | LLSimpleCameraErrorCodeCameraPermission = 10,
34 | LLSimpleCameraErrorCodeMicrophonePermission = 11,
35 | LLSimpleCameraErrorCodeSession = 12,
36 | LLSimpleCameraErrorCodeVideoNotEnabled = 13
37 | } LLSimpleCameraErrorCode;
38 |
39 | @interface LLSimpleCamera : UIViewController
40 |
41 | /**
42 | * Triggered on device change.
43 | */
44 | @property (nonatomic, copy) void (^onDeviceChange)(LLSimpleCamera *camera, AVCaptureDevice *device);
45 |
46 | /**
47 | * Triggered on any kind of error.
48 | */
49 | @property (nonatomic, copy) void (^onError)(LLSimpleCamera *camera, NSError *error);
50 |
51 | /**
52 | * Triggered when camera starts recording
53 | */
54 | @property (nonatomic, copy) void (^onStartRecording)(LLSimpleCamera* camera);
55 |
56 | /**
57 | * Camera quality, set a constants prefixed with AVCaptureSessionPreset.
58 | * Make sure to call before calling -(void)initialize method, otherwise it would be late.
59 | */
60 | @property (copy, nonatomic) NSString *cameraQuality;
61 |
62 | /**
63 | * Camera flash mode.
64 | */
65 | @property (nonatomic, readonly) LLCameraFlash flash;
66 |
67 | /**
68 | * Camera mirror mode.
69 | */
70 | @property (nonatomic) LLCameraMirror mirror;
71 |
72 | /**
73 | * Position of the camera.
74 | */
75 | @property (nonatomic) LLCameraPosition position;
76 |
77 | /**
78 | * White balance mode. Default is: AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance
79 | */
80 | @property (nonatomic) AVCaptureWhiteBalanceMode whiteBalanceMode;
81 |
82 | /**
83 | * Boolean value to indicate if the video is enabled.
84 | */
85 | @property (nonatomic, getter=isVideoEnabled) BOOL videoEnabled;
86 |
87 | /**
88 | * Boolean value to indicate if the camera is recording a video at the current moment.
89 | */
90 | @property (nonatomic, getter=isRecording) BOOL recording;
91 |
92 | /**
93 | * Boolean value to indicate if zooming is enabled.
94 | */
95 | @property (nonatomic, getter=isZoomingEnabled) BOOL zoomingEnabled;
96 |
97 | /**
98 | * Float value to set maximum scaling factor
99 | */
100 | @property (nonatomic, assign) CGFloat maxScale;
101 |
102 | /**
103 | * Fixess the orientation after the image is captured is set to Yes.
104 | * see: http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload
105 | */
106 | @property (nonatomic) BOOL fixOrientationAfterCapture;
107 |
108 | /**
109 | * Set NO if you don't want ot enable user triggered focusing. Enabled by default.
110 | */
111 | @property (nonatomic) BOOL tapToFocus;
112 |
113 | /**
114 | * Set YES if you your view controller does not allow autorotation,
115 | * however you want to take the device rotation into account no matter what. Disabled by default.
116 | */
117 | @property (nonatomic) BOOL useDeviceOrientation;
118 |
119 | /**
120 | * Use this method to request camera permission before initalizing LLSimpleCamera.
121 | */
122 | + (void)requestCameraPermission:(void (^)(BOOL granted))completionBlock;
123 |
124 | /**
125 | * Use this method to request microphone permission before initalizing LLSimpleCamera.
126 | */
127 | + (void)requestMicrophonePermission:(void (^)(BOOL granted))completionBlock;
128 |
129 | /**
130 | * Returns an instance of LLSimpleCamera with the given quality.
131 | * Quality parameter could be any variable starting with AVCaptureSessionPreset.
132 | */
133 | - (instancetype)initWithQuality:(NSString *)quality position:(LLCameraPosition)position;
134 |
135 |
136 |
137 | /**
138 | * Starts running the camera session.
139 | */
140 | - (void)start;
141 |
142 | /**
143 | * Stops the running camera session. Needs to be called when the app doesn't show the view.
144 | */
145 | - (void)stop;
146 |
147 |
148 | /**
149 | * Capture an image.
150 | * @param onCapture a block triggered after the capturing the photo.
151 | * @param exactSeenImage If set YES, then the image is cropped to the exact size as the preview. So you get exactly what you see.
152 | * @param animationBlock you can create your own animation by playing with preview layer.
153 | */
154 | -(void)capture:(void (^)(LLSimpleCamera *camera, UIImage *image, NSDictionary *metadata, NSError *error))onCapture exactSeenImage:(BOOL)exactSeenImage animationBlock:(void (^)(AVCaptureVideoPreviewLayer *))animationBlock;
155 |
156 | /**
157 | * Capture an image.
158 | * @param onCapture a block triggered after the capturing the photo.
159 | * @param exactSeenImage If set YES, then the image is cropped to the exact size as the preview. So you get exactly what you see.
160 | */
161 | -(void)capture:(void (^)(LLSimpleCamera *camera, UIImage *image, NSDictionary *metadata, NSError *error))onCapture exactSeenImage:(BOOL)exactSeenImage;
162 |
163 | /**
164 | * Capture an image.
165 | * @param onCapture a block triggered after the capturing the photo.
166 | */
167 | -(void)capture:(void (^)(LLSimpleCamera *camera, UIImage *image, NSDictionary *metadata, NSError *error))onCapture;
168 |
169 | /**
170 | * Attaches the LLSimpleCamera to another view controller with a frame. It basically adds the LLSimpleCamera as a
171 | * child vc to the given vc.
172 | * @param vc A view controller.
173 | * @param frame The frame of the camera.
174 | */
175 | - (void)attachToViewController:(UIViewController *)vc withFrame:(CGRect)frame;
176 |
177 | /**
178 | * Changes the posiition of the camera (either back or front) and returns the final position.
179 | */
180 | - (LLCameraPosition)togglePosition;
181 |
182 | /**
183 | * Update the flash mode of the camera. Returns true if it is successful. Otherwise false.
184 | */
185 | - (BOOL)updateFlashMode:(LLCameraFlash)cameraFlash;
186 |
187 | /**
188 | * Checks if flash is avilable for the currently active device.
189 | */
190 | - (BOOL)isFlashAvailable;
191 |
192 | /**
193 | * Checks if torch (flash for video) is avilable for the currently active device.
194 | */
195 | - (BOOL)isTorchAvailable;
196 |
197 | /**
198 | * Alter the layer and the animation displayed when the user taps on screen.
199 | * @param layer Layer to be displayed
200 | * @param animation to be applied after the layer is shown
201 | */
202 | - (void)alterFocusBox:(CALayer *)layer animation:(CAAnimation *)animation;
203 |
204 | /**
205 | * Checks is the front camera is available.
206 | */
207 | + (BOOL)isFrontCameraAvailable;
208 |
209 | /**
210 | * Checks is the rear camera is available.
211 | */
212 | + (BOOL)isRearCameraAvailable;
213 | @end
214 |
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/camera-flash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/camera-flash.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/camera-flash@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/camera-flash@2x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/cameraButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/cameraButton.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/cameraButton@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/cameraButton@2x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/cameraButton@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/cameraButton@3x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/closeButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/closeButton.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/closeButton@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/closeButton@2x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/closeButton@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/closeButton@3x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/en.lproj/Root.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/en.lproj/Root.strings
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/swapButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/swapButton.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/swapButton@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/swapButton@2x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.bundle/swapButton@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamera/PureCamera.bundle/swapButton@3x.png
--------------------------------------------------------------------------------
/PureCamera/PureCamera.h:
--------------------------------------------------------------------------------
1 | /*!
2 | @abstract
3 |
4 | */
5 | #import
6 | #import "TOCropViewController.h"
7 |
8 | typedef void (^fininshcapture)(UIImage *image);
9 | @interface PureCamera : UIViewController
10 | @property (nonatomic,copy) fininshcapture fininshcapture;
11 | //@property (nonatomic,assign) fininshcapture fininshcapture;
12 | @property (nonatomic, assign) TOCropViewControllerAspectRatio aspectRatioStle;
13 |
14 |
15 |
16 |
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/PureCamera/PureCamera.m:
--------------------------------------------------------------------------------
1 | /*!
2 | @abstract
3 | Created by 孙凯峰 on 2016/10/18.
4 | */
5 | #define KScreenSize [UIScreen mainScreen].bounds.size
6 | #define KScreenwidth [UIScreen mainScreen].bounds.size.width
7 | #define KScreenheight [UIScreen mainScreen].bounds.size.height
8 | #define IsIphone6P KScreenSize.width==414
9 | #define IsIphone6 KScreenSize.width==375
10 | #define IsIphone5S KScreenSize.height==568
11 | #define IsIphone5 KScreenSize.height==568
12 | //456字体大小
13 | #define KIOS_Iphone456(iphone6p,iphone6,iphone5s,iphone5,iphone4s) (IsIphone6P?iphone6p:(IsIphone6?iphone6:((IsIphone5S||IsIphone5)?iphone5s:iphone4s)))
14 | //宽高
15 | #define KIphoneSize_Widith(iphone6) (IsIphone6P?1.104*iphone6:(IsIphone6?iphone6:((IsIphone5S||IsIphone5)?0.853*iphone6:0.853*iphone6)))
16 | #define KIphoneSize_Height(iphone6) (IsIphone6P?1.103*iphone6:(IsIphone6?iphone6:((IsIphone5S||IsIphone5)?0.851*iphone6:0.720*iphone6)))
17 | #import "PureCamera.h"
18 | #import "TOCropViewController.h"
19 | #import "LLSimpleCamera.h"
20 |
21 | @interface PureCamera ()
22 | @property (strong, nonatomic) LLSimpleCamera *camera;
23 | @property (strong, nonatomic) UILabel *errorLabel;
24 | @property (strong, nonatomic) UIButton *snapButton;
25 | @property (strong, nonatomic) UIButton *switchButton;
26 | @property (strong, nonatomic) UIButton *flashButton;
27 | @property (strong, nonatomic) UIButton *backButton;
28 |
29 | @end
30 |
31 | @implementation PureCamera
32 |
33 | - (void)viewDidLoad
34 | {
35 | [super viewDidLoad];
36 | //拍照按钮
37 | [self InitializeCamera];
38 | NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"PureCamera" ofType:@"bundle"]];
39 | self.snapButton = [UIButton buttonWithType:UIButtonTypeCustom];
40 | self.snapButton.clipsToBounds = YES;
41 | self.snapButton.layer.cornerRadius =75 / 2.0f;
42 | UIImage *snapImg = [UIImage imageNamed:@"cameraButton" inBundle:bundle compatibleWithTraitCollection:nil];
43 | [self.snapButton setImage:snapImg forState:UIControlStateNormal];
44 | [self.snapButton addTarget:self action:@selector(snapButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
45 | [self.view addSubview:self.snapButton];
46 | //闪关灯按钮
47 | self.flashButton = [UIButton buttonWithType:UIButtonTypeSystem];
48 |
49 | self.flashButton.tintColor = [UIColor whiteColor];
50 | UIImage *flashImg = [UIImage imageNamed:@"camera-flash" inBundle:bundle compatibleWithTraitCollection:nil];
51 | [self.flashButton setImage:flashImg forState:UIControlStateNormal];
52 | self.flashButton.imageEdgeInsets = UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f);
53 | [self.flashButton addTarget:self action:@selector(flashButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
54 | [self.view addSubview:self.flashButton];
55 | if([LLSimpleCamera isFrontCameraAvailable] && [LLSimpleCamera isRearCameraAvailable]) {
56 | //摄像头转换按钮
57 | self.switchButton = [UIButton buttonWithType:UIButtonTypeCustom];
58 | UIImage *switchhImg = [UIImage imageNamed:@"swapButton" inBundle:bundle compatibleWithTraitCollection:nil];
59 | [self.switchButton setImage:switchhImg forState:UIControlStateNormal];
60 | [self.switchButton addTarget:self action:@selector(switchButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
61 | [self.view addSubview:self.switchButton];
62 | //返回按钮
63 | self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
64 | UIImage *closeImage= [UIImage imageNamed:@"closeButton" inBundle:bundle compatibleWithTraitCollection:nil];
65 | [self.backButton setImage:closeImage forState:UIControlStateNormal];
66 | [self.backButton addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
67 | [self.view addSubview:self.backButton];
68 | }
69 |
70 | }
71 |
72 |
73 | - (void)viewWillAppear:(BOOL)animated
74 | {
75 | [super viewWillAppear:animated];
76 | self.view.backgroundColor = [UIColor blackColor];
77 | [self.navigationController setNavigationBarHidden:YES animated:NO];
78 | // snap button to capture image
79 |
80 | //判断前后摄像头是否可用
81 |
82 |
83 | // start the camera
84 | [self.camera start];
85 | }
86 | #pragma mark ------------- 初始化相机--------------
87 | -(void)InitializeCamera{
88 | CGRect screenRect = self.view.frame;
89 |
90 | // 创建一个相机
91 | self.camera = [[LLSimpleCamera alloc] initWithQuality:AVCaptureSessionPresetHigh position:LLCameraPositionRear];
92 |
93 | // attach to a view controller
94 | [self.camera attachToViewController:self withFrame:CGRectMake(0, 0, screenRect.size.width, screenRect.size.height)];
95 |
96 | self.camera.fixOrientationAfterCapture = NO;
97 |
98 | // take the required actions on a device change
99 | __weak typeof(self) weakSelf = self;
100 | [self.camera setOnDeviceChange:^(LLSimpleCamera *camera, AVCaptureDevice * device) {
101 |
102 | NSLog(@"Device changed.");
103 |
104 | // device changed, check if flash is available
105 | if([camera isFlashAvailable]) {
106 | weakSelf.flashButton.hidden = NO;
107 |
108 | if(camera.flash == LLCameraFlashOff) {
109 | weakSelf.flashButton.selected = NO;
110 | }
111 | else {
112 | weakSelf.flashButton.selected = YES;
113 | }
114 | }
115 | else {
116 | weakSelf.flashButton.hidden = YES;
117 | }
118 | }];
119 |
120 | [self.camera setOnError:^(LLSimpleCamera *camera, NSError *error) {
121 | NSLog(@"Camera error: %@", error);
122 |
123 | if([error.domain isEqualToString:LLSimpleCameraErrorDomain]) {
124 | if(error.code == LLSimpleCameraErrorCodeCameraPermission) {
125 | if(weakSelf.errorLabel) {
126 | [weakSelf.errorLabel removeFromSuperview];
127 | }
128 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
129 | label.text = @"未获取相机权限";
130 | label.numberOfLines = 2;
131 | label.lineBreakMode = NSLineBreakByWordWrapping;
132 | label.backgroundColor = [UIColor clearColor];
133 | label.font = [UIFont fontWithName:@"AvenirNext-DemiBold" size:13.0f];
134 | label.textColor = [UIColor whiteColor];
135 | label.textAlignment = NSTextAlignmentCenter;
136 | [label sizeToFit];
137 | label.center = CGPointMake(screenRect.size.width / 2.0f, screenRect.size.height / 2.0f);
138 | weakSelf.errorLabel = label;
139 | [weakSelf.view addSubview:weakSelf.errorLabel];
140 | }
141 | }
142 | }];
143 |
144 |
145 | }
146 |
147 | /* camera button methods */
148 |
149 | - (void)switchButtonPressed:(UIButton *)button
150 | {
151 | [self.camera togglePosition];
152 | }
153 | -(void)backButtonPressed:(UIButton *)button{
154 | [self dismissViewControllerAnimated:YES completion:nil];
155 | }
156 | - (NSURL *)applicationDocumentsDirectory
157 | {
158 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
159 | }
160 |
161 | - (void)flashButtonPressed:(UIButton *)button
162 | {
163 | if(self.camera.flash == LLCameraFlashOff) {
164 | BOOL done = [self.camera updateFlashMode:LLCameraFlashOn];
165 | if(done) {
166 | self.flashButton.selected = YES;
167 | self.flashButton.tintColor = [UIColor yellowColor];
168 | }
169 | }
170 | else {
171 | BOOL done = [self.camera updateFlashMode:LLCameraFlashOff];
172 | if(done) {
173 | self.flashButton.selected = NO;
174 | self.flashButton.tintColor = [UIColor whiteColor];
175 | }
176 | }
177 | }
178 | #pragma mark -------------拍照--------------
179 |
180 | - (void)snapButtonPressed:(UIButton *)button
181 | {
182 | __weak typeof(self) weakSelf = self;
183 | // 去拍照
184 | [self.camera capture:^(LLSimpleCamera *camera, UIImage *image, NSDictionary *metadata, NSError *error) {
185 | NSLog(@"拍照结束");
186 | if(!error) {
187 | TOCropViewControllerAspectRatio aspectRatioStle = TOCropViewControllerAspectRatioOriginal;
188 | if (self.aspectRatioStle) {
189 | aspectRatioStle = self.aspectRatioStle;
190 | }
191 | TOCropViewController *cropController = [[TOCropViewController alloc] initWithImage:image aspectRatioStle:aspectRatioStle];
192 | cropController.delegate = self;
193 | [weakSelf presentViewController:cropController animated:YES completion:nil];
194 | }
195 | else {
196 | NSLog(@"An error has occured: %@", error);
197 | }
198 | } exactSeenImage:YES];
199 | }
200 |
201 | - (void)viewWillLayoutSubviews
202 | {
203 | [super viewWillLayoutSubviews];
204 | self.camera.view.frame=self.view.frame;
205 | self.snapButton.frame=CGRectMake((KScreenwidth-KIphoneSize_Widith(75))/2, KScreenheight-KIphoneSize_Widith(90), KIphoneSize_Widith(75), KIphoneSize_Widith(75));
206 | self.flashButton.frame=CGRectMake((KScreenwidth-KIphoneSize_Widith(36))/2, 25, KIphoneSize_Widith(36), KIphoneSize_Widith(44));
207 | self.switchButton.frame=CGRectMake(KScreenwidth-50, KScreenheight-KIphoneSize_Widith(75), KIphoneSize_Widith(45), KIphoneSize_Widith(45));
208 | self.backButton.frame=CGRectMake(5, KScreenheight-KIphoneSize_Widith(75), KIphoneSize_Widith(45), KIphoneSize_Widith(45));
209 | }
210 | - (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle{
211 | self.view.alpha = 0;
212 | self.fininshcapture(image);
213 | [self dismissViewControllerAnimated:NO completion:^{
214 | }];
215 | [self dismissViewControllerAnimated:NO completion:^{
216 | }];
217 | }
218 | - (BOOL)prefersStatusBarHidden
219 | {
220 | return YES;
221 | }
222 |
223 | - (void)didReceiveMemoryWarning
224 | {
225 | [super didReceiveMemoryWarning];
226 | }
227 |
228 |
229 | @end
230 |
--------------------------------------------------------------------------------
/PureCamera/PureCropVC.h:
--------------------------------------------------------------------------------
1 | //
2 | // PureCropVC.h
3 | // PureCamerademo
4 | //
5 | // Created by 五月 on 2018/4/4.
6 | // Copyright © 2018年 五月. All rights reserved.
7 | //
8 |
9 | #import "TOCropViewController.h"
10 |
11 | @interface PureCropVC : TOCropViewController
12 | //@property(nonatomic,assign) TOCropViewControllerAspectRatio AspectRatio;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/PureCamera/PureCropVC.m:
--------------------------------------------------------------------------------
1 | //
2 | // PureCropVC.m
3 | // PureCamerademo
4 | //
5 | // Created by 五月 on 2018/4/4.
6 | // Copyright © 2018年 五月. All rights reserved.
7 | //
8 |
9 | #import "PureCropVC.h"
10 |
11 | @interface PureCropVC ()
12 |
13 | @end
14 |
15 | @implementation PureCropVC
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view.
20 | }
21 |
22 | - (void)didReceiveMemoryWarning {
23 | [super didReceiveMemoryWarning];
24 | // Dispose of any resources that can be recreated.
25 | }
26 |
27 | /*
28 | #pragma mark - Navigation
29 |
30 | // In a storyboard-based application, you will often want to do a little preparation before navigation
31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
32 | // Get the new view controller using [segue destinationViewController].
33 | // Pass the selected object to the new view controller.
34 | }
35 | */
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/PureCamera/TOActivityCroppedImageProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOActivityCroppedImageProvider.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @interface TOActivityCroppedImageProvider : UIActivityItemProvider
26 |
27 | @property (nonatomic, readonly) UIImage *image;
28 | @property (nonatomic, readonly) CGRect cropFrame;
29 | @property (nonatomic, readonly) NSInteger angle;
30 |
31 | - (instancetype)initWithImage:(UIImage *)image cropFrame:(CGRect)cropFrame angle:(NSInteger)angle;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/PureCamera/TOActivityCroppedImageProvider.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOActivityCroppedImageProvider.m
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOActivityCroppedImageProvider.h"
24 | #import "UIImage+CropRotate.h"
25 |
26 | @interface TOActivityCroppedImageProvider ()
27 |
28 | @property (nonatomic, strong, readwrite) UIImage *image;
29 | @property (nonatomic, assign, readwrite) CGRect cropFrame;
30 | @property (nonatomic, assign, readwrite) NSInteger angle;
31 |
32 | @property (atomic, strong) UIImage *croppedImage;
33 |
34 | @end
35 |
36 | @implementation TOActivityCroppedImageProvider
37 |
38 | - (instancetype)initWithImage:(UIImage *)image cropFrame:(CGRect)cropFrame angle:(NSInteger)angle
39 | {
40 | if (self = [super initWithPlaceholderItem:[UIImage new]]) {
41 | _image = image;
42 | _cropFrame = cropFrame;
43 | _angle = angle;
44 | }
45 |
46 | return self;
47 | }
48 |
49 | #pragma mark - UIActivity Protocols -
50 | - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
51 | {
52 | return [[UIImage alloc] init];
53 | }
54 |
55 | - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
56 | {
57 | return self.croppedImage;
58 | }
59 |
60 | #pragma mark - Image Generation -
61 | - (id)item
62 | {
63 | //If the user didn't touch the image, just forward along the original
64 | if (self.angle == 0 && CGRectEqualToRect(self.cropFrame, (CGRect){CGPointZero, self.image.size})) {
65 | self.croppedImage = self.image;
66 | return self.croppedImage;
67 | }
68 |
69 | UIImage *image = [self.image croppedImageWithFrame:self.cropFrame angle:self.angle];
70 | self.croppedImage = image;
71 | return self.croppedImage;
72 | }
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/PureCamera/TOCropOverlayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropOverlayView.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @interface TOCropOverlayView : UIView
26 |
27 | @property (nonatomic, assign) BOOL gridHidden;
28 |
29 | /**
30 | Shows and hides the interior grid lines
31 | */
32 | - (void)setGridHidden:(BOOL)hidden animated:(BOOL)animated;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/PureCamera/TOCropOverlayView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropOverlayView.m
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCropOverlayView.h"
24 |
25 | static const CGFloat kTOCropOverLayerCornerWidth = 20.0f;
26 |
27 | @interface TOCropOverlayView ()
28 |
29 | @property (nonatomic, strong) NSArray *horizontalGridLines;
30 | @property (nonatomic, strong) NSArray *verticalGridLines;
31 |
32 | @property (nonatomic, strong) NSArray *outerLineViews; //top, right, bottom, left
33 |
34 | @property (nonatomic, strong) NSArray *topLeftLineViews; //vertical, horizontal
35 | @property (nonatomic, strong) NSArray *bottomLeftLineViews;
36 | @property (nonatomic, strong) NSArray *bottomRightLineViews;
37 | @property (nonatomic, strong) NSArray *topRightLineViews;
38 |
39 | - (void)setup;
40 | - (void)layoutLines;
41 |
42 | @end
43 |
44 | @implementation TOCropOverlayView
45 |
46 | - (instancetype)initWithFrame:(CGRect)frame
47 | {
48 | if (self = [super initWithFrame:frame]) {
49 | self.clipsToBounds = NO;
50 | [self setup];
51 | }
52 |
53 | return self;
54 | }
55 |
56 | - (void)setup
57 | {
58 | UIView *(^newLineView)(void) = ^UIView *(void){
59 | UIView *newLine = [[UIView alloc] initWithFrame:CGRectZero];
60 | newLine.backgroundColor = [UIColor whiteColor];
61 | [self addSubview:newLine];
62 | return newLine;
63 | };
64 |
65 | _outerLineViews = @[newLineView(), newLineView(), newLineView(), newLineView()];
66 |
67 | _topLeftLineViews = @[newLineView(), newLineView()];
68 | _bottomLeftLineViews = @[newLineView(), newLineView()];
69 | _topRightLineViews = @[newLineView(), newLineView()];
70 | _bottomRightLineViews = @[newLineView(), newLineView()];
71 |
72 | _horizontalGridLines = @[newLineView(), newLineView()];
73 | _verticalGridLines = @[newLineView(), newLineView()];
74 | }
75 |
76 | - (void)setFrame:(CGRect)frame
77 | {
78 | [super setFrame:frame];
79 |
80 | if (_outerLineViews)
81 | [self layoutLines];
82 | }
83 |
84 | - (void)didMoveToSuperview
85 | {
86 | [super didMoveToSuperview];
87 |
88 | if (_outerLineViews)
89 | [self layoutLines];
90 | }
91 |
92 | - (void)layoutLines
93 | {
94 | CGSize boundsSize = self.bounds.size;
95 |
96 | //border lines
97 | for (NSInteger i = 0; i < 4; i++) {
98 | UIView *lineView = self.outerLineViews[i];
99 |
100 | CGRect frame = CGRectZero;
101 | switch (i) {
102 | case 0: frame = (CGRect){0,-1.0f,boundsSize.width+2.0f, 1.0f}; break; //top
103 | case 1: frame = (CGRect){boundsSize.width,0.0f,1.0f,boundsSize.height}; break; //right
104 | case 2: frame = (CGRect){-1.0f,boundsSize.height,boundsSize.width+2.0f,1.0f}; break; //bottom
105 | case 3: frame = (CGRect){-1.0f,0,1.0f,boundsSize.height+1.0f}; break; //left
106 | }
107 |
108 | lineView.frame = frame;
109 | }
110 |
111 | //corner liness
112 | NSArray *cornerLines = @[self.topLeftLineViews, self.topRightLineViews, self.bottomRightLineViews, self.bottomLeftLineViews];
113 | for (NSInteger i = 0; i < 4; i++) {
114 | NSArray *cornerLine = cornerLines[i];
115 |
116 | CGRect verticalFrame, horizontalFrame;
117 | switch (i) {
118 | case 0: //top left
119 | verticalFrame = (CGRect){-3.0f,-3.0f,3.0f,kTOCropOverLayerCornerWidth+3.0f};
120 | horizontalFrame = (CGRect){0,-3.0f,kTOCropOverLayerCornerWidth,3.0f};
121 | break;
122 | case 1: //top right
123 | verticalFrame = (CGRect){boundsSize.width,-3.0f,3.0f,kTOCropOverLayerCornerWidth+3.0f};
124 | horizontalFrame = (CGRect){boundsSize.width-kTOCropOverLayerCornerWidth,-3.0f,kTOCropOverLayerCornerWidth,3.0f};
125 | break;
126 | case 2: //bottom right
127 | verticalFrame = (CGRect){boundsSize.width,boundsSize.height-kTOCropOverLayerCornerWidth,3.0f,kTOCropOverLayerCornerWidth+3.0f};
128 | horizontalFrame = (CGRect){boundsSize.width-kTOCropOverLayerCornerWidth,boundsSize.height,kTOCropOverLayerCornerWidth,3.0f};
129 | break;
130 | case 3: //bottom left
131 | verticalFrame = (CGRect){-3.0f,boundsSize.height-kTOCropOverLayerCornerWidth,3.0f,kTOCropOverLayerCornerWidth};
132 | horizontalFrame = (CGRect){-3.0f,boundsSize.height,kTOCropOverLayerCornerWidth+3.0f,3.0f};
133 | break;
134 | }
135 |
136 | [cornerLine[0] setFrame:verticalFrame];
137 | [cornerLine[1] setFrame:horizontalFrame];
138 | }
139 |
140 | //grid lines - horizontal
141 | CGFloat thickness = 1.0f / [[UIScreen mainScreen] scale];
142 | NSInteger numberOfLines = self.horizontalGridLines.count;
143 | CGFloat padding = (CGRectGetHeight(self.bounds) - (thickness*numberOfLines)) / (numberOfLines + 1);
144 | for (NSInteger i = 0; i < numberOfLines; i++) {
145 | UIView *lineView = self.horizontalGridLines[i];
146 | CGRect frame = CGRectZero;
147 | frame.size.height = thickness;
148 | frame.size.width = CGRectGetWidth(self.bounds);
149 | frame.origin.y = (padding * (i+1)) + (thickness * i);
150 | lineView.frame = frame;
151 | }
152 |
153 | //grid lines - vertical
154 | numberOfLines = self.verticalGridLines.count;
155 | padding = (CGRectGetWidth(self.bounds) - (thickness*numberOfLines)) / (numberOfLines + 1);
156 | for (NSInteger i = 0; i < numberOfLines; i++) {
157 | UIView *lineView = self.verticalGridLines[i];
158 | CGRect frame = CGRectZero;
159 | frame.size.width = thickness;
160 | frame.size.height = CGRectGetHeight(self.bounds);
161 | frame.origin.x = (padding * (i+1)) + (thickness * i);
162 | lineView.frame = frame;
163 | }
164 | }
165 |
166 | - (void)setGridHidden:(BOOL)hidden animated:(BOOL)animated
167 | {
168 | _gridHidden = hidden;
169 |
170 | if (animated == NO) {
171 | for (UIView *lineView in self.horizontalGridLines) {
172 | lineView.alpha = hidden ? 0.0f : 1.0f;
173 | }
174 |
175 | for (UIView *lineView in self.verticalGridLines) {
176 | lineView.alpha = hidden ? 0.0f : 1.0f;
177 | }
178 |
179 | return;
180 | }
181 |
182 | [UIView animateWithDuration:hidden?0.35f:0.2f animations:^{
183 | for (UIView *lineView in self.horizontalGridLines)
184 | lineView.alpha = hidden ? 0.0f : 1.0f;
185 |
186 | for (UIView *lineView in self.verticalGridLines)
187 | lineView.alpha = hidden ? 0.0f : 1.0f;
188 | }];
189 | }
190 |
191 | - (void)setGridHidden:(BOOL)gridHidden
192 | {
193 | [self setGridHidden:gridHidden animated:NO];
194 | }
195 |
196 | @end
197 |
--------------------------------------------------------------------------------
/PureCamera/TOCropScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropScrollView
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @interface TOCropScrollView : UIScrollView
26 |
27 | @property (nonatomic, copy) void (^touchesBegan)(void);
28 | @property (nonatomic, copy) void (^touchesCancelled)(void);
29 | @property (nonatomic, copy) void (^touchesEnded)(void);
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/PureCamera/TOCropScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropScrollView
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCropScrollView.h"
24 |
25 | @implementation TOCropScrollView
26 |
27 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
28 | {
29 | if (self.touchesBegan)
30 | self.touchesBegan();
31 |
32 | [super touchesBegan:touches withEvent:event];
33 | }
34 |
35 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
36 | {
37 | if (self.touchesEnded)
38 | self.touchesEnded();
39 |
40 | [super touchesEnded:touches withEvent:event];
41 | }
42 |
43 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
44 | {
45 | if (self.touchesCancelled)
46 | self.touchesCancelled();
47 |
48 | [super touchesCancelled:touches withEvent:event];
49 | }
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/PureCamera/TOCropToolbar.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropToolbar.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @interface TOCropToolbar : UIView
26 |
27 | /* Button feedback handler blocks */
28 | @property (nonatomic, copy) void (^cancelButtonTapped)(void);
29 | @property (nonatomic, copy) void (^doneButtonTapped)(void);
30 | @property (nonatomic, copy) void (^rotateButtonTapped)(void);
31 | @property (nonatomic, copy) void (^clampButtonTapped)(void);
32 | @property (nonatomic, copy) void (^resetButtonTapped)(void);
33 |
34 | /* Aspect ratio button settings */
35 | @property (nonatomic, assign) BOOL clampButtonGlowing;
36 | @property (nonatomic, readonly) CGRect clampButtonFrame;
37 |
38 | /* Disable the rotate button */
39 | @property (nonatomic, assign) BOOL rotateButtonHidden;
40 |
41 | /* Enable the reset button */
42 | @property (nonatomic, assign) BOOL resetButtonEnabled;
43 |
44 | /* Done button frame for popover controllers */
45 | @property (nonatomic, readonly) CGRect doneButtonFrame;
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/PureCamera/TOCropToolbar.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropToolbar.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCropToolbar.h"
24 |
25 | @interface TOCropToolbar()
26 |
27 | @property (nonatomic, strong) UIButton *doneTextButton;
28 | @property (nonatomic, strong) UIButton *doneIconButton;
29 |
30 | @property (nonatomic, strong) UIButton *cancelTextButton;
31 | @property (nonatomic, strong) UIButton *cancelIconButton;
32 |
33 | @property (nonatomic, strong) UIButton *rotateButton;
34 | @property (nonatomic, strong) UIButton *resetButton;
35 | @property (nonatomic, strong) UIButton *clampButton;
36 |
37 | - (void)setup;
38 | - (void)buttonTapped:(id)button;
39 |
40 | + (UIImage *)doneImage;
41 | + (UIImage *)cancelImage;
42 | + (UIImage *)resetImage;
43 | + (UIImage *)rotateImage;
44 | + (UIImage *)clampImage;
45 |
46 | @end
47 |
48 | @implementation TOCropToolbar
49 |
50 | - (instancetype)initWithFrame:(CGRect)frame
51 | {
52 | if (self = [super initWithFrame:frame]) {
53 | [self setup];
54 | }
55 |
56 | return self;
57 | }
58 |
59 | - (void)setup {
60 | self.backgroundColor = [UIColor colorWithWhite:0.12f alpha:1.0f];
61 |
62 | _doneTextButton = [UIButton buttonWithType:UIButtonTypeSystem];
63 | _doneTextButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
64 | [_doneTextButton setTitle:NSLocalizedStringFromTableInBundle(@"完成",
65 | @"TOCropViewControllerLocalizable",[NSBundle bundleForClass:[self class]],
66 | nil)forState:UIControlStateNormal];
67 | [_doneTextButton setTitleColor:[UIColor colorWithRed:1.0f green:0.8f blue:0.0f alpha:1.0f] forState:UIControlStateNormal];
68 | [_doneTextButton.titleLabel setFont:[UIFont systemFontOfSize:17.0f]];
69 | [_doneTextButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
70 | [self addSubview:_doneTextButton];
71 |
72 | _doneIconButton = [UIButton buttonWithType:UIButtonTypeSystem];
73 | [_doneIconButton setImage:[TOCropToolbar doneImage] forState:UIControlStateNormal];
74 | [_doneIconButton setTintColor:[UIColor colorWithRed:1.0f green:0.8f blue:0.0f alpha:1.0f]];
75 | [_doneIconButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
76 | [self addSubview:_doneIconButton];
77 |
78 | _cancelTextButton = [UIButton buttonWithType:UIButtonTypeSystem];
79 | _cancelTextButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
80 | [_cancelTextButton setTitle:NSLocalizedStringFromTableInBundle(@"取消",
81 | @"TOCropViewControllerLocalizable",
82 | [NSBundle bundleForClass:[self class]],
83 | nil)
84 | forState:UIControlStateNormal];
85 | [_cancelTextButton.titleLabel setFont:[UIFont systemFontOfSize:17.0f]];
86 | [_cancelTextButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
87 | [self addSubview:_cancelTextButton];
88 |
89 | _cancelIconButton = [UIButton buttonWithType:UIButtonTypeSystem];
90 | [_cancelIconButton setImage:[TOCropToolbar cancelImage] forState:UIControlStateNormal];
91 | [_cancelIconButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
92 | [self addSubview:_cancelIconButton];
93 |
94 | _clampButton = [UIButton buttonWithType:UIButtonTypeSystem];
95 | _clampButton.contentMode = UIViewContentModeCenter;
96 | _clampButton.tintColor = [UIColor whiteColor];
97 | [_clampButton setImage:[TOCropToolbar clampImage] forState:UIControlStateNormal];
98 | [_clampButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
99 | [self addSubview:_clampButton];
100 |
101 | _rotateButton = [UIButton buttonWithType:UIButtonTypeSystem];
102 | _rotateButton.contentMode = UIViewContentModeCenter;
103 | _rotateButton.tintColor = [UIColor whiteColor];
104 | [_rotateButton setImage:[TOCropToolbar rotateImage] forState:UIControlStateNormal];
105 | [_rotateButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
106 | [self addSubview:_rotateButton];
107 |
108 | _resetButton = [UIButton buttonWithType:UIButtonTypeSystem];
109 | _resetButton.contentMode = UIViewContentModeCenter;
110 | _resetButton.tintColor = [UIColor whiteColor];
111 | _resetButton.enabled = NO;
112 | [_resetButton setImage:[TOCropToolbar resetImage] forState:UIControlStateNormal];
113 | [_resetButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
114 | [self addSubview:_resetButton];
115 | }
116 |
117 | - (void)layoutSubviews
118 | {
119 | [super layoutSubviews];
120 |
121 | BOOL verticalLayout = (CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds));
122 | CGSize boundsSize = self.bounds.size;
123 |
124 | self.cancelIconButton.hidden = (!verticalLayout);
125 | self.cancelTextButton.hidden = (verticalLayout);
126 | self.doneIconButton.hidden = (!verticalLayout);
127 | self.doneTextButton.hidden = (verticalLayout);
128 |
129 | self.rotateButton.hidden = self.rotateButtonHidden;
130 |
131 | if (verticalLayout == NO) {
132 | CGRect frame = CGRectZero;
133 | frame.size.height = 44.0f;
134 | frame.size.width = [self.cancelTextButton.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:self.cancelTextButton.titleLabel.font}].width + 10;
135 | self.cancelTextButton.frame = frame;
136 |
137 | frame.size.width = [self.doneTextButton.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:self.doneTextButton.titleLabel.font}].width + 10;
138 | frame.origin.x = boundsSize.width - CGRectGetWidth(frame);
139 | self.doneTextButton.frame = frame;
140 |
141 | CGRect containerRect = (CGRect){0,0,165.0f,44.0f};
142 | containerRect.origin.x = (CGRectGetWidth(self.bounds) - (CGRectGetWidth(containerRect))) * 0.5f;
143 |
144 | CGRect buttonFrame = (CGRect){0,0,44.0f,44.0f};
145 |
146 | if (self.rotateButtonHidden) {
147 | buttonFrame.origin.x = CGRectGetMinX(containerRect);
148 | self.resetButton.frame = buttonFrame;
149 | }
150 | else {
151 | buttonFrame.origin.x = CGRectGetMinX(containerRect);
152 | self.rotateButton.frame = buttonFrame;
153 |
154 | buttonFrame.origin.x = CGRectGetMidX(containerRect) - 22.0f;
155 | self.resetButton.frame = buttonFrame;
156 | }
157 |
158 | buttonFrame.origin.x = CGRectGetMaxX(containerRect) - 44.0f;
159 | self.clampButton.frame = buttonFrame;
160 | }
161 | else {
162 | CGRect frame = CGRectZero;
163 | frame.size.height = 44.0f;
164 | frame.size.width = 44.0f;
165 | frame.origin.y = CGRectGetHeight(self.bounds) - 44.0f;
166 | self.cancelIconButton.frame = frame;
167 |
168 | frame.origin.y = 0.0f;
169 | frame.size.width = 44.0f;
170 | frame.size.height = 44.0f;
171 | self.doneIconButton.frame = frame;
172 |
173 | CGRect containerRect = (CGRect){0,0,44.0f,165.0f};
174 | containerRect.origin.y = (CGRectGetHeight(self.bounds) - (CGRectGetHeight(containerRect))) * 0.5f;
175 |
176 | CGRect buttonFrame = (CGRect){0,0,44.0f,44.0f};
177 |
178 | if (self.rotateButtonHidden) {
179 | buttonFrame.origin.y = CGRectGetMinY(containerRect);
180 | self.resetButton.frame = buttonFrame;
181 | }
182 | else {
183 | buttonFrame.origin.y = CGRectGetMinY(containerRect);
184 | self.rotateButton.frame = buttonFrame;
185 |
186 | buttonFrame.origin.y = CGRectGetMidY(containerRect) - 22.0f;
187 | self.resetButton.frame = buttonFrame;
188 | }
189 |
190 | buttonFrame.origin.y = CGRectGetMaxY(containerRect) - 44.0f;
191 | self.clampButton.frame = buttonFrame;
192 | }
193 | }
194 |
195 | - (void)buttonTapped:(id)button
196 | {
197 | if (button == self.cancelTextButton || button == self.cancelIconButton) {
198 | if (self.cancelButtonTapped)
199 | self.cancelButtonTapped();
200 | }
201 | else if (button == self.doneTextButton || button == self.doneIconButton) {
202 | if (self.doneButtonTapped)
203 | self.doneButtonTapped();
204 | }
205 | else if (button == self.resetButton && self.resetButtonTapped) {
206 | self.resetButtonTapped();
207 | }
208 | else if (button == self.rotateButton && self.rotateButtonTapped) {
209 | self.rotateButtonTapped();
210 | }
211 | else if (button == self.clampButton && self.clampButtonTapped) {
212 | self.clampButtonTapped();
213 | return;
214 | }
215 | }
216 |
217 | - (CGRect)clampButtonFrame
218 | {
219 | return self.clampButton.frame;
220 | }
221 |
222 | - (void)setClampButtonGlowing:(BOOL)clampButtonGlowing
223 | {
224 | if (_clampButtonGlowing == clampButtonGlowing)
225 | return;
226 |
227 | _clampButtonGlowing = clampButtonGlowing;
228 |
229 | if (_clampButtonGlowing)
230 | self.clampButton.tintColor = nil;
231 | else
232 | self.clampButton.tintColor = [UIColor whiteColor];
233 | }
234 |
235 | - (void)setRotateButtonHidden:(BOOL)rotateButtonHidden
236 | {
237 | if (_rotateButtonHidden == rotateButtonHidden)
238 | return;
239 |
240 | _rotateButtonHidden = rotateButtonHidden;
241 | [self setNeedsLayout];
242 | }
243 |
244 | - (BOOL)resetButtonEnabled
245 | {
246 | return self.resetButton.enabled;
247 | }
248 |
249 | - (void)setResetButtonEnabled:(BOOL)resetButtonEnabled
250 | {
251 | self.resetButton.enabled = resetButtonEnabled;
252 | }
253 |
254 | - (CGRect)doneButtonFrame
255 | {
256 | if (self.doneIconButton.hidden == NO)
257 | return self.doneIconButton.frame;
258 |
259 | return self.doneTextButton.frame;
260 | }
261 |
262 | #pragma mark - Image Generation -
263 | + (UIImage *)doneImage
264 | {
265 | UIImage *doneImage = nil;
266 |
267 | UIGraphicsBeginImageContextWithOptions((CGSize){17,14}, NO, 0.0f);
268 | {
269 | //// Rectangle Drawing
270 | UIBezierPath* rectanglePath = UIBezierPath.bezierPath;
271 | [rectanglePath moveToPoint: CGPointMake(1, 7)];
272 | [rectanglePath addLineToPoint: CGPointMake(6, 12)];
273 | [rectanglePath addLineToPoint: CGPointMake(16, 1)];
274 | [UIColor.whiteColor setStroke];
275 | rectanglePath.lineWidth = 2;
276 | [rectanglePath stroke];
277 |
278 |
279 | doneImage = UIGraphicsGetImageFromCurrentImageContext();
280 | }
281 | UIGraphicsEndImageContext();
282 |
283 | return doneImage;
284 | }
285 |
286 | + (UIImage *)cancelImage
287 | {
288 | UIImage *cancelImage = nil;
289 |
290 | UIGraphicsBeginImageContextWithOptions((CGSize){16,16}, NO, 0.0f);
291 | {
292 | UIBezierPath* bezierPath = UIBezierPath.bezierPath;
293 | [bezierPath moveToPoint: CGPointMake(15, 15)];
294 | [bezierPath addLineToPoint: CGPointMake(1, 1)];
295 | [UIColor.whiteColor setStroke];
296 | bezierPath.lineWidth = 2;
297 | [bezierPath stroke];
298 |
299 |
300 | //// Bezier 2 Drawing
301 | UIBezierPath* bezier2Path = UIBezierPath.bezierPath;
302 | [bezier2Path moveToPoint: CGPointMake(1, 15)];
303 | [bezier2Path addLineToPoint: CGPointMake(15, 1)];
304 | [UIColor.whiteColor setStroke];
305 | bezier2Path.lineWidth = 2;
306 | [bezier2Path stroke];
307 |
308 | cancelImage = UIGraphicsGetImageFromCurrentImageContext();
309 | }
310 | UIGraphicsEndImageContext();
311 |
312 | return cancelImage;
313 | }
314 |
315 | + (UIImage *)rotateImage
316 | {
317 | UIImage *rotateImage = nil;
318 |
319 | UIGraphicsBeginImageContextWithOptions((CGSize){18,21}, NO, 0.0f);
320 | {
321 | //// Rectangle 2 Drawing
322 | UIBezierPath* rectangle2Path = [UIBezierPath bezierPathWithRect: CGRectMake(0, 9, 12, 12)];
323 | [UIColor.whiteColor setFill];
324 | [rectangle2Path fill];
325 |
326 |
327 | //// Rectangle 3 Drawing
328 | UIBezierPath* rectangle3Path = UIBezierPath.bezierPath;
329 | [rectangle3Path moveToPoint: CGPointMake(5, 3)];
330 | [rectangle3Path addLineToPoint: CGPointMake(10, 6)];
331 | [rectangle3Path addLineToPoint: CGPointMake(10, 0)];
332 | [rectangle3Path addLineToPoint: CGPointMake(5, 3)];
333 | [rectangle3Path closePath];
334 | [UIColor.whiteColor setFill];
335 | [rectangle3Path fill];
336 |
337 |
338 | //// Bezier Drawing
339 | UIBezierPath* bezierPath = UIBezierPath.bezierPath;
340 | [bezierPath moveToPoint: CGPointMake(10, 3)];
341 | [bezierPath addCurveToPoint: CGPointMake(17.5, 11) controlPoint1: CGPointMake(15, 3) controlPoint2: CGPointMake(17.5, 5.91)];
342 | [UIColor.whiteColor setStroke];
343 | bezierPath.lineWidth = 1;
344 | [bezierPath stroke];
345 | rotateImage = UIGraphicsGetImageFromCurrentImageContext();
346 | }
347 | UIGraphicsEndImageContext();
348 |
349 | return rotateImage;
350 | }
351 |
352 | + (UIImage *)resetImage
353 | {
354 | UIImage *resetImage = nil;
355 |
356 | UIGraphicsBeginImageContextWithOptions((CGSize){22,18}, NO, 0.0f);
357 | {
358 |
359 | //// Bezier 2 Drawing
360 | UIBezierPath* bezier2Path = UIBezierPath.bezierPath;
361 | [bezier2Path moveToPoint: CGPointMake(22, 9)];
362 | [bezier2Path addCurveToPoint: CGPointMake(13, 18) controlPoint1: CGPointMake(22, 13.97) controlPoint2: CGPointMake(17.97, 18)];
363 | [bezier2Path addCurveToPoint: CGPointMake(13, 16) controlPoint1: CGPointMake(13, 17.35) controlPoint2: CGPointMake(13, 16.68)];
364 | [bezier2Path addCurveToPoint: CGPointMake(20, 9) controlPoint1: CGPointMake(16.87, 16) controlPoint2: CGPointMake(20, 12.87)];
365 | [bezier2Path addCurveToPoint: CGPointMake(13, 2) controlPoint1: CGPointMake(20, 5.13) controlPoint2: CGPointMake(16.87, 2)];
366 | [bezier2Path addCurveToPoint: CGPointMake(6.55, 6.27) controlPoint1: CGPointMake(10.1, 2) controlPoint2: CGPointMake(7.62, 3.76)];
367 | [bezier2Path addCurveToPoint: CGPointMake(6, 9) controlPoint1: CGPointMake(6.2, 7.11) controlPoint2: CGPointMake(6, 8.03)];
368 | [bezier2Path addLineToPoint: CGPointMake(4, 9)];
369 | [bezier2Path addCurveToPoint: CGPointMake(4.65, 5.63) controlPoint1: CGPointMake(4, 7.81) controlPoint2: CGPointMake(4.23, 6.67)];
370 | [bezier2Path addCurveToPoint: CGPointMake(7.65, 1.76) controlPoint1: CGPointMake(5.28, 4.08) controlPoint2: CGPointMake(6.32, 2.74)];
371 | [bezier2Path addCurveToPoint: CGPointMake(13, 0) controlPoint1: CGPointMake(9.15, 0.65) controlPoint2: CGPointMake(11, 0)];
372 | [bezier2Path addCurveToPoint: CGPointMake(22, 9) controlPoint1: CGPointMake(17.97, 0) controlPoint2: CGPointMake(22, 4.03)];
373 | [bezier2Path closePath];
374 | [UIColor.whiteColor setFill];
375 | [bezier2Path fill];
376 |
377 |
378 | //// Polygon Drawing
379 | UIBezierPath* polygonPath = UIBezierPath.bezierPath;
380 | [polygonPath moveToPoint: CGPointMake(5, 15)];
381 | [polygonPath addLineToPoint: CGPointMake(10, 9)];
382 | [polygonPath addLineToPoint: CGPointMake(0, 9)];
383 | [polygonPath addLineToPoint: CGPointMake(5, 15)];
384 | [polygonPath closePath];
385 | [UIColor.whiteColor setFill];
386 | [polygonPath fill];
387 |
388 |
389 | resetImage = UIGraphicsGetImageFromCurrentImageContext();
390 | }
391 |
392 | return resetImage;
393 | }
394 |
395 | + (UIImage *)clampImage
396 | {
397 | UIImage *clampImage = nil;
398 |
399 | UIGraphicsBeginImageContextWithOptions((CGSize){22,16}, NO, 0.0f);
400 | {
401 | //// Color Declarations
402 | UIColor* outerBox = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 0.553];
403 | UIColor* innerBox = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 0.773];
404 |
405 | //// Rectangle Drawing
406 | UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 3, 13, 13)];
407 | [UIColor.whiteColor setFill];
408 | [rectanglePath fill];
409 |
410 |
411 | //// Outer
412 | {
413 | //// Top Drawing
414 | UIBezierPath* topPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0, 22, 2)];
415 | [outerBox setFill];
416 | [topPath fill];
417 |
418 |
419 | //// Side Drawing
420 | UIBezierPath* sidePath = [UIBezierPath bezierPathWithRect: CGRectMake(19, 2, 3, 14)];
421 | [outerBox setFill];
422 | [sidePath fill];
423 | }
424 |
425 |
426 | //// Rectangle 2 Drawing
427 | UIBezierPath* rectangle2Path = [UIBezierPath bezierPathWithRect: CGRectMake(14, 3, 4, 13)];
428 | [innerBox setFill];
429 | [rectangle2Path fill];
430 |
431 |
432 | clampImage = UIGraphicsGetImageFromCurrentImageContext();
433 | }
434 | UIGraphicsEndImageContext();
435 |
436 | return clampImage;
437 | }
438 |
439 | @end
440 |
--------------------------------------------------------------------------------
/PureCamera/TOCropView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropView.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @class TOCropView;
26 |
27 | @protocol TOCropViewDelegate
28 |
29 | - (void)cropViewDidBecomeResettable:(TOCropView *)cropView;
30 | - (void)cropViewDidBecomeNonResettable:(TOCropView *)cropView;
31 |
32 | @end
33 |
34 | @interface TOCropView : UIView
35 |
36 | /**
37 | The image that the crop view is displaying. This cannot be changed once the crop view is instantiated.
38 | */
39 | @property (nonatomic, strong, readonly) UIImage *image;
40 |
41 | /**
42 | A delegate object that receives notifications from the crop view
43 | */
44 | @property (nonatomic, weak) id delegate;
45 |
46 | /**
47 | Whether the user has manipulated the crop view to the point where it can be reset
48 | */
49 | @property (nonatomic, readonly) BOOL canReset;
50 |
51 | /**
52 | The frame of the cropping box on the crop view
53 | */
54 | @property (nonatomic, readonly) CGRect cropBoxFrame;
55 |
56 | /**
57 | The frame of the entire image in the backing scroll view
58 | */
59 | @property (nonatomic, readonly) CGRect imageViewFrame;
60 |
61 | /**
62 | Inset the workable region of the crop view in case in order to make space for accessory views
63 | */
64 | @property (nonatomic, assign) UIEdgeInsets cropRegionInsets;
65 |
66 | /**
67 | Disable the dynamic translucency in order to smoothly relayout the view
68 | */
69 | @property (nonatomic, assign) BOOL simpleMode;
70 |
71 | /**
72 | When the cropping box is locked to its current size
73 | */
74 | @property (nonatomic, assign) BOOL aspectLockEnabled;
75 |
76 | /**
77 | True when the height of the crop box is bigger than the width
78 | */
79 | @property (nonatomic, readonly) BOOL cropBoxAspectRatioIsPortrait;
80 |
81 | /**
82 | The rotation angle of the crop view (Will always be negative as it rotates in a counter-clockwise direction)
83 | */
84 | @property (nonatomic, assign, readonly) NSInteger angle;
85 |
86 | /**
87 | Hide all of the crop elements for transition animations
88 | */
89 | @property (nonatomic, assign) BOOL croppingViewsHidden;
90 |
91 | /**
92 | In relation to the coordinate space of the image, the frame that the crop view is focussing on
93 | */
94 | @property (nonatomic, readonly) CGRect croppedImageFrame;
95 |
96 | /**
97 | Set the grid overlay graphic to be hidden
98 | */
99 | @property (nonatomic, assign) BOOL gridOverlayHidden;
100 |
101 | /**
102 | Create a new instance of the crop view with the supplied image
103 | */
104 | - (instancetype)initWithImage:(UIImage *)image;
105 |
106 | /**
107 | When performing large size transitions (eg, orientation rotation),
108 | set simple mode to YES to temporarily graphically heavy effects like translucency.
109 |
110 | @param simpleMode Whether simple mode is enabled or not
111 |
112 | */
113 | - (void)setSimpleMode:(BOOL)simpleMode animated:(BOOL)animated;
114 |
115 | /**
116 | When performing a screen rotation that will change the size of the scroll view, this takes
117 | a snapshot of all of the scroll view data before it gets manipulated by iOS.
118 | Please call this in your view controller, before the rotation animation block is committed.
119 | */
120 | - (void)prepareforRotation;
121 |
122 | /**
123 | Performs the realignment of the crop view while the screen is rotating.
124 | Please call this inside your view controller's screen rotation animation block.
125 | */
126 | - (void)performRelayoutForRotation;
127 |
128 | /**
129 | Reset the crop box and zoom scale back to the initial layout
130 |
131 | @param animated The reset is animated
132 | */
133 | - (void)resetLayoutToDefaultAnimated:(BOOL)animated;
134 |
135 | /**
136 | Enables an aspect ratio lock where the crop box will always scale at a specific ratio.
137 |
138 | @param aspectRatio The aspect ratio (For example 16:9 is 16.0f/9.0f). Specify 0.0f to lock to the image's original aspect ratio
139 | @param animated Whether the locking effect is animated
140 | */
141 | - (void)setAspectLockEnabledWithAspectRatio:(CGSize)aspectRatio animated:(BOOL)animated;
142 |
143 | /**
144 | Rotates the entire canvas to a 90-degree angle
145 |
146 | @param angle The angle in which to rotate (May be 0, 90, 180, 270)
147 | @param animated Whether the transition is animated
148 | */
149 | - (void)rotateImageNinetyDegreesAnimated:(BOOL)animated;
150 |
151 | /**
152 | Animate the grid overlay graphic to be visible
153 | */
154 | - (void)setGridOverlayHidden:(BOOL)gridOverlayHidden animated:(BOOL)animated;
155 |
156 | /**
157 | Animate the cropping component views to become visible
158 | */
159 | - (void)setCroppingViewsHidden:(BOOL)hidden animated:(BOOL)animated;
160 |
161 |
162 | @end
163 |
--------------------------------------------------------------------------------
/PureCamera/TOCropViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropViewController.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 | @class TOCropViewController;
25 |
26 |
27 | ///------------------------------------------------
28 | /// @name Delegate
29 | ///------------------------------------------------
30 |
31 | @protocol TOCropViewControllerDelegate
32 | @optional
33 |
34 | /**
35 | Called when the user has committed the crop action, and provides just the cropping rectangle
36 |
37 | @param image The newly cropped image.
38 | @param cropRect A rectangle indicating the crop region of the image the user chose (In the original image's local co-ordinate space)
39 | */
40 | - (void)cropViewController:(TOCropViewController *)cropViewController didCropImageToRect:(CGRect)cropRect angle:(NSInteger)angle;
41 |
42 | /**
43 | Called when the user has committed the crop action, and provides both the original image with crop co-ordinates.
44 |
45 | @param image The newly cropped image.
46 | @param cropRect A rectangle indicating the crop region of the image the user chose (In the original image's local co-ordinate space)
47 | */
48 | - (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle;
49 |
50 | /**
51 | If implemented, when the user hits cancel, or completes a UIActivityViewController operation, this delegate will be called,
52 | giving you a chance to manually dismiss the view controller
53 |
54 | */
55 | - (void)cropViewController:(TOCropViewController *)cropViewController didFinishCancelled:(BOOL)cancelled;
56 |
57 | @end
58 |
59 |
60 | typedef enum : NSInteger {
61 | TOCropViewControllerAspectRatioOriginal = 0,
62 | TOCropViewControllerAspectRatioSquare,
63 | TOCropViewControllerAspectRatio1x2,
64 | TOCropViewControllerAspectRatio3x2,
65 | TOCropViewControllerAspectRatio5x3,
66 | TOCropViewControllerAspectRatio4x3,
67 | TOCropViewControllerAspectRatio5x4,
68 | TOCropViewControllerAspectRatio7x5,
69 | TOCropViewControllerAspectRatio16x9,
70 | } TOCropViewControllerAspectRatio;
71 |
72 |
73 |
74 | @interface TOCropViewController : UIViewController
75 |
76 | //typedef enum(NSInteger, TOCropViewControllerAspectRatio) {
77 | // TOCropViewControllerAspectRatioOriginal,
78 | // TOCropViewControllerAspectRatioSquare,
79 | // TOCropViewControllerAspectRatio1x2,
80 | // TOCropViewControllerAspectRatio3x2,
81 | // TOCropViewControllerAspectRatio5x3,
82 | // TOCropViewControllerAspectRatio4x3,
83 | // TOCropViewControllerAspectRatio5x4,
84 | // TOCropViewControllerAspectRatio7x5,
85 | // TOCropViewControllerAspectRatio16x9
86 | //};
87 |
88 |
89 | /**
90 | The original, uncropped image that was passed to this controller.
91 | */
92 | @property (nonatomic, readonly) UIImage *image;
93 |
94 | /**
95 | The view controller's delegate that will return the resulting cropped image, as well as crop information
96 | */
97 | @property (nonatomic, weak) id delegate;
98 |
99 | /**
100 | If true, when the user hits 'Done', a UIActivityController will appear before the view controller ends
101 | */
102 | @property (nonatomic, assign) BOOL showActivitySheetOnDone;
103 |
104 | /**
105 | If performing a transition animation, this block can be used to set up any view states just before the animation begins
106 | */
107 | @property (nonatomic, copy) void (^prepareForTransitionHandler)(void);
108 |
109 | /**
110 | If `showActivitySheetOnDone` is true, then these activity items will be supplied to that UIActivityViewController
111 | in addition to the `TOActivityCroppedImageProvider` object.
112 | */
113 | @property (nonatomic, strong) NSArray *activityItems;
114 |
115 | /**
116 | If `showActivitySheetOnDone` is true, then you may specify any custom activities your app implements in this array.
117 | If your activity requires access to the cropping information, it can be accessed in the supplied `TOActivityCroppedImageProvider` object
118 | */
119 | @property (nonatomic, strong) NSArray *applicationActivities;
120 |
121 | /**
122 | If `showActivitySheetOnDone` is true, then you may expliclty set activities that won't appear in the share sheet here.
123 | */
124 | @property (nonatomic, strong) NSArray *excludedActivityTypes;
125 |
126 | ///------------------------------------------------
127 | /// @name Object Creation
128 | ///------------------------------------------------
129 |
130 | /**
131 | Creates a new instance of a crop view controller with the supplied image
132 |
133 | @param image The image that will be used to crop.
134 | */
135 | - (instancetype)initWithImage:(UIImage *)image aspectRatioStle:(TOCropViewControllerAspectRatio)style;
136 |
137 | /**
138 | Play a custom animation of the target image zooming to its position in the crop controller while the background fades in.
139 | If any view configurations need to be done before the animation starts, please do them in `prepareForTransitionHandler`
140 |
141 | @param viewController The parent controller that this view controller would be presenting from.
142 | @param frame In the screen's coordinate space, the frame from which the image should animate from.
143 | @param completion A block that is called once the transition animation is completed.
144 | */
145 | - (void)presentAnimatedFromParentViewController:(UIViewController *)viewController fromFrame:(CGRect)frame completion:(void (^)(void))completion;
146 |
147 | /**
148 | Play a custom animation of the supplied cropped image zooming out from the cropped frame to the specified frame as the rest of the content fades out.
149 | If any view configurations need to be done before the animation starts, please do them in `prepareForTransitionHandler`
150 |
151 | @param viewController The parent controller that this view controller would be presenting from.
152 | @param frame The target frame that the image will animate to
153 | @param completion A block that is called once the transition animation is completed.
154 | */
155 | - (void)dismissAnimatedFromParentViewController:(UIViewController *)viewController withCroppedImage:(UIImage *)image toFrame:(CGRect)frame completion:(void (^)(void))completion;
156 |
157 | /**
158 | Play a custom animation of the supplied cropped image zooming out from the cropped frame to the specified frame as the rest of the content fades out.
159 | If any view configurations need to be done before the animation starts, please do them in `prepareForTransitionHandler`
160 |
161 | @param viewController The parent controller that this view controller would be presenting from.
162 | @param frame The target frame that the image will animate to
163 | @param completion A block that is called once the transition animation is completed.
164 | */
165 | - (void)dismissAnimatedFromParentViewController:(UIViewController *)viewController toFrame:(CGRect)frame completion:(void (^)(void))completion;
166 |
167 | @end
168 |
169 |
--------------------------------------------------------------------------------
/PureCamera/TOCropViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropViewController.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCropViewController.h"
24 | #import "TOCropView.h"
25 |
26 | #import "TOCropToolbar.h"
27 | #import "TOCropViewControllerTransitioning.h"
28 | #import "TOActivityCroppedImageProvider.h"
29 | #import "UIImage+CropRotate.h"
30 | #import "TOCroppedImageAttributes.h"
31 |
32 |
33 |
34 | @interface TOCropViewController ()
35 | @property (nonatomic, strong) TOCropView *cropView;
36 |
37 | @property (nonatomic, readwrite) UIImage *image;
38 | @property (nonatomic, strong) TOCropToolbar *toolbar;
39 | @property (nonatomic, strong) UIView *snapshotView;
40 | @property (nonatomic, strong) TOCropViewControllerTransitioning *transitionController;
41 | @property (nonatomic, assign) BOOL inTransition;
42 | @property (nonatomic, assign) TOCropViewControllerAspectRatio aspectRatioStle;
43 |
44 |
45 | #pragma clang diagnostic push
46 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
47 | @property (nonatomic, strong) UIPopoverController *activityPopoverController;
48 | #pragma clang diagnostic pop
49 |
50 | /* Button callback */
51 | - (void)cancelButtonTapped;
52 | - (void)doneButtonTapped;
53 | - (void)showAspectRatioDialog;
54 | - (void)resetCropViewLayout;
55 | - (void)rotateCropView;
56 |
57 | /* View layout */
58 | - (CGRect)frameForToolBarWithVerticalLayout:(BOOL)verticalLayout;
59 |
60 | @end
61 |
62 | @implementation TOCropViewController
63 |
64 | - (instancetype)initWithImage:(UIImage *)image aspectRatioStle:(TOCropViewControllerAspectRatio)aspectRatioStle
65 | {
66 | self = [super init];
67 | if (self) {
68 |
69 | self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
70 | self.modalPresentationStyle = UIModalPresentationFullScreen;
71 |
72 | _transitionController = [[TOCropViewControllerTransitioning alloc] init];
73 | _image = image;
74 | self.aspectRatioStle = aspectRatioStle;
75 |
76 | }
77 |
78 | return self;
79 | }
80 |
81 | - (void)viewDidLoad
82 | {
83 | [super viewDidLoad];
84 |
85 | BOOL landscapeLayout = CGRectGetWidth(self.view.frame) > CGRectGetHeight(self.view.frame);
86 | self.cropView = [[TOCropView alloc] initWithImage:self.image];
87 | self.cropView.frame = (CGRect){(landscapeLayout ? 44.0f : 0.0f),0,(CGRectGetWidth(self.view.bounds) - (landscapeLayout ? 44.0f : 0.0f)), (CGRectGetHeight(self.view.bounds)-(landscapeLayout ? 0.0f : 44.0f)) };
88 | self.cropView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
89 | self.cropView.delegate = self;
90 | [self.view addSubview:self.cropView];
91 | CGSize aspectRatio = CGSizeZero;
92 | // aspectRatio = CGSizeMake(1.0f, 2.0f);
93 | aspectRatio = [self convertAspectRatioStyleToRatio:self.aspectRatioStle];
94 |
95 | [self.cropView setAspectLockEnabledWithAspectRatio:aspectRatio animated:false];
96 |
97 | self.toolbar = [[TOCropToolbar alloc] initWithFrame:CGRectZero];
98 | self.toolbar.frame = [self frameForToolBarWithVerticalLayout:CGRectGetWidth(self.view.bounds) < CGRectGetHeight(self.view.bounds)];
99 | [self.view addSubview:self.toolbar];
100 |
101 | __weak typeof(self) weakSelf = self;
102 | self.toolbar.doneButtonTapped = ^{ [weakSelf doneButtonTapped]; };
103 | self.toolbar.cancelButtonTapped = ^{ [weakSelf cancelButtonTapped]; };
104 | self.toolbar.resetButtonTapped = ^{ [weakSelf resetCropViewLayout]; };
105 | self.toolbar.clampButtonTapped = ^{ [weakSelf showAspectRatioDialog]; };
106 | self.toolbar.rotateButtonTapped = ^{ [weakSelf rotateCropView]; };
107 |
108 | self.transitioningDelegate = self;
109 |
110 | self.view.backgroundColor = self.cropView.backgroundColor;
111 | }
112 |
113 | - (void)viewWillAppear:(BOOL)animated
114 | {
115 | [super viewWillAppear:animated];
116 |
117 | if ([UIApplication sharedApplication].statusBarHidden == NO) {
118 | self.inTransition = YES;
119 | [self setNeedsStatusBarAppearanceUpdate];
120 | }
121 | }
122 |
123 | - (void)viewDidAppear:(BOOL)animated
124 | {
125 | [super viewDidAppear:animated];
126 | self.inTransition = NO;
127 | if (animated && [UIApplication sharedApplication].statusBarHidden == NO) {
128 | [UIView animateWithDuration:0.3f animations:^{ [self setNeedsStatusBarAppearanceUpdate]; }];
129 |
130 | if (self.cropView.gridOverlayHidden)
131 | [self.cropView setGridOverlayHidden:NO animated:YES];
132 | }
133 | }
134 |
135 | - (void)viewWillDisappear:(BOOL)animated
136 | {
137 | [super viewWillDisappear:animated];
138 | self.inTransition = YES;
139 | [UIView animateWithDuration:0.5f animations:^{ [self setNeedsStatusBarAppearanceUpdate]; }];
140 | }
141 |
142 | - (void)viewDidDisappear:(BOOL)animated
143 | {
144 | [super viewDidDisappear:animated];
145 | self.inTransition = NO;
146 | [self setNeedsStatusBarAppearanceUpdate];
147 | }
148 |
149 | #pragma mark - Status Bar -
150 | - (UIStatusBarStyle)preferredStatusBarStyle
151 | {
152 | return UIStatusBarStyleDefault;
153 | }
154 |
155 | - (BOOL)prefersStatusBarHidden
156 | {
157 | return !self.inTransition;
158 | }
159 |
160 | - (CGRect)frameForToolBarWithVerticalLayout:(BOOL)verticalLayout
161 | {
162 | CGRect frame = self.toolbar.frame;
163 | if (verticalLayout ) {
164 | frame = self.toolbar.frame;
165 | frame.origin.x = 0.0f;
166 | frame.origin.y = 0.0f;
167 | frame.size.width = 44.0f;
168 | frame.size.height = CGRectGetHeight(self.view.frame);
169 | }
170 | else {
171 | frame.origin.x = 0.0f;
172 | frame.origin.y = CGRectGetHeight(self.view.bounds) - 44.0f;
173 | frame.size.width = CGRectGetWidth(self.view.bounds);
174 | frame.size.height = 44.0f;
175 | }
176 |
177 | return frame;
178 | }
179 |
180 | - (void)viewDidLayoutSubviews
181 | {
182 | [super viewDidLayoutSubviews];
183 |
184 | BOOL verticalLayout = CGRectGetWidth(self.view.bounds) > CGRectGetHeight(self.view.bounds);
185 | if (verticalLayout ) {
186 | CGRect frame = self.cropView.frame;
187 | frame.origin.x = 44.0f;
188 | frame.size.width = CGRectGetWidth(self.view.bounds) - 44.0f;
189 | frame.size.height = CGRectGetHeight(self.view.bounds);
190 | self.cropView.frame = frame;
191 | }
192 | else {
193 | CGRect frame = self.cropView.frame;
194 | frame.origin.x = 0.0f;
195 | frame.size.width = CGRectGetWidth(self.view.bounds);
196 | frame.size.height = CGRectGetHeight(self.view.bounds) - 44.0f;
197 | self.cropView.frame = frame;
198 | }
199 |
200 | [UIView setAnimationsEnabled:NO];
201 | self.toolbar.frame = [self frameForToolBarWithVerticalLayout:verticalLayout];
202 | [self.toolbar setNeedsLayout];
203 | [UIView setAnimationsEnabled:YES];
204 | }
205 |
206 | #pragma mark - Rotation Handling -
207 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
208 | {
209 | self.snapshotView = [self.toolbar snapshotViewAfterScreenUpdates:NO];
210 | self.snapshotView.frame = self.toolbar.frame;
211 |
212 | if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation))
213 | self.snapshotView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
214 | else
215 | self.snapshotView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin;
216 |
217 | [self.view addSubview:self.snapshotView];
218 |
219 | self.toolbar.frame = [self frameForToolBarWithVerticalLayout:UIInterfaceOrientationIsLandscape(toInterfaceOrientation)];
220 | [self.toolbar layoutIfNeeded];
221 |
222 | self.toolbar.alpha = 0.0f;
223 |
224 | self.cropView.simpleMode = YES;
225 | [self.cropView prepareforRotation];
226 | }
227 |
228 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
229 | {
230 | self.toolbar.frame = [self frameForToolBarWithVerticalLayout:UIInterfaceOrientationIsLandscape(toInterfaceOrientation)];
231 |
232 | [UIView animateWithDuration:duration animations:^{
233 | self.snapshotView.alpha = 0.0f;
234 | self.toolbar.alpha = 1.0f;
235 | }];
236 | [self.cropView performRelayoutForRotation];
237 | }
238 |
239 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
240 | {
241 | [self.snapshotView removeFromSuperview];
242 | self.snapshotView = nil;
243 |
244 | [self.cropView setSimpleMode:NO animated:YES];
245 | }
246 |
247 | #pragma mark - Reset -
248 | - (void)resetCropViewLayout
249 | {
250 | [self.cropView resetLayoutToDefaultAnimated:YES];
251 | self.cropView.aspectLockEnabled = NO;
252 | self.toolbar.clampButtonGlowing = NO;
253 | }
254 |
255 | #pragma mark - Aspect Ratio Handling -
256 | - (void)showAspectRatioDialog
257 | {
258 | // if (self.cropView.aspectLockEnabled) {
259 | // self.cropView.aspectLockEnabled = NO;
260 | // self.toolbar.clampButtonGlowing = NO;
261 | // return;
262 | // }
263 | //
264 | //TODO: Completely overhaul this once iOS 7 support is dropped
265 | #pragma clang diagnostic push
266 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
267 | BOOL verticalCropBox = NO;
268 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
269 | delegate:self
270 | cancelButtonTitle:NSLocalizedStringFromTableInBundle(@"取消",
271 | @"TOCropViewControllerLocalizable",
272 | [NSBundle bundleForClass:[self class]],
273 | nil)
274 | destructiveButtonTitle:nil
275 | otherButtonTitles:NSLocalizedStringFromTableInBundle(@"原始",
276 | @"TOCropViewControllerLocalizable",
277 | [NSBundle bundleForClass:[self class]],
278 | nil),
279 | NSLocalizedStringFromTableInBundle(@"正方形",
280 | @"TOCropViewControllerLocalizable",
281 | [NSBundle bundleForClass:[self class]],
282 | nil),
283 | verticalCropBox ? @"2:1" : @"1:2",
284 | verticalCropBox ? @"2:3" : @"3:2",
285 | verticalCropBox ? @"3:4" : @"4:3",
286 | verticalCropBox ? @"9:16" : @"16:9",nil];
287 |
288 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
289 | [actionSheet showFromRect:self.toolbar.clampButtonFrame inView:self.toolbar animated:YES];
290 | else
291 | [actionSheet showInView:self.view];
292 | #pragma clang diagnostic pop
293 | }
294 |
295 |
296 |
297 | -(CGSize)convertAspectRatioStyleToRatio:(TOCropViewControllerAspectRatio)aspectRatioStle {
298 | CGSize aspectRatio = CGSizeZero;
299 |
300 | switch (aspectRatioStle) {
301 | case TOCropViewControllerAspectRatioOriginal:
302 | aspectRatio = CGSizeZero;
303 | break;
304 | case TOCropViewControllerAspectRatioSquare:
305 | aspectRatio = CGSizeMake(1.0f, 1.0f);
306 | break;
307 | case TOCropViewControllerAspectRatio1x2:
308 | aspectRatio = CGSizeMake(1.0f, 2.0f);
309 | break;
310 | case TOCropViewControllerAspectRatio3x2:
311 | aspectRatio = CGSizeMake(3.0f, 2.0f);
312 | break;
313 | case TOCropViewControllerAspectRatio5x3:
314 | aspectRatio = CGSizeMake(5.0f, 3.0f);
315 | break;
316 | case TOCropViewControllerAspectRatio4x3:
317 | aspectRatio = CGSizeMake(4.0f, 3.0f);
318 | break;
319 | case TOCropViewControllerAspectRatio5x4:
320 | aspectRatio = CGSizeMake(5.0f, 4.0f);
321 | break;
322 | case TOCropViewControllerAspectRatio7x5:
323 | aspectRatio = CGSizeMake(7.0f, 5.0f);
324 | break;
325 | case TOCropViewControllerAspectRatio16x9:
326 | aspectRatio = CGSizeMake(16.0f, 9.0f);
327 | break;
328 | default:
329 | break;
330 | }
331 | return aspectRatio;
332 | }
333 | - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
334 | {
335 | CGSize aspectRatio = CGSizeZero;
336 |
337 | switch (buttonIndex) {
338 | case TOCropViewControllerAspectRatioOriginal:
339 | aspectRatio = CGSizeZero;
340 | break;
341 | case TOCropViewControllerAspectRatioSquare:
342 | aspectRatio = CGSizeMake(1.0f, 1.0f);
343 | break;
344 | case TOCropViewControllerAspectRatio1x2:
345 | aspectRatio = CGSizeMake(1.0f, 2.0f);
346 | break;
347 | case TOCropViewControllerAspectRatio3x2:
348 | aspectRatio = CGSizeMake(3.0f, 2.0f);
349 | break;
350 | case TOCropViewControllerAspectRatio5x3:
351 | aspectRatio = CGSizeMake(5.0f, 3.0f);
352 | break;
353 | case TOCropViewControllerAspectRatio4x3:
354 | aspectRatio = CGSizeMake(4.0f, 3.0f);
355 | break;
356 | case TOCropViewControllerAspectRatio5x4:
357 | aspectRatio = CGSizeMake(5.0f, 4.0f);
358 | break;
359 | case TOCropViewControllerAspectRatio7x5:
360 | aspectRatio = CGSizeMake(7.0f, 5.0f);
361 | break;
362 | case TOCropViewControllerAspectRatio16x9:
363 | aspectRatio = CGSizeMake(16.0f, 9.0f);
364 | break;
365 | default:
366 | return;
367 | }
368 |
369 | // if (self.cropView.cropBoxAspectRatioIsPortrait) {
370 | // CGFloat width = aspectRatio.width;
371 | // aspectRatio.width = aspectRatio.height;
372 | // aspectRatio.height = width;
373 | // }
374 |
375 | [self.cropView setAspectLockEnabledWithAspectRatio:aspectRatio animated:YES];
376 | self.toolbar.clampButtonGlowing = YES;
377 | }
378 |
379 | - (void)rotateCropView
380 | {
381 | [self.cropView rotateImageNinetyDegreesAnimated:YES];
382 | }
383 |
384 | #pragma mark - Crop View Delegates -
385 | - (void)cropViewDidBecomeResettable:(TOCropView *)cropView
386 | {
387 | self.toolbar.resetButtonEnabled = YES;
388 | }
389 |
390 | - (void)cropViewDidBecomeNonResettable:(TOCropView *)cropView
391 | {
392 | self.toolbar.resetButtonEnabled = NO;
393 | }
394 |
395 | #pragma mark - Presentation Handling -
396 | - (void)presentAnimatedFromParentViewController:(UIViewController *)viewController fromFrame:(CGRect)frame completion:(void (^)(void))completion
397 | {
398 | self.transitionController.image = self.image;
399 | self.transitionController.fromFrame = frame;
400 |
401 | __weak typeof (self) weakSelf = self;
402 | [viewController presentViewController:self animated:YES completion:^ {
403 | typeof (self) strongSelf = weakSelf;
404 | if (completion) {
405 | completion();
406 | }
407 |
408 | [strongSelf.cropView setCroppingViewsHidden:NO animated:YES];
409 | if (!CGRectIsEmpty(frame)) {
410 | [strongSelf.cropView setGridOverlayHidden:NO animated:YES];
411 | }
412 | }];
413 | }
414 |
415 | - (void)dismissAnimatedFromParentViewController:(UIViewController *)viewController withCroppedImage:(UIImage *)image toFrame:(CGRect)frame completion:(void (^)(void))completion
416 | {
417 | self.transitionController.image = image;
418 | self.transitionController.fromFrame = [self.cropView convertRect:self.cropView.cropBoxFrame toView:self.view];
419 | self.transitionController.toFrame = frame;
420 |
421 | [viewController dismissViewControllerAnimated:YES completion:^ {
422 | if (completion) {
423 | completion();
424 | }
425 | }];
426 | }
427 |
428 | - (void)dismissAnimatedFromParentViewController:(UIViewController *)viewController toFrame:(CGRect)frame completion:(void (^)(void))completion
429 | {
430 | self.transitionController.image = self.image;
431 | self.transitionController.fromFrame = [self.cropView convertRect:self.cropView.imageViewFrame toView:self.view];
432 | self.transitionController.toFrame = frame;
433 |
434 | [viewController dismissViewControllerAnimated:YES completion:^ {
435 | if (completion) {
436 | completion();
437 | }
438 | }];
439 | }
440 |
441 | - (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
442 | {
443 | __weak typeof (self) weakSelf = self;
444 | self.transitionController.prepareForTransitionHandler = ^{
445 | typeof (self) strongSelf = weakSelf;
446 | strongSelf.transitionController.toFrame = [strongSelf.cropView convertRect:strongSelf.cropView.cropBoxFrame toView:strongSelf.view];
447 | if (!CGRectIsEmpty(strongSelf.transitionController.fromFrame))
448 | strongSelf.cropView.croppingViewsHidden = YES;
449 |
450 | if (strongSelf.prepareForTransitionHandler)
451 | strongSelf.prepareForTransitionHandler();
452 |
453 | strongSelf.prepareForTransitionHandler = nil;
454 | };
455 |
456 | self.transitionController.isDismissing = NO;
457 | return self.transitionController;
458 | }
459 |
460 | - (id )animationControllerForDismissedController:(UIViewController *)dismissed
461 | {
462 | __weak typeof (self) weakSelf = self;
463 | self.transitionController.prepareForTransitionHandler = ^{
464 | typeof (self) strongSelf = weakSelf;
465 | if (!CGRectIsEmpty(strongSelf.transitionController.toFrame))
466 | strongSelf.cropView.croppingViewsHidden = YES;
467 | else
468 | strongSelf.cropView.simpleMode = YES;
469 |
470 | if (strongSelf.prepareForTransitionHandler)
471 | strongSelf.prepareForTransitionHandler();
472 | };
473 |
474 | self.transitionController.isDismissing = YES;
475 | return self.transitionController;
476 | }
477 |
478 | #pragma mark - Button Feedback -
479 | - (void)cancelButtonTapped
480 | {
481 | if ([self.delegate respondsToSelector:@selector(cropViewController:didFinishCancelled:)]) {
482 | [self.delegate cropViewController:self didFinishCancelled:YES];
483 | return;
484 | }
485 |
486 | self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
487 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
488 | }
489 |
490 | - (void)doneButtonTapped
491 | {
492 | CGRect cropFrame = self.cropView.croppedImageFrame;
493 | NSInteger angle = self.cropView.angle;
494 |
495 | //If desired, when the user taps done, show an activity sheet
496 | if (self.showActivitySheetOnDone) {
497 | TOActivityCroppedImageProvider *imageItem = [[TOActivityCroppedImageProvider alloc] initWithImage:self.image cropFrame:cropFrame angle:angle];
498 | TOCroppedImageAttributes *attributes = [[TOCroppedImageAttributes alloc] initWithCroppedFrame:cropFrame angle:angle originalImageSize:self.image.size];
499 |
500 | NSMutableArray *activityItems = [@[imageItem, attributes] mutableCopy];
501 | if (self.activityItems)
502 | [activityItems addObjectsFromArray:self.activityItems];
503 |
504 | UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:self.applicationActivities];
505 | activityController.excludedActivityTypes = self.excludedActivityTypes;
506 |
507 | if (NSClassFromString(@"UIPopoverPresentationController")) {
508 | activityController.modalPresentationStyle = UIModalPresentationPopover;
509 | activityController.popoverPresentationController.sourceView = self.toolbar;
510 | activityController.popoverPresentationController.sourceRect = self.toolbar.doneButtonFrame;
511 | [self presentViewController:activityController animated:YES completion:nil];
512 | }
513 | else {
514 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
515 | [self presentViewController:activityController animated:YES completion:nil];
516 | }
517 | else {
518 | #pragma clang diagnostic push
519 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
520 | [self.activityPopoverController dismissPopoverAnimated:NO];
521 | self.activityPopoverController = [[UIPopoverController alloc] initWithContentViewController:activityController];
522 | [self.activityPopoverController presentPopoverFromRect:self.toolbar.doneButtonFrame inView:self.toolbar permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
523 | #pragma clang diagnostic pop
524 | }
525 | }
526 | __weak typeof(activityController) blockController = activityController;
527 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
528 | activityController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
529 | if (!completed)
530 | return;
531 |
532 | if ([self.delegate respondsToSelector:@selector(cropViewController:didFinishCancelled:)]) {
533 | [self.delegate cropViewController:self didFinishCancelled:NO];
534 | }
535 | else {
536 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
537 | blockController.completionWithItemsHandler = nil;
538 | }
539 | };
540 | #else
541 | activityController.completionHandler = ^(NSString *activityType, BOOL completed) {
542 | if (!completed)
543 | return;
544 |
545 | if ([self.delegate respondsToSelector:@selector(cropViewController:didFinishCancelled:)]) {
546 | [self.delegate cropViewController:self didFinishCancelled:NO];
547 | }
548 | else {
549 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
550 | blockController.completionHandler = nil;
551 | }
552 | };
553 | #endif
554 |
555 | return;
556 | }
557 |
558 | //If the delegate that only supplies crop data is provided, call it
559 | if ([self.delegate respondsToSelector:@selector(cropViewController:didCropImageToRect:angle:)]) {
560 | [self.delegate cropViewController:self didCropImageToRect:cropFrame angle:angle];
561 | }
562 | //If the delegate that requires the specific cropped image is provided, call it
563 | else if ([self.delegate respondsToSelector:@selector(cropViewController:didCropToImage:withRect:angle:)]) {
564 | UIImage *image = nil;
565 | if (angle == 0 && CGRectEqualToRect(cropFrame, (CGRect){CGPointZero, self.image.size})) {
566 | image = self.image;
567 | }
568 | else {
569 | image = [self.image croppedImageWithFrame:cropFrame angle:angle];
570 | }
571 |
572 | //dispatch on the next run-loop so the animation isn't interuppted by the crop operation
573 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.03f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
574 | [self.delegate cropViewController:self didCropToImage:image withRect:cropFrame angle:angle];
575 | });
576 | }
577 | else {
578 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
579 | }
580 | }
581 |
582 | @end
583 |
--------------------------------------------------------------------------------
/PureCamera/TOCropViewControllerLocalizable.strings:
--------------------------------------------------------------------------------
1 | "Done" = "Done";
2 | "Cancel" = "Cancel";
3 | "Reset" = "Reset";
4 | "Original" = "Original";
5 | "Square" = "Square";
--------------------------------------------------------------------------------
/PureCamera/TOCropViewControllerTransitioning.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropViewControllerTransitioning.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 | #import
25 |
26 | @interface TOCropViewControllerTransitioning : NSObject
27 |
28 | @property (nonatomic, assign) BOOL isDismissing;
29 |
30 | @property (nonatomic, strong) UIImage *image;
31 | @property (nonatomic, assign) CGRect fromFrame;
32 | @property (nonatomic, assign) CGRect toFrame;
33 |
34 | @property (nonatomic, copy) void (^prepareForTransitionHandler)(void);
35 |
36 | - (void)reset;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/PureCamera/TOCropViewControllerTransitioning.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCropViewControllerTransitioning.m
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCropViewControllerTransitioning.h"
24 | #import
25 |
26 | @implementation TOCropViewControllerTransitioning
27 |
28 | - (NSTimeInterval)transitionDuration:(id )transitionContext
29 | {
30 | return 0.45f;
31 | }
32 |
33 | - (void)animateTransition:(id )transitionContext
34 | {
35 | UIView *containerView = [transitionContext containerView];
36 |
37 | UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
38 | UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
39 |
40 | UIViewController *cropViewController = (self.isDismissing == NO) ? toViewController : fromViewController;
41 | UIViewController *previousController = (self.isDismissing == NO) ? fromViewController : toViewController;
42 |
43 | cropViewController.view.frame = containerView.bounds;
44 | previousController.view.frame = containerView.bounds;
45 |
46 | UIImageView *imageView = nil;
47 | if ((self.isDismissing && !CGRectIsEmpty(self.toFrame)) || (!self.isDismissing && !CGRectIsEmpty(self.fromFrame))) {
48 | imageView = [[UIImageView alloc] initWithImage:self.image];
49 | imageView.frame = self.fromFrame;
50 | [containerView addSubview:imageView];
51 | }
52 |
53 | if (self.isDismissing == NO) {
54 | [containerView addSubview:cropViewController.view];
55 | [containerView bringSubviewToFront:imageView];
56 | }
57 | else {
58 | [containerView insertSubview:previousController.view belowSubview:cropViewController.view];
59 | }
60 |
61 | if (self.prepareForTransitionHandler)
62 | self.prepareForTransitionHandler();
63 |
64 | cropViewController.view.alpha = (self.isDismissing ? 1.0f : 0.0f);
65 | if (imageView) {
66 | [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0f usingSpringWithDamping:1.0f initialSpringVelocity:0.7f options:0 animations:^{
67 | imageView.frame = self.toFrame;
68 | } completion:^(BOOL complete) {
69 | [imageView removeFromSuperview];
70 | }];
71 | }
72 |
73 | [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
74 | cropViewController.view.alpha = (self.isDismissing ? 0.0f : 1.0f);
75 | } completion:^(BOOL complete) {
76 | [self reset];
77 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
78 | }];
79 | }
80 |
81 | - (void)reset
82 | {
83 | self.image = nil;
84 | self.fromFrame = CGRectZero;
85 | self.toFrame = CGRectZero;
86 | self.prepareForTransitionHandler = nil;
87 | }
88 |
89 | @end
90 |
--------------------------------------------------------------------------------
/PureCamera/TOCroppedImageAttributes.h:
--------------------------------------------------------------------------------
1 | //
2 | // TOCroppedImageAttributes.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 | #import
25 |
26 | @interface TOCroppedImageAttributes : NSObject
27 |
28 | @property (nonatomic, readonly) NSInteger angle;
29 | @property (nonatomic, readonly) CGRect croppedFrame;
30 | @property (nonatomic, readonly) CGSize originalImageSize;
31 |
32 | - (instancetype)initWithCroppedFrame:(CGRect)croppedFrame angle:(NSInteger)angle originalImageSize:(CGSize)originalSize;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/PureCamera/TOCroppedImageAttributes.m:
--------------------------------------------------------------------------------
1 | //
2 | // TOCroppedImageAttributes.m
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TOCroppedImageAttributes.h"
24 |
25 | @interface TOCroppedImageAttributes ()
26 |
27 | @property (nonatomic, assign, readwrite) NSInteger angle;
28 | @property (nonatomic, assign, readwrite) CGRect croppedFrame;
29 | @property (nonatomic, assign, readwrite) CGSize originalImageSize;
30 |
31 | @end
32 |
33 | @implementation TOCroppedImageAttributes
34 |
35 | - (instancetype)initWithCroppedFrame:(CGRect)croppedFrame angle:(NSInteger)angle originalImageSize:(CGSize)originalSize
36 | {
37 | if (self = [super init]) {
38 | _angle = angle;
39 | _croppedFrame = croppedFrame;
40 | _originalImageSize = originalSize;
41 | }
42 |
43 | return self;
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/PureCamera/UIImage+CropRotate.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+CropRotate.h
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | @interface UIImage (CropRotate)
26 |
27 | - (UIImage *)croppedImageWithFrame:(CGRect)frame angle:(NSInteger)angle;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/PureCamera/UIImage+CropRotate.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+CropRotate.m
3 | //
4 | // Copyright 2015 Timothy Oliver. All rights reserved.
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to
8 | // deal in the Software without restriction, including without limitation the
9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | // sell copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "UIImage+CropRotate.h"
24 |
25 | @implementation UIImage (CropRotate)
26 |
27 | - (UIImage *)croppedImageWithFrame:(CGRect)frame angle:(NSInteger)angle
28 | {
29 | UIImage *croppedImage = nil;
30 | CGPoint drawPoint = CGPointZero;
31 |
32 | UIGraphicsBeginImageContextWithOptions(frame.size, YES, self.scale);
33 | {
34 | CGContextRef context = UIGraphicsGetCurrentContext();
35 |
36 | //To conserve memory in not needing to completely re-render the image re-rotated,
37 | //map the image to a view and then use Core Animation to manipulate its rotation
38 | if (angle != 0) {
39 | UIImageView *imageView = [[UIImageView alloc] initWithImage:self];
40 | imageView.layer.minificationFilter = @"nearest";
41 | imageView.layer.magnificationFilter = @"neareset";
42 | imageView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, angle * (M_PI/180.0f));
43 | CGRect rotatedRect = CGRectApplyAffineTransform(imageView.bounds, imageView.transform);
44 | UIView *containerView = [[UIView alloc] initWithFrame:(CGRect){CGPointZero, rotatedRect.size}];
45 | [containerView addSubview:imageView];
46 | imageView.center = containerView.center;
47 | CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
48 | [containerView.layer renderInContext:context];
49 | }
50 | else {
51 | CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
52 | [self drawAtPoint:drawPoint];
53 | }
54 |
55 | croppedImage = UIGraphicsGetImageFromCurrentImageContext();
56 | }
57 | UIGraphicsEndImageContext();
58 |
59 | return croppedImage;
60 | }
61 |
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/PureCamera/UIImage+FixOrientation.h:
--------------------------------------------------------------------------------
1 | // http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload
2 |
3 |
4 |
5 | #import
6 |
7 | @interface UIImage(fixOrientation)
8 | - (UIImage *)fixOrientation;
9 | @end
10 |
--------------------------------------------------------------------------------
/PureCamera/UIImage+FixOrientation.m:
--------------------------------------------------------------------------------
1 |
2 |
3 | #import "UIImage+FixOrientation.h"
4 |
5 | @implementation UIImage (fixOrientation)
6 |
7 | - (UIImage *)fixOrientation {
8 |
9 | // No-op if the orientation is already correct
10 | if (self.imageOrientation == UIImageOrientationUp) return self;
11 |
12 | // We need to calculate the proper transformation to make the image upright.
13 | // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
14 | CGAffineTransform transform = CGAffineTransformIdentity;
15 |
16 | switch (self.imageOrientation) {
17 | case UIImageOrientationDown:
18 | case UIImageOrientationDownMirrored:
19 | transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
20 | transform = CGAffineTransformRotate(transform, M_PI);
21 | break;
22 |
23 | case UIImageOrientationLeft:
24 | case UIImageOrientationLeftMirrored:
25 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
26 | transform = CGAffineTransformRotate(transform, M_PI_2);
27 | break;
28 |
29 | case UIImageOrientationRight:
30 | case UIImageOrientationRightMirrored:
31 | transform = CGAffineTransformTranslate(transform, 0, self.size.height);
32 | transform = CGAffineTransformRotate(transform, -M_PI_2);
33 | break;
34 | case UIImageOrientationUp:
35 | case UIImageOrientationUpMirrored:
36 | break;
37 | }
38 |
39 | switch (self.imageOrientation) {
40 | case UIImageOrientationUpMirrored:
41 | case UIImageOrientationDownMirrored:
42 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
43 | transform = CGAffineTransformScale(transform, -1, 1);
44 | break;
45 |
46 | case UIImageOrientationLeftMirrored:
47 | case UIImageOrientationRightMirrored:
48 | transform = CGAffineTransformTranslate(transform, self.size.height, 0);
49 | transform = CGAffineTransformScale(transform, -1, 1);
50 | break;
51 | case UIImageOrientationUp:
52 | case UIImageOrientationDown:
53 | case UIImageOrientationLeft:
54 | case UIImageOrientationRight:
55 | break;
56 | }
57 |
58 | // Now we draw the underlying CGImage into a new context, applying the transform
59 | // calculated above.
60 | CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
61 | CGImageGetBitsPerComponent(self.CGImage), 0,
62 | CGImageGetColorSpace(self.CGImage),
63 | CGImageGetBitmapInfo(self.CGImage));
64 | CGContextConcatCTM(ctx, transform);
65 | switch (self.imageOrientation) {
66 | case UIImageOrientationLeft:
67 | case UIImageOrientationLeftMirrored:
68 | case UIImageOrientationRight:
69 | case UIImageOrientationRightMirrored:
70 | // Grr...
71 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
72 | break;
73 |
74 | default:
75 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
76 | break;
77 | }
78 |
79 | // And now we just create a new UIImage from the drawing context
80 | CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
81 | UIImage *img = [UIImage imageWithCGImage:cgimg];
82 | CGContextRelease(ctx);
83 | CGImageRelease(cgimg);
84 | return img;
85 | }
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1D53DF0E1F48343000534C17 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D53DF051F48343000534C17 /* AppDelegate.m */; };
11 | 1D53DF0F1F48343000534C17 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D53DF061F48343000534C17 /* Assets.xcassets */; };
12 | 1D53DF101F48343000534C17 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1D53DF071F48343000534C17 /* LaunchScreen.storyboard */; };
13 | 1D53DF111F48343000534C17 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1D53DF091F48343000534C17 /* Main.storyboard */; };
14 | 1D53DF121F48343000534C17 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D53DF0B1F48343000534C17 /* main.m */; };
15 | 1D53DF131F48343000534C17 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D53DF0D1F48343000534C17 /* ViewController.m */; };
16 | 6C163CC520AF159700CB5DB0 /* TOActivityCroppedImageProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CA920AF159700CB5DB0 /* TOActivityCroppedImageProvider.m */; };
17 | 6C163CC620AF159700CB5DB0 /* UIImage+CropRotate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CAB20AF159700CB5DB0 /* UIImage+CropRotate.m */; };
18 | 6C163CC720AF159700CB5DB0 /* TOCropViewControllerTransitioning.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CAD20AF159700CB5DB0 /* TOCropViewControllerTransitioning.m */; };
19 | 6C163CC820AF159700CB5DB0 /* LLSimpleCamera+Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CAE20AF159700CB5DB0 /* LLSimpleCamera+Helper.m */; };
20 | 6C163CC920AF159700CB5DB0 /* TOCroppedImageAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CB120AF159700CB5DB0 /* TOCroppedImageAttributes.m */; };
21 | 6C163CCA20AF159700CB5DB0 /* PureCamera.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6C163CB220AF159700CB5DB0 /* PureCamera.bundle */; };
22 | 6C163CCB20AF159700CB5DB0 /* TOCropScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CB520AF159700CB5DB0 /* TOCropScrollView.m */; };
23 | 6C163CCC20AF159700CB5DB0 /* TOCropViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CB620AF159700CB5DB0 /* TOCropViewController.m */; };
24 | 6C163CCD20AF159700CB5DB0 /* TOCropViewControllerLocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6C163CB720AF159700CB5DB0 /* TOCropViewControllerLocalizable.strings */; };
25 | 6C163CCE20AF159700CB5DB0 /* TOCropView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CB820AF159700CB5DB0 /* TOCropView.m */; };
26 | 6C163CCF20AF159700CB5DB0 /* TOCropOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CBA20AF159700CB5DB0 /* TOCropOverlayView.m */; };
27 | 6C163CD020AF159700CB5DB0 /* PureCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CBD20AF159700CB5DB0 /* PureCamera.m */; };
28 | 6C163CD120AF159700CB5DB0 /* TOCropToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CBF20AF159700CB5DB0 /* TOCropToolbar.m */; };
29 | 6C163CD220AF159700CB5DB0 /* LLSimpleCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CC120AF159700CB5DB0 /* LLSimpleCamera.m */; };
30 | 6C163CD320AF159700CB5DB0 /* UIImage+FixOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CC420AF159700CB5DB0 /* UIImage+FixOrientation.m */; };
31 | 6C163CD620AF165B00CB5DB0 /* PureCropVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C163CD520AF165B00CB5DB0 /* PureCropVC.m */; };
32 | 6C397B262065003600B3B864 /* KModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C397B252065003500B3B864 /* KModel.m */; };
33 | /* End PBXBuildFile section */
34 |
35 | /* Begin PBXFileReference section */
36 | 1D53DF041F48343000534C17 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
37 | 1D53DF051F48343000534C17 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
38 | 1D53DF061F48343000534C17 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
39 | 1D53DF081F48343000534C17 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
40 | 1D53DF0A1F48343000534C17 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
41 | 1D53DF0B1F48343000534C17 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
42 | 1D53DF0C1F48343000534C17 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
43 | 1D53DF0D1F48343000534C17 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
44 | 1DD4F5021DDC676600F0D6B0 /* PureCamerademo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PureCamerademo.app; sourceTree = BUILT_PRODUCTS_DIR; };
45 | 6C163CA920AF159700CB5DB0 /* TOActivityCroppedImageProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOActivityCroppedImageProvider.m; sourceTree = ""; };
46 | 6C163CAA20AF159700CB5DB0 /* TOCropView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropView.h; sourceTree = ""; };
47 | 6C163CAB20AF159700CB5DB0 /* UIImage+CropRotate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+CropRotate.m"; sourceTree = ""; };
48 | 6C163CAC20AF159700CB5DB0 /* PureCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PureCamera.h; sourceTree = ""; };
49 | 6C163CAD20AF159700CB5DB0 /* TOCropViewControllerTransitioning.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropViewControllerTransitioning.m; sourceTree = ""; };
50 | 6C163CAE20AF159700CB5DB0 /* LLSimpleCamera+Helper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "LLSimpleCamera+Helper.m"; sourceTree = ""; };
51 | 6C163CAF20AF159700CB5DB0 /* TOCropOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropOverlayView.h; sourceTree = ""; };
52 | 6C163CB020AF159700CB5DB0 /* LLSimpleCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLSimpleCamera.h; sourceTree = ""; };
53 | 6C163CB120AF159700CB5DB0 /* TOCroppedImageAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCroppedImageAttributes.m; sourceTree = ""; };
54 | 6C163CB220AF159700CB5DB0 /* PureCamera.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = PureCamera.bundle; sourceTree = ""; };
55 | 6C163CB320AF159700CB5DB0 /* TOCropToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropToolbar.h; sourceTree = ""; };
56 | 6C163CB420AF159700CB5DB0 /* UIImage+FixOrientation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+FixOrientation.h"; sourceTree = ""; };
57 | 6C163CB520AF159700CB5DB0 /* TOCropScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropScrollView.m; sourceTree = ""; };
58 | 6C163CB620AF159700CB5DB0 /* TOCropViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropViewController.m; sourceTree = ""; };
59 | 6C163CB720AF159700CB5DB0 /* TOCropViewControllerLocalizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = TOCropViewControllerLocalizable.strings; sourceTree = ""; };
60 | 6C163CB820AF159700CB5DB0 /* TOCropView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropView.m; sourceTree = ""; };
61 | 6C163CB920AF159700CB5DB0 /* TOActivityCroppedImageProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOActivityCroppedImageProvider.h; sourceTree = ""; };
62 | 6C163CBA20AF159700CB5DB0 /* TOCropOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropOverlayView.m; sourceTree = ""; };
63 | 6C163CBB20AF159700CB5DB0 /* LLSimpleCamera+Helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LLSimpleCamera+Helper.h"; sourceTree = ""; };
64 | 6C163CBC20AF159700CB5DB0 /* TOCropViewControllerTransitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropViewControllerTransitioning.h; sourceTree = ""; };
65 | 6C163CBD20AF159700CB5DB0 /* PureCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PureCamera.m; sourceTree = ""; };
66 | 6C163CBE20AF159700CB5DB0 /* UIImage+CropRotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+CropRotate.h"; sourceTree = ""; };
67 | 6C163CBF20AF159700CB5DB0 /* TOCropToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCropToolbar.m; sourceTree = ""; };
68 | 6C163CC020AF159700CB5DB0 /* TOCroppedImageAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCroppedImageAttributes.h; sourceTree = ""; };
69 | 6C163CC120AF159700CB5DB0 /* LLSimpleCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLSimpleCamera.m; sourceTree = ""; };
70 | 6C163CC220AF159700CB5DB0 /* TOCropViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropViewController.h; sourceTree = ""; };
71 | 6C163CC320AF159700CB5DB0 /* TOCropScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TOCropScrollView.h; sourceTree = ""; };
72 | 6C163CC420AF159700CB5DB0 /* UIImage+FixOrientation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+FixOrientation.m"; sourceTree = ""; };
73 | 6C163CD420AF165B00CB5DB0 /* PureCropVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PureCropVC.h; sourceTree = ""; };
74 | 6C163CD520AF165B00CB5DB0 /* PureCropVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PureCropVC.m; sourceTree = ""; };
75 | 6C1D93111F48591100AE1102 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../../Info.plist; sourceTree = ""; };
76 | 6C397B242065003500B3B864 /* KModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KModel.h; sourceTree = ""; };
77 | 6C397B252065003500B3B864 /* KModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KModel.m; sourceTree = ""; };
78 | /* End PBXFileReference section */
79 |
80 | /* Begin PBXFrameworksBuildPhase section */
81 | 1DD4F4FF1DDC676600F0D6B0 /* Frameworks */ = {
82 | isa = PBXFrameworksBuildPhase;
83 | buildActionMask = 2147483647;
84 | files = (
85 | );
86 | runOnlyForDeploymentPostprocessing = 0;
87 | };
88 | /* End PBXFrameworksBuildPhase section */
89 |
90 | /* Begin PBXGroup section */
91 | 1D53DF021F48343000534C17 /* PureCamerademo */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 1D53DF031F48343000534C17 /* PureCamerademo */,
95 | );
96 | path = PureCamerademo;
97 | sourceTree = "";
98 | };
99 | 1D53DF031F48343000534C17 /* PureCamerademo */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 6C1D93111F48591100AE1102 /* Info.plist */,
103 | 1D53DF041F48343000534C17 /* AppDelegate.h */,
104 | 1D53DF051F48343000534C17 /* AppDelegate.m */,
105 | 1D53DF061F48343000534C17 /* Assets.xcassets */,
106 | 1D53DF071F48343000534C17 /* LaunchScreen.storyboard */,
107 | 1D53DF091F48343000534C17 /* Main.storyboard */,
108 | 1D53DF0B1F48343000534C17 /* main.m */,
109 | 1D53DF0C1F48343000534C17 /* ViewController.h */,
110 | 1D53DF0D1F48343000534C17 /* ViewController.m */,
111 | 6C397B242065003500B3B864 /* KModel.h */,
112 | 6C397B252065003500B3B864 /* KModel.m */,
113 | );
114 | path = PureCamerademo;
115 | sourceTree = "";
116 | };
117 | 1DD4F4F91DDC676600F0D6B0 = {
118 | isa = PBXGroup;
119 | children = (
120 | 6C163CA820AF159700CB5DB0 /* PureCamera */,
121 | 1D53DF021F48343000534C17 /* PureCamerademo */,
122 | 1DD4F5031DDC676600F0D6B0 /* Products */,
123 | );
124 | sourceTree = "";
125 | };
126 | 1DD4F5031DDC676600F0D6B0 /* Products */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 1DD4F5021DDC676600F0D6B0 /* PureCamerademo.app */,
130 | );
131 | name = Products;
132 | sourceTree = "";
133 | };
134 | 6C163CA820AF159700CB5DB0 /* PureCamera */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 6C163CD420AF165B00CB5DB0 /* PureCropVC.h */,
138 | 6C163CD520AF165B00CB5DB0 /* PureCropVC.m */,
139 | 6C163CA920AF159700CB5DB0 /* TOActivityCroppedImageProvider.m */,
140 | 6C163CAA20AF159700CB5DB0 /* TOCropView.h */,
141 | 6C163CAB20AF159700CB5DB0 /* UIImage+CropRotate.m */,
142 | 6C163CAC20AF159700CB5DB0 /* PureCamera.h */,
143 | 6C163CAD20AF159700CB5DB0 /* TOCropViewControllerTransitioning.m */,
144 | 6C163CAE20AF159700CB5DB0 /* LLSimpleCamera+Helper.m */,
145 | 6C163CAF20AF159700CB5DB0 /* TOCropOverlayView.h */,
146 | 6C163CB020AF159700CB5DB0 /* LLSimpleCamera.h */,
147 | 6C163CB120AF159700CB5DB0 /* TOCroppedImageAttributes.m */,
148 | 6C163CB220AF159700CB5DB0 /* PureCamera.bundle */,
149 | 6C163CB320AF159700CB5DB0 /* TOCropToolbar.h */,
150 | 6C163CB420AF159700CB5DB0 /* UIImage+FixOrientation.h */,
151 | 6C163CB520AF159700CB5DB0 /* TOCropScrollView.m */,
152 | 6C163CB620AF159700CB5DB0 /* TOCropViewController.m */,
153 | 6C163CB720AF159700CB5DB0 /* TOCropViewControllerLocalizable.strings */,
154 | 6C163CB820AF159700CB5DB0 /* TOCropView.m */,
155 | 6C163CB920AF159700CB5DB0 /* TOActivityCroppedImageProvider.h */,
156 | 6C163CBA20AF159700CB5DB0 /* TOCropOverlayView.m */,
157 | 6C163CBB20AF159700CB5DB0 /* LLSimpleCamera+Helper.h */,
158 | 6C163CBC20AF159700CB5DB0 /* TOCropViewControllerTransitioning.h */,
159 | 6C163CBD20AF159700CB5DB0 /* PureCamera.m */,
160 | 6C163CBE20AF159700CB5DB0 /* UIImage+CropRotate.h */,
161 | 6C163CBF20AF159700CB5DB0 /* TOCropToolbar.m */,
162 | 6C163CC020AF159700CB5DB0 /* TOCroppedImageAttributes.h */,
163 | 6C163CC120AF159700CB5DB0 /* LLSimpleCamera.m */,
164 | 6C163CC220AF159700CB5DB0 /* TOCropViewController.h */,
165 | 6C163CC320AF159700CB5DB0 /* TOCropScrollView.h */,
166 | 6C163CC420AF159700CB5DB0 /* UIImage+FixOrientation.m */,
167 | );
168 | path = PureCamera;
169 | sourceTree = "";
170 | };
171 | /* End PBXGroup section */
172 |
173 | /* Begin PBXNativeTarget section */
174 | 1DD4F5011DDC676600F0D6B0 /* PureCamerademo */ = {
175 | isa = PBXNativeTarget;
176 | buildConfigurationList = 1DD4F52F1DDC676600F0D6B0 /* Build configuration list for PBXNativeTarget "PureCamerademo" */;
177 | buildPhases = (
178 | 1DD4F4FE1DDC676600F0D6B0 /* Sources */,
179 | 1DD4F4FF1DDC676600F0D6B0 /* Frameworks */,
180 | 1DD4F5001DDC676600F0D6B0 /* Resources */,
181 | );
182 | buildRules = (
183 | );
184 | dependencies = (
185 | );
186 | name = PureCamerademo;
187 | productName = SKFCamerademo;
188 | productReference = 1DD4F5021DDC676600F0D6B0 /* PureCamerademo.app */;
189 | productType = "com.apple.product-type.application";
190 | };
191 | /* End PBXNativeTarget section */
192 |
193 | /* Begin PBXProject section */
194 | 1DD4F4FA1DDC676600F0D6B0 /* Project object */ = {
195 | isa = PBXProject;
196 | attributes = {
197 | LastUpgradeCheck = 0810;
198 | ORGANIZATIONNAME = "五月";
199 | TargetAttributes = {
200 | 1DD4F5011DDC676600F0D6B0 = {
201 | CreatedOnToolsVersion = 8.1;
202 | DevelopmentTeam = AA4YKUFB2C;
203 | ProvisioningStyle = Automatic;
204 | };
205 | };
206 | };
207 | buildConfigurationList = 1DD4F4FD1DDC676600F0D6B0 /* Build configuration list for PBXProject "PureCamerademo" */;
208 | compatibilityVersion = "Xcode 3.2";
209 | developmentRegion = English;
210 | hasScannedForEncodings = 0;
211 | knownRegions = (
212 | English,
213 | en,
214 | Base,
215 | );
216 | mainGroup = 1DD4F4F91DDC676600F0D6B0;
217 | productRefGroup = 1DD4F5031DDC676600F0D6B0 /* Products */;
218 | projectDirPath = "";
219 | projectRoot = "";
220 | targets = (
221 | 1DD4F5011DDC676600F0D6B0 /* PureCamerademo */,
222 | );
223 | };
224 | /* End PBXProject section */
225 |
226 | /* Begin PBXResourcesBuildPhase section */
227 | 1DD4F5001DDC676600F0D6B0 /* Resources */ = {
228 | isa = PBXResourcesBuildPhase;
229 | buildActionMask = 2147483647;
230 | files = (
231 | 6C163CCA20AF159700CB5DB0 /* PureCamera.bundle in Resources */,
232 | 1D53DF0F1F48343000534C17 /* Assets.xcassets in Resources */,
233 | 6C163CCD20AF159700CB5DB0 /* TOCropViewControllerLocalizable.strings in Resources */,
234 | 1D53DF111F48343000534C17 /* Main.storyboard in Resources */,
235 | 1D53DF101F48343000534C17 /* LaunchScreen.storyboard in Resources */,
236 | );
237 | runOnlyForDeploymentPostprocessing = 0;
238 | };
239 | /* End PBXResourcesBuildPhase section */
240 |
241 | /* Begin PBXSourcesBuildPhase section */
242 | 1DD4F4FE1DDC676600F0D6B0 /* Sources */ = {
243 | isa = PBXSourcesBuildPhase;
244 | buildActionMask = 2147483647;
245 | files = (
246 | 6C163CC820AF159700CB5DB0 /* LLSimpleCamera+Helper.m in Sources */,
247 | 6C163CC620AF159700CB5DB0 /* UIImage+CropRotate.m in Sources */,
248 | 6C163CCF20AF159700CB5DB0 /* TOCropOverlayView.m in Sources */,
249 | 1D53DF131F48343000534C17 /* ViewController.m in Sources */,
250 | 6C163CCC20AF159700CB5DB0 /* TOCropViewController.m in Sources */,
251 | 6C163CC920AF159700CB5DB0 /* TOCroppedImageAttributes.m in Sources */,
252 | 6C163CD220AF159700CB5DB0 /* LLSimpleCamera.m in Sources */,
253 | 6C163CD020AF159700CB5DB0 /* PureCamera.m in Sources */,
254 | 6C163CC720AF159700CB5DB0 /* TOCropViewControllerTransitioning.m in Sources */,
255 | 1D53DF121F48343000534C17 /* main.m in Sources */,
256 | 6C397B262065003600B3B864 /* KModel.m in Sources */,
257 | 6C163CD320AF159700CB5DB0 /* UIImage+FixOrientation.m in Sources */,
258 | 1D53DF0E1F48343000534C17 /* AppDelegate.m in Sources */,
259 | 6C163CCE20AF159700CB5DB0 /* TOCropView.m in Sources */,
260 | 6C163CCB20AF159700CB5DB0 /* TOCropScrollView.m in Sources */,
261 | 6C163CC520AF159700CB5DB0 /* TOActivityCroppedImageProvider.m in Sources */,
262 | 6C163CD620AF165B00CB5DB0 /* PureCropVC.m in Sources */,
263 | 6C163CD120AF159700CB5DB0 /* TOCropToolbar.m in Sources */,
264 | );
265 | runOnlyForDeploymentPostprocessing = 0;
266 | };
267 | /* End PBXSourcesBuildPhase section */
268 |
269 | /* Begin PBXVariantGroup section */
270 | 1D53DF071F48343000534C17 /* LaunchScreen.storyboard */ = {
271 | isa = PBXVariantGroup;
272 | children = (
273 | 1D53DF081F48343000534C17 /* Base */,
274 | );
275 | name = LaunchScreen.storyboard;
276 | sourceTree = "";
277 | };
278 | 1D53DF091F48343000534C17 /* Main.storyboard */ = {
279 | isa = PBXVariantGroup;
280 | children = (
281 | 1D53DF0A1F48343000534C17 /* Base */,
282 | );
283 | name = Main.storyboard;
284 | sourceTree = "";
285 | };
286 | /* End PBXVariantGroup section */
287 |
288 | /* Begin XCBuildConfiguration section */
289 | 1DD4F52D1DDC676600F0D6B0 /* Debug */ = {
290 | isa = XCBuildConfiguration;
291 | buildSettings = {
292 | ALWAYS_SEARCH_USER_PATHS = NO;
293 | CLANG_ANALYZER_NONNULL = YES;
294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
295 | CLANG_CXX_LIBRARY = "libc++";
296 | CLANG_ENABLE_MODULES = YES;
297 | CLANG_ENABLE_OBJC_ARC = YES;
298 | CLANG_WARN_BOOL_CONVERSION = YES;
299 | CLANG_WARN_CONSTANT_CONVERSION = YES;
300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
301 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
302 | CLANG_WARN_EMPTY_BODY = YES;
303 | CLANG_WARN_ENUM_CONVERSION = YES;
304 | CLANG_WARN_INFINITE_RECURSION = YES;
305 | CLANG_WARN_INT_CONVERSION = YES;
306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
307 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
308 | CLANG_WARN_UNREACHABLE_CODE = YES;
309 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
310 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
311 | COPY_PHASE_STRIP = NO;
312 | DEBUG_INFORMATION_FORMAT = dwarf;
313 | ENABLE_STRICT_OBJC_MSGSEND = YES;
314 | ENABLE_TESTABILITY = YES;
315 | FRAMEWORK_SEARCH_PATHS = "";
316 | GCC_C_LANGUAGE_STANDARD = gnu99;
317 | GCC_DYNAMIC_NO_PIC = NO;
318 | GCC_NO_COMMON_BLOCKS = YES;
319 | GCC_OPTIMIZATION_LEVEL = 0;
320 | GCC_PREPROCESSOR_DEFINITIONS = (
321 | "DEBUG=1",
322 | "$(inherited)",
323 | );
324 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
325 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
326 | GCC_WARN_UNDECLARED_SELECTOR = YES;
327 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
328 | GCC_WARN_UNUSED_FUNCTION = YES;
329 | GCC_WARN_UNUSED_VARIABLE = YES;
330 | IPHONEOS_DEPLOYMENT_TARGET = 10.1;
331 | MTL_ENABLE_DEBUG_INFO = YES;
332 | ONLY_ACTIVE_ARCH = YES;
333 | SDKROOT = iphoneos;
334 | };
335 | name = Debug;
336 | };
337 | 1DD4F52E1DDC676600F0D6B0 /* Release */ = {
338 | isa = XCBuildConfiguration;
339 | buildSettings = {
340 | ALWAYS_SEARCH_USER_PATHS = NO;
341 | CLANG_ANALYZER_NONNULL = YES;
342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
343 | CLANG_CXX_LIBRARY = "libc++";
344 | CLANG_ENABLE_MODULES = YES;
345 | CLANG_ENABLE_OBJC_ARC = YES;
346 | CLANG_WARN_BOOL_CONVERSION = YES;
347 | CLANG_WARN_CONSTANT_CONVERSION = YES;
348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
349 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
350 | CLANG_WARN_EMPTY_BODY = YES;
351 | CLANG_WARN_ENUM_CONVERSION = YES;
352 | CLANG_WARN_INFINITE_RECURSION = YES;
353 | CLANG_WARN_INT_CONVERSION = YES;
354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
355 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
356 | CLANG_WARN_UNREACHABLE_CODE = YES;
357 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
358 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
359 | COPY_PHASE_STRIP = NO;
360 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
361 | ENABLE_NS_ASSERTIONS = NO;
362 | ENABLE_STRICT_OBJC_MSGSEND = YES;
363 | FRAMEWORK_SEARCH_PATHS = "";
364 | GCC_C_LANGUAGE_STANDARD = gnu99;
365 | GCC_NO_COMMON_BLOCKS = YES;
366 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
367 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
368 | GCC_WARN_UNDECLARED_SELECTOR = YES;
369 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
370 | GCC_WARN_UNUSED_FUNCTION = YES;
371 | GCC_WARN_UNUSED_VARIABLE = YES;
372 | IPHONEOS_DEPLOYMENT_TARGET = 10.1;
373 | MTL_ENABLE_DEBUG_INFO = NO;
374 | SDKROOT = iphoneos;
375 | VALIDATE_PRODUCT = YES;
376 | };
377 | name = Release;
378 | };
379 | 1DD4F5301DDC676600F0D6B0 /* Debug */ = {
380 | isa = XCBuildConfiguration;
381 | buildSettings = {
382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
383 | CODE_SIGN_IDENTITY = "iPhone Developer";
384 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
385 | CODE_SIGN_STYLE = Automatic;
386 | DEVELOPMENT_TEAM = AA4YKUFB2C;
387 | FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks";
388 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
389 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
390 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
391 | PRODUCT_BUNDLE_IDENTIFIER = s.PureCamerademo;
392 | PRODUCT_NAME = "$(TARGET_NAME)";
393 | PROVISIONING_PROFILE_SPECIFIER = "";
394 | };
395 | name = Debug;
396 | };
397 | 1DD4F5311DDC676600F0D6B0 /* Release */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
401 | CODE_SIGN_IDENTITY = "iPhone Developer";
402 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
403 | CODE_SIGN_STYLE = Automatic;
404 | DEVELOPMENT_TEAM = AA4YKUFB2C;
405 | FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks";
406 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
407 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
408 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
409 | PRODUCT_BUNDLE_IDENTIFIER = s.PureCamerademo;
410 | PRODUCT_NAME = "$(TARGET_NAME)";
411 | PROVISIONING_PROFILE_SPECIFIER = "";
412 | };
413 | name = Release;
414 | };
415 | /* End XCBuildConfiguration section */
416 |
417 | /* Begin XCConfigurationList section */
418 | 1DD4F4FD1DDC676600F0D6B0 /* Build configuration list for PBXProject "PureCamerademo" */ = {
419 | isa = XCConfigurationList;
420 | buildConfigurations = (
421 | 1DD4F52D1DDC676600F0D6B0 /* Debug */,
422 | 1DD4F52E1DDC676600F0D6B0 /* Release */,
423 | );
424 | defaultConfigurationIsVisible = 0;
425 | defaultConfigurationName = Release;
426 | };
427 | 1DD4F52F1DDC676600F0D6B0 /* Build configuration list for PBXNativeTarget "PureCamerademo" */ = {
428 | isa = XCConfigurationList;
429 | buildConfigurations = (
430 | 1DD4F5301DDC676600F0D6B0 /* Debug */,
431 | 1DD4F5311DDC676600F0D6B0 /* Release */,
432 | );
433 | defaultConfigurationIsVisible = 0;
434 | defaultConfigurationName = Release;
435 | };
436 | /* End XCConfigurationList section */
437 | };
438 | rootObject = 1DD4F4FA1DDC676600F0D6B0 /* Project object */;
439 | }
440 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/project.xcworkspace/xcuserdata/shiyue.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamerademo.xcodeproj/project.xcworkspace/xcuserdata/shiyue.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/project.xcworkspace/xcuserdata/sunkaifeng.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamerademo.xcodeproj/project.xcworkspace/xcuserdata/sunkaifeng.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/xcuserdata/shiyue.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/xcuserdata/shiyue.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | PureCamerademo.xcscheme
8 |
9 | isShown
10 |
11 | orderHint
12 | 1
13 |
14 |
15 | SuppressBuildableAutocreation
16 |
17 | 1DD4F5011DDC676600F0D6B0
18 |
19 | primary
20 |
21 |
22 | 1DD4F51A1DDC676600F0D6B0
23 |
24 | primary
25 |
26 |
27 | 1DD4F5251DDC676600F0D6B0
28 |
29 | primary
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/xcuserdata/sunkaifeng.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
18 |
24 |
25 |
26 |
27 |
28 |
30 |
42 |
43 |
44 |
46 |
58 |
59 |
60 |
62 |
74 |
75 |
76 |
78 |
90 |
91 |
92 |
94 |
106 |
107 |
108 |
110 |
122 |
123 |
124 |
126 |
138 |
139 |
140 |
142 |
154 |
155 |
156 |
158 |
170 |
171 |
172 |
174 |
186 |
187 |
188 |
190 |
202 |
203 |
204 |
206 |
218 |
219 |
220 |
222 |
234 |
235 |
236 |
238 |
250 |
251 |
252 |
254 |
266 |
267 |
268 |
270 |
282 |
283 |
284 |
286 |
298 |
299 |
300 |
302 |
314 |
315 |
316 |
318 |
330 |
331 |
332 |
334 |
346 |
347 |
348 |
350 |
362 |
363 |
364 |
366 |
378 |
379 |
380 |
382 |
394 |
395 |
396 |
398 |
410 |
411 |
412 |
414 |
426 |
427 |
428 |
430 |
442 |
443 |
444 |
446 |
458 |
459 |
460 |
462 |
474 |
475 |
476 |
478 |
490 |
491 |
492 |
494 |
506 |
507 |
508 |
510 |
522 |
523 |
524 |
526 |
538 |
539 |
540 |
542 |
554 |
555 |
556 |
558 |
570 |
571 |
572 |
574 |
586 |
587 |
588 |
590 |
602 |
603 |
604 |
606 |
618 |
619 |
620 |
621 |
622 |
--------------------------------------------------------------------------------
/PureCamerademo.xcodeproj/xcuserdata/sunkaifeng.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | PureCamerademo.xcscheme
8 |
9 | orderHint
10 | 1
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 1DD4F5011DDC676600F0D6B0
16 |
17 | primary
18 |
19 |
20 | 1DD4F51A1DDC676600F0D6B0
21 |
22 | primary
23 |
24 |
25 | 1DD4F5251DDC676600F0D6B0
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // PureCamerademo
4 | //
5 | // Created by 孙凯峰 on 2016/11/16.
6 | // Copyright © 2016年 孙凯峰. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // PureCamerademo
4 | //
5 | // Created by 孙凯峰 on 2016/11/16.
6 | // Copyright © 2016年 孙凯峰. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/1.imageset/C8AECEE3EC242CAA4442358F3D912F9A.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamerademo/PureCamerademo/Assets.xcassets/1.imageset/C8AECEE3EC242CAA4442358F3D912F9A.jpg
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "C8AECEE3EC242CAA4442358F3D912F9A.jpg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "FE00349D152834B01E38D3F64A9D1217.jpg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/2.imageset/FE00349D152834B01E38D3F64A9D1217.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wubianxiaoxian/PureCamera-Demo/31a8a0970774561ceab0b29c7829388ee802f992/PureCamerademo/PureCamerademo/Assets.xcassets/2.imageset/FE00349D152834B01E38D3F64A9D1217.jpg
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
29 |
30 |
31 |
32 |
33 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/KModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // KModel.h
3 | // PureCamerademo
4 | //
5 | // Created by 五月 on 2018/3/23.
6 | // Copyright © 2018年 五月. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface KModel : NSObject
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/KModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // KModel.m
3 | // PureCamerademo
4 | //
5 | // Created by 五月 on 2018/3/23.
6 | // Copyright © 2018年 五月. All rights reserved.
7 | //
8 |
9 | #import "KModel.h"
10 |
11 | @implementation KModel
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // PureCamerademo
4 | //
5 | // Created by 孙凯峰 on 2016/11/16.
6 | // Copyright © 2016年 孙凯峰. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // PureCamerademo
4 | //
5 | // Created by 孙凯峰 on 2016/11/16.
6 | // Copyright © 2016年 孙凯峰. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "PureCamera.h"
11 | #import "TOCropViewController.h"
12 | #import "PureCropVC.h"
13 | @interface ViewController ()
14 |
15 | - (IBAction)pushCameraclick:(id)sender;
16 | @property (weak, nonatomic) IBOutlet UIImageView *Kimageview;
17 | - (IBAction)pushCropClick:(id)sender;
18 | @property (weak, nonatomic) IBOutlet UIImageView *cropImageview;
19 |
20 | @end
21 |
22 | @implementation ViewController
23 |
24 | - (void)viewDidLoad {
25 | [super viewDidLoad];
26 | }
27 |
28 |
29 | - (void)didReceiveMemoryWarning {
30 | [super didReceiveMemoryWarning];
31 | // Dispose of any resources that can be recreated.
32 | }
33 |
34 | - (IBAction)pushCameraclick:(id)sender {
35 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
36 | PureCamera *homec = [[PureCamera alloc] init];
37 | __weak typeof(self) myself = self;
38 | homec.fininshcapture = ^(UIImage *ss) {
39 | if (ss) {
40 | NSLog(@"照片存在");
41 | myself.Kimageview.image = ss;
42 | }
43 | };
44 | [myself presentViewController:homec
45 | animated:NO
46 | completion:^{
47 | }];
48 | } else {
49 | NSLog(@"相机调用失败");
50 | }
51 | }
52 | - (IBAction)pushCropClick:(id)sender {
53 | // self.cropImageview.image
54 |
55 | PureCropVC *vc = [[PureCropVC alloc]initWithImage:self.cropImageview.image aspectRatioStle:TOCropViewControllerAspectRatioSquare];
56 | vc.delegate = self;
57 |
58 | [self presentViewController:vc animated:YES completion:nil];
59 | }
60 | - (void)cropViewController:(TOCropViewController *)cropViewController
61 | didCropToImage:(UIImage *)image
62 | withRect:(CGRect)cropRect
63 | angle:(NSInteger)angle {
64 |
65 | self.cropImageview.image = image;
66 | self.navigationItem.rightBarButtonItem.enabled = YES;
67 | CGRect viewFrame = [self.view convertRect:self.cropImageview.frame toView:self.navigationController.view];
68 | [cropViewController dismissAnimatedFromParentViewController:self
69 | withCroppedImage:image
70 | toFrame:viewFrame
71 | completion:^{
72 | }];
73 | NSLog(@"最后");
74 | }
75 | @end
76 |
--------------------------------------------------------------------------------
/PureCamerademo/PureCamerademo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // PureCamerademo
4 | //
5 | // Created by 孙凯峰 on 2016/11/16.
6 | // Copyright © 2016年 孙凯峰. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PureCamera
2 | =
3 |
4 |
5 | [](https://travis-ci.org/wubianxiaoxian/PureCamera)
6 | [](http://cocoapods.org/pods/PureCamera)
7 | [](http://cocoapods.org/pods/PureCamera)
8 | [](http://cocoapods.org/pods/PureCamera)
9 |
10 |
11 |
12 | A custom camera that allows for free cropping of photos upon completion
13 | ----
14 |
15 | Requirements
16 | ----
17 |
18 | * Xcode 8 or higher
19 | * iOS 8.0 or higher
20 | * ARC
21 |
22 | Version
23 | ----
24 |
25 | * 1.6.3
26 |
27 | Usage
28 | ----
29 |
30 | * Installation with CocoaPods: pod 'PureCamera', import
31 |
32 | ```objc
33 | #import
34 | ```
35 |
36 | * Or download the demo locally and add PureCamera to your project, import
37 |
38 | ```objc
39 | #import "PureCamera.h"
40 | ```
41 |
42 | * Add the following to info.plist
43 |
44 | ```objc
45 | Privacy - Camera Usage Description Use camera
46 | ```
47 |
48 | * Use the following method to call the camera
49 |
50 | ```objc
51 | PureCamera *homec=[[PureCamera alloc]init];
52 | __weak typeof(self)myself=self;
53 | homec.fininshcapture=^(UIImage *ss){
54 | if (ss) {
55 | NSLog(@"Photo exists");
56 | //Here you can get the cropped photo
57 | myself.ViewImageview.image=ss;
58 | }
59 | } ;
60 | [self presentViewController:homec animated:NO completion:^{}];}
61 | ```
62 |
63 | * Use the following method to call the image cropping page
64 |
65 | ```objc
66 | First import #import "TOCropViewController.h"
67 | Adhere to @interface ViewController()
68 | Pass in an image and you can present the image cropping page
69 |
70 | TOCropViewController *cropController = [[TOCropViewController alloc] initWithImage:self.cropImageview.image];
71 | cropController.delegate = self;
72 | [self presentViewController:cropController animated:YES completion:nil];
73 |
74 | - (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
75 | {
76 | self.cropImageview.image=image;
77 | self.navigationItem.rightBarButtonItem.enabled = YES;
78 | //The following defines an animation effect, which is that when the image cropping page disappears, it will use the frame of the view you defined as the boundary after the disappearance.
79 | CGRect viewFrame = [self.view convertRect:self.cropImageview.frame toView:self.navigationController.view];
80 | [cropViewController dismissAnimatedFromParentViewController:self withCroppedImage:image toFrame:viewFrame completion:^{
81 | }];
82 | }
83 | ```
84 |
85 |
86 | 
87 |
88 | If you encounter any problems during use, please feel free to submit an issue.
89 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Xcode
2 | # Build, test, and archive an Xcode workspace on macOS.
3 | # Add steps that install certificates, test, sign, and distribute an app, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/xcode
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'macos-latest'
11 |
12 | steps:
13 | - task: Xcode@5
14 | inputs:
15 | actions: 'build'
16 | scheme: ''
17 | sdk: 'iphoneos'
18 | configuration: 'Release'
19 | xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
20 | xcodeVersion: 'default' # Options: 8, 9, 10, default, specifyPath
21 |
--------------------------------------------------------------------------------