Преглед изворни кода

1.修改照片预览界面,实现截图。

Pen Li пре 9 година
родитељ
комит
e66585362e

BIN
RA Image/RA Image.xcodeproj/project.xcworkspace/xcuserdata/macmini1.xcuserdatad/UserInterfaceState.xcuserstate


+ 33 - 26
RA Image/RA Image/BasicModeViewController.m

@@ -158,41 +158,43 @@
 //    [self presentViewController:imgPicker animated:YES completion:nil];
 
     
+    CGFloat w = CGRectGetWidth(self.view.frame);
+    CGFloat h = CGRectGetHeight(self.view.frame);
     // 自定义相机控制视图
     UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
     imgPicker.delegate = self;
     imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
     imgPicker.allowsEditing = NO;
     imgPicker.showsCameraControls  = NO;
-    UIView* overlay = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 150 , self.view.frame.size.width, 150)];
+    UIView* overlay = [[UIView alloc]initWithFrame:CGRectMake(0, h - 150 , w, 150)];
 
     // Cancel
     UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
-    cancelBtn.frame = CGRectMake(10, 10, 60, 40);
+    cancelBtn.frame = CGRectMake(20, (150 - 40) * 0.5, 60, 40);
     [cancelBtn setTitle:@"cancel" forState:UIControlStateNormal];
     [cancelBtn addTarget:self action:@selector(cancelCameraClick:) forControlEvents:UIControlEventTouchUpInside];
     [overlay addSubview:cancelBtn];
     
     // Take
     UIButton *takeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
-    takeBtn.frame = CGRectMake(80, 10, 60, 40);
+    takeBtn.frame = CGRectMake((w - 60) * 0.5, (150 - 40) * 0.5, 60, 40);
     [takeBtn setTitle:@"take" forState:UIControlStateNormal];
     [takeBtn addTarget:self action:@selector(takePhotoClick:) forControlEvents:UIControlEventTouchUpInside];
     [overlay addSubview:takeBtn];
     
     // flash
     UIButton *flashBtn = [UIButton buttonWithType:UIButtonTypeCustom];
-    flashBtn.frame = CGRectMake(150, 10, 60, 40);
+    flashBtn.frame = CGRectMake(w - 80, (150 - 40) * 0.5, 60, 40);
     [flashBtn setTitle:@"Auto" forState:UIControlStateNormal];
     [flashBtn addTarget:self action:@selector(flashBtnClick:) forControlEvents:UIControlEventTouchUpInside];
     [overlay addSubview:flashBtn];
     
-    // camera
-    UIButton *cameraChangeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
-    cameraChangeBtn.frame = CGRectMake(220, 10, 60, 40);
-    [cameraChangeBtn setTitle:@"change" forState:UIControlStateNormal];
-    [cameraChangeBtn addTarget:self action:@selector(cameraChangeClick:) forControlEvents:UIControlEventTouchUpInside];
-    [overlay addSubview:cameraChangeBtn];
+//    // camera
+//    UIButton *cameraChangeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+//    cameraChangeBtn.frame = CGRectMake(220, 10, 60, 40);
+//    [cameraChangeBtn setTitle:@"change" forState:UIControlStateNormal];
+//    [cameraChangeBtn addTarget:self action:@selector(cameraChangeClick:) forControlEvents:UIControlEventTouchUpInside];
+//    [overlay addSubview:cameraChangeBtn];
     
     
     // 相机属性设置得在设置SourceType后设置
@@ -414,22 +416,27 @@
     TakePhotoPreviewController *preVC = (TakePhotoPreviewController *)[self viewControllerInStoryboard:@"Mode" withId:@"TakePhotoPreviewController"];
     preVC.photoHandler = ^(UIImage *img){
         if (img) {
-            NSString *path = [weakself saveImage:img];
-            if (path) {// 保存成功
-                [weakself receiveImage:img];
-                NSString *md5 = [RAUtils md5WithFile:path];
-                NSMutableDictionary *photoDic = @{
-                                                  @"photo" : img,
-                                                  @"check" : @(NO),
-                                                  @"file"  : [path lastPathComponent],
-                                                  @"md5"   : md5,
-                                                  @"path"  : path
-                                                  }.mutableCopy;
-                [weakself.photos addObject:photoDic];
-                weakself.photoCount++;
-            } else {
-                [RAUtils message_alert:@"Save photo failed" title:@"Warning" controller:weakself];
-            }
+            dispatch_async(dispatch_get_global_queue(0, 0), ^{
+                NSString *path = [weakself saveImage:img];
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    if (path) {// 保存成功
+                        [weakself receiveImage:img];
+                        NSString *md5 = [RAUtils md5WithFile:path];
+                        NSMutableDictionary *photoDic = @{
+                                                          @"photo" : img,
+                                                          @"check" : @(NO),
+                                                          @"file"  : [path lastPathComponent],
+                                                          @"md5"   : md5,
+                                                          @"path"  : path
+                                                          }.mutableCopy;
+                        [weakself.photos addObject:photoDic];
+                        weakself.photoCount++;
+                    } else {
+                        [RAUtils message_alert:@"Save photo failed" title:@"Warning" controller:weakself];
+                    }
+                });
+
+            });
         }
     };
     preVC.preImage = image;

+ 53 - 29
RA Image/RA Image/Mode.storyboard

@@ -788,7 +788,7 @@
         <!--Take Photo Preview Controller-->
         <scene sceneID="Y3z-vH-wec">
             <objects>
-                <viewController storyboardIdentifier="TakePhotoPreviewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="533-wD-Chz" customClass="TakePhotoPreviewController" sceneMemberID="viewController">
+                <viewController storyboardIdentifier="TakePhotoPreviewController" automaticallyAdjustsScrollViewInsets="NO" useStoryboardIdentifierAsRestorationIdentifier="YES" id="533-wD-Chz" customClass="TakePhotoPreviewController" sceneMemberID="viewController">
                     <layoutGuides>
                         <viewControllerLayoutGuide type="top" id="SXM-WT-Q0L"/>
                         <viewControllerLayoutGuide type="bottom" id="68i-cD-6Ue"/>
@@ -797,42 +797,66 @@
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
-                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ecC-0F-hpb">
-                                <rect key="frame" x="67" y="199.5" width="240" height="268"/>
-                                <constraints>
-                                    <constraint firstAttribute="height" constant="268" id="D2w-f4-cYc"/>
-                                    <constraint firstAttribute="width" constant="240" id="D4j-Dz-Y8H"/>
-                                </constraints>
-                            </imageView>
-                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aIO-Rg-abl">
-                                <rect key="frame" x="16" y="617" width="47" height="30"/>
-                                <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                                <state key="normal" title="Retake"/>
-                                <connections>
-                                    <action selector="retakeBtnClick:" destination="533-wD-Chz" eventType="touchUpInside" id="DIM-kU-L5E"/>
-                                </connections>
-                            </button>
-                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Khf-Lc-MrL">
-                                <rect key="frame" x="287" y="617" width="72" height="30"/>
-                                <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                                <state key="normal" title="Use Photo"/>
+                            <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" maximumZoomScale="4" translatesAutoresizingMaskIntoConstraints="NO" id="BHi-a9-hom">
+                                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                                 <connections>
-                                    <action selector="usePhotoClick:" destination="533-wD-Chz" eventType="touchUpInside" id="S8B-QZ-ZyV"/>
+                                    <outlet property="delegate" destination="533-wD-Chz" id="K2H-WI-nD1"/>
                                 </connections>
-                            </button>
+                            </scrollView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ySP-Oj-Ybt">
+                                <rect key="frame" x="1" y="90" width="373" height="415"/>
+                            </view>
+                            <view alpha="0.45000000000000001" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OPr-J2-wJK">
+                                <rect key="frame" x="0.0" y="605" width="375" height="62"/>
+                                <subviews>
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aIO-Rg-abl">
+                                        <rect key="frame" x="20" y="16" width="47" height="30"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                        <state key="normal" title="Retake"/>
+                                        <connections>
+                                            <action selector="retakeBtnClick:" destination="533-wD-Chz" eventType="touchUpInside" id="DIM-kU-L5E"/>
+                                        </connections>
+                                    </button>
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Khf-Lc-MrL">
+                                        <rect key="frame" x="283" y="16" width="72" height="30"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                        <state key="normal" title="Use Photo"/>
+                                        <connections>
+                                            <action selector="usePhotoClick:" destination="533-wD-Chz" eventType="touchUpInside" id="S8B-QZ-ZyV"/>
+                                        </connections>
+                                    </button>
+                                </subviews>
+                                <color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="62" id="9bL-uN-DEB"/>
+                                    <constraint firstItem="aIO-Rg-abl" firstAttribute="leading" secondItem="OPr-J2-wJK" secondAttribute="leading" constant="20" id="AU1-ey-GMx"/>
+                                    <constraint firstAttribute="trailing" secondItem="Khf-Lc-MrL" secondAttribute="trailing" constant="20" id="Hfc-ZN-mhQ"/>
+                                    <constraint firstItem="aIO-Rg-abl" firstAttribute="centerY" secondItem="OPr-J2-wJK" secondAttribute="centerY" id="dDA-aJ-a1e"/>
+                                    <constraint firstItem="Khf-Lc-MrL" firstAttribute="centerY" secondItem="OPr-J2-wJK" secondAttribute="centerY" id="xP8-gE-6YZ"/>
+                                </constraints>
+                            </view>
                         </subviews>
                         <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
                         <constraints>
-                            <constraint firstItem="68i-cD-6Ue" firstAttribute="top" secondItem="Khf-Lc-MrL" secondAttribute="bottom" constant="20" id="2DH-lZ-PG6"/>
-                            <constraint firstItem="ecC-0F-hpb" firstAttribute="centerX" secondItem="37H-ep-vSP" secondAttribute="centerX" id="ISv-PL-6GF"/>
-                            <constraint firstItem="68i-cD-6Ue" firstAttribute="top" secondItem="aIO-Rg-abl" secondAttribute="bottom" constant="20" id="TlD-Jd-Qr8"/>
-                            <constraint firstAttribute="leadingMargin" secondItem="aIO-Rg-abl" secondAttribute="leading" id="agS-1R-OBr"/>
-                            <constraint firstAttribute="trailingMargin" secondItem="Khf-Lc-MrL" secondAttribute="trailing" id="dRr-MK-ldy"/>
-                            <constraint firstItem="ecC-0F-hpb" firstAttribute="centerY" secondItem="37H-ep-vSP" secondAttribute="centerY" id="tCv-uB-y49"/>
+                            <constraint firstItem="OPr-J2-wJK" firstAttribute="leading" secondItem="37H-ep-vSP" secondAttribute="leading" id="0NV-Mc-ysQ"/>
+                            <constraint firstItem="68i-cD-6Ue" firstAttribute="top" secondItem="OPr-J2-wJK" secondAttribute="bottom" id="7fq-M7-WmB"/>
+                            <constraint firstItem="ySP-Oj-Ybt" firstAttribute="leading" secondItem="37H-ep-vSP" secondAttribute="leading" constant="1" id="BGL-ry-bXi"/>
+                            <constraint firstItem="BHi-a9-hom" firstAttribute="leading" secondItem="37H-ep-vSP" secondAttribute="leading" id="LwH-kQ-7Lu"/>
+                            <constraint firstItem="68i-cD-6Ue" firstAttribute="top" secondItem="BHi-a9-hom" secondAttribute="bottom" id="ODm-bF-jag"/>
+                            <constraint firstItem="ySP-Oj-Ybt" firstAttribute="top" secondItem="SXM-WT-Q0L" secondAttribute="bottom" constant="90" id="cys-xZ-Lmc"/>
+                            <constraint firstItem="OPr-J2-wJK" firstAttribute="top" secondItem="ySP-Oj-Ybt" secondAttribute="bottom" constant="100" id="fkG-cJ-3ZE"/>
+                            <constraint firstItem="BHi-a9-hom" firstAttribute="top" secondItem="SXM-WT-Q0L" secondAttribute="bottom" id="hiL-HZ-9TR"/>
+                            <constraint firstAttribute="trailing" secondItem="BHi-a9-hom" secondAttribute="trailing" id="jNH-U9-1Sg"/>
+                            <constraint firstAttribute="trailing" secondItem="OPr-J2-wJK" secondAttribute="trailing" id="kEK-0P-eZo"/>
+                            <constraint firstAttribute="trailing" secondItem="ySP-Oj-Ybt" secondAttribute="trailing" constant="1" id="rGT-Ty-hAe"/>
                         </constraints>
                     </view>
+                    <nil key="simulatedStatusBarMetrics"/>
+                    <nil key="simulatedTopBarMetrics"/>
+                    <nil key="simulatedBottomBarMetrics"/>
                     <connections>
-                        <outlet property="previewImageView" destination="ecC-0F-hpb" id="MzG-PN-Sci"/>
+                        <outlet property="editContainer" destination="ySP-Oj-Ybt" id="Oxq-tv-RdU"/>
+                        <outlet property="previewScroll" destination="BHi-a9-hom" id="ZG5-gt-Nqd"/>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="RP8-jW-gRB" userLabel="First Responder" sceneMemberID="firstResponder"/>

+ 107 - 4
RA Image/RA Image/TakePhotoPreviewController.m

@@ -8,9 +8,12 @@
 
 #import "TakePhotoPreviewController.h"
 
-@interface TakePhotoPreviewController ()
+@interface TakePhotoPreviewController ()<UIScrollViewDelegate>
 
-@property (strong, nonatomic) IBOutlet UIImageView *previewImageView;
+@property (strong, nonatomic) IBOutlet UIScrollView *previewScroll;
+@property (strong, nonatomic) IBOutlet UIView *editContainer;
+
+@property (nonatomic,strong) UIImageView *imgView;
 
 @end
 
@@ -19,8 +22,25 @@
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
+    [self.view insertSubview:[UIView new] atIndex:0];
+    
+    self.editContainer.layer.borderColor = [UIColor whiteColor].CGColor;
+    self.editContainer.layer.borderWidth = 0.5f;
+    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewPinch:)];
+    [self.editContainer addGestureRecognizer:pinch];
+    
+    [self.previewScroll addSubview:self.imgView];
+}
+
+- (void)viewDidLayoutSubviews {
+    [super viewDidLayoutSubviews];
+    
+    self.imgView.frame = CGRectMake(0, 70, CGRectGetWidth(self.previewScroll.frame), CGRectGetHeight(self.previewScroll.frame) - 150);
     
-    self.previewImageView.image = self.preImage;
+}
+
+- (BOOL)prefersStatusBarHidden {
+    return YES;
 }
 
 - (void)didReceiveMemoryWarning {
@@ -28,6 +48,39 @@
     // Dispose of any resources that can be recreated.
 }
 
+- (UIImageView *)imgView {
+    if (!_imgView) {
+        _imgView = [[UIImageView alloc] initWithImage:self.preImage];
+        _imgView.userInteractionEnabled = YES;
+        
+    }
+    return _imgView;
+}
+
+- (UIImage *)captureImageInView:(UIView *)view {
+    UIImage *img = nil;
+    
+//    UIGraphicsBeginImageContext(view.frame.size);
+    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [UIScreen mainScreen].scale);
+    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
+    img = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    
+    return img;
+}
+
+- (UIImage *)captureImageWithImage:(UIImage *)image inRect:(CGRect)rect {
+    CGFloat scale = [UIScreen mainScreen].scale;
+    rect.origin.x *= scale;
+    rect.origin.y *= scale;
+    rect.size.height *= scale;
+    rect.size.width *= scale;
+    CGImageRef imgRef = CGImageCreateWithImageInRect(image.CGImage, rect);
+    UIImage *img = [UIImage imageWithCGImage:imgRef];
+    CGImageRelease(imgRef);
+    return img;
+}
+
 - (IBAction)retakeBtnClick:(UIButton *)sender {
     if (self.photoHandler) {
         self.photoHandler(nil);
@@ -37,10 +90,60 @@
 
 - (IBAction)usePhotoClick:(UIButton *)sender {
     if (self.photoHandler) {
-        self.photoHandler(self.preImage);
+        UIImage *img = [self captureImageInView:self.view];
+        img = [self captureImageWithImage:img inRect:self.editContainer.frame];
+        self.photoHandler(img);
     }
     [self.navigationController popViewControllerAnimated:YES];
 }
 
+#pragma mark - UIScrollViewDelegate
+
+//- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
+//    return self.imgView;
+//}
+
+#pragma mark - pinch
+
+- (void)imageViewPinch:(UIPinchGestureRecognizer *)pinch{
+    
+    UIScrollView *scroll = self.previewScroll;
+    UIImageView *imgv = [scroll.subviews firstObject];
+    
+    CGFloat width = scroll.frame.size.width;
+    CGFloat height = scroll.frame.size.height;
+    
+    imgv.transform = CGAffineTransformScale(imgv.transform, pinch.scale, pinch.scale);
+    CGSize size = scroll.contentSize;
+    //    size.width = size.width * pinch.scale;
+    //    size.height = size.height * pinch.scale;
+    size = imgv.frame.size;// bounds 和 frame 不一致
+    CGSize itemSize = self.editContainer.frame.size;
+    
+    if (size.height < itemSize.height || size.width < itemSize.width) { // 禁止缩小得比原图小
+        imgv.transform = CGAffineTransformIdentity;
+        size = imgv.frame.size;
+    }
+    
+    
+//    if (size.width < width) {
+//        size.width = width;
+//    }
+//    if (size.height < height) {
+//        size.height = height;
+//    }
+    
+    scroll.contentSize = size;
+    scroll.contentOffset = CGPointMake((size.width - width) * 0.5, (size.height - height) * 0.5);
+    // 保持在屏幕中心
+    CGPoint offset = scroll.contentOffset;
+    CGFloat x = offset.x + width * 0.5;
+    CGFloat y = offset.y + height * 0.5;
+    imgv.center = CGPointMake(x, y);
+    
+    pinch.scale = 1;
+}
+
+
 
 @end