Commit d134b88a3685ed4356389269733402c758bd8d1c
1 parent
cc3abe0e
提交编写测试工程
Showing
16 changed files
with
1578 additions
and
7 deletions
CNLiveScanGoodsCamera.podspec
| @@ -30,7 +30,7 @@ TODO: Add long description of the pod here. | @@ -30,7 +30,7 @@ TODO: Add long description of the pod here. | ||
| 30 | 30 | ||
| 31 | s.ios.deployment_target = '8.0' | 31 | s.ios.deployment_target = '8.0' |
| 32 | 32 | ||
| 33 | - s.source_files = 'CNLiveScanGoodsCamera/Classes/**/*' | 33 | + s.source_files = 'CNLiveScanGoodsCamera/Classes/*.{h,m}' |
| 34 | 34 | ||
| 35 | # s.resource_bundles = { | 35 | # s.resource_bundles = { |
| 36 | # 'CNLiveScanGoodsCamera' => ['CNLiveScanGoodsCamera/Assets/*.png'] | 36 | # 'CNLiveScanGoodsCamera' => ['CNLiveScanGoodsCamera/Assets/*.png'] |
| @@ -38,5 +38,7 @@ TODO: Add long description of the pod here. | @@ -38,5 +38,7 @@ TODO: Add long description of the pod here. | ||
| 38 | 38 | ||
| 39 | # s.public_header_files = 'Pod/Classes/**/*.h' | 39 | # s.public_header_files = 'Pod/Classes/**/*.h' |
| 40 | # s.frameworks = 'UIKit', 'MapKit' | 40 | # s.frameworks = 'UIKit', 'MapKit' |
| 41 | - # s.dependency 'AFNetworking', '~> 2.3' | 41 | + s.dependency 'AFNetworking' |
| 42 | +# #基础请求组件库 | ||
| 43 | +# s.dependency 'CNLiveRequestBastKit' | ||
| 42 | end | 44 | end |
CNLiveScanGoodsCamera/Classes/CNLiveCutGridLayer.h
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveCutGridLayer.h | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import <QuartzCore/QuartzCore.h> | ||
| 9 | + | ||
| 10 | +NS_ASSUME_NONNULL_BEGIN | ||
| 11 | + | ||
| 12 | +@interface CNLiveCutGridLayer : CALayer | ||
| 13 | + | ||
| 14 | +@property (nonatomic, assign) CGRect clippingRect; //裁剪范围 | ||
| 15 | +@property (nonatomic, strong) UIColor *bgColor; //背景颜色 | ||
| 16 | +@property (nonatomic, strong) UIColor *gridColor; //线条颜色 | ||
| 17 | + | ||
| 18 | +@end | ||
| 19 | + | ||
| 20 | +NS_ASSUME_NONNULL_END |
CNLiveScanGoodsCamera/Classes/CNLiveCutGridLayer.m
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveCutGridLayer.m | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import "CNLiveCutGridLayer.h" | ||
| 9 | + | ||
| 10 | +@implementation CNLiveCutGridLayer | ||
| 11 | + | ||
| 12 | +- (void)drawInContext:(CGContextRef)context { | ||
| 13 | + CGRect rct = self.bounds; | ||
| 14 | + CGContextSetFillColorWithColor(context, self.bgColor.CGColor); | ||
| 15 | + CGContextFillRect(context, rct); | ||
| 16 | + | ||
| 17 | + //清除范围(截图范围) | ||
| 18 | + CGContextClearRect(context, _clippingRect); | ||
| 19 | + | ||
| 20 | + CGContextSetStrokeColorWithColor(context, self.gridColor.CGColor); | ||
| 21 | + CGContextSetLineWidth(context, 0.8); | ||
| 22 | + | ||
| 23 | + rct = self.clippingRect; | ||
| 24 | + | ||
| 25 | + CGContextBeginPath(context); | ||
| 26 | + CGFloat dW = 0; | ||
| 27 | + //画竖线 | ||
| 28 | + for(int i = 0;i < 4; ++i){ | ||
| 29 | + CGContextMoveToPoint(context, rct.origin.x + dW, rct.origin.y); | ||
| 30 | + CGContextAddLineToPoint(context, rct.origin.x + dW, rct.origin.y + rct.size.height); | ||
| 31 | + dW += _clippingRect.size.width / 3; | ||
| 32 | + } | ||
| 33 | + dW = 0; | ||
| 34 | + //画横线 | ||
| 35 | + for(int i = 0;i < 4; ++i){ | ||
| 36 | + CGContextMoveToPoint(context, rct.origin.x, rct.origin.y + dW); | ||
| 37 | + CGContextAddLineToPoint(context, rct.origin.x + rct.size.width, rct.origin.y + dW); | ||
| 38 | + dW += rct.size.height/3; | ||
| 39 | + } | ||
| 40 | + CGContextStrokePath(context); | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +@end |
CNLiveScanGoodsCamera/Classes/CNLiveCutImageToolView.h
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveCutImageToolView.h | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import <UIKit/UIKit.h> | ||
| 9 | + | ||
| 10 | +NS_ASSUME_NONNULL_BEGIN | ||
| 11 | + | ||
| 12 | +@interface CNLiveCutImageToolView : UIView | ||
| 13 | + | ||
| 14 | +@property (nonatomic, copy) void (^cancelBlock)(void); | ||
| 15 | +@property (nonatomic, copy) void (^finishBlock)(UIImage *image); | ||
| 16 | + | ||
| 17 | +/// selectClipRatio 0 = 全屏 1 = 1:1 | ||
| 18 | ++(instancetype)showViewWithImg:(UIImage *)image andSelectClipRatio:(CGFloat)selectClipRatio; | ||
| 19 | + | ||
| 20 | +@end | ||
| 21 | + | ||
| 22 | +NS_ASSUME_NONNULL_END |
CNLiveScanGoodsCamera/Classes/CNLiveCutImageToolView.m
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveCutImageToolView.m | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import "CNLiveCutImageToolView.h" | ||
| 9 | +#import "CNLiveCutGridLayer.h" | ||
| 10 | +#import "CNLiveCutSquareView.h" | ||
| 11 | + | ||
| 12 | +static const NSUInteger kLeftTopCircleView = 0; | ||
| 13 | +static const NSUInteger kLeftBottomCircleView = 1; | ||
| 14 | +static const NSUInteger kRightTopCircleView = 2; | ||
| 15 | +static const NSUInteger kRightBottomCircleView = 3; | ||
| 16 | + | ||
| 17 | +// 屏幕尺寸定义 | ||
| 18 | +#define KScreenBounds [UIScreen mainScreen].bounds | ||
| 19 | +#define kScreenW [UIScreen mainScreen].bounds.size.width | ||
| 20 | +#define kScreenH [UIScreen mainScreen].bounds.size.height | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +@interface CNLiveCutImageToolView () | ||
| 24 | + | ||
| 25 | +@property (nonatomic, strong) UIImage *image; | ||
| 26 | +@property (nonatomic, strong) UIImageView *imageView; | ||
| 27 | +/// 裁剪范围 | ||
| 28 | +@property (nonatomic, assign) CGRect clippingRect; | ||
| 29 | + | ||
| 30 | +@property (nonatomic, assign) CGFloat selectClipRatio; | ||
| 31 | +@end | ||
| 32 | + | ||
| 33 | +@implementation CNLiveCutImageToolView | ||
| 34 | +{ | ||
| 35 | + CNLiveCutGridLayer *_gridLayer; | ||
| 36 | + //4个角 | ||
| 37 | + CNLiveCutSquareView *_ltView; | ||
| 38 | + CNLiveCutSquareView *_lbView; | ||
| 39 | + CNLiveCutSquareView *_rtView; | ||
| 40 | + CNLiveCutSquareView *_rbView; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +-(instancetype)initWithFrame:(CGRect)frame withImg:(UIImage *)image andSelectClipRatio:(CGFloat)selectClipRatio | ||
| 45 | +{ | ||
| 46 | + self = [super initWithFrame:frame]; | ||
| 47 | + if (self) { | ||
| 48 | + self.image = image; | ||
| 49 | + [self initUI]; | ||
| 50 | + self.selectClipRatio = selectClipRatio; | ||
| 51 | + } | ||
| 52 | + return self; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +-(void)initUI | ||
| 56 | +{ | ||
| 57 | + self.backgroundColor = [UIColor blueColor]; | ||
| 58 | + | ||
| 59 | + self.imageView = [[UIImageView alloc] init]; | ||
| 60 | + self.imageView.image = self.image; | ||
| 61 | + [self addSubview:self.imageView]; | ||
| 62 | + [self setImageViewFrame]; | ||
| 63 | + /// 拖动裁剪区域 | ||
| 64 | + UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGridView:)]; | ||
| 65 | + self.imageView.userInteractionEnabled = YES; | ||
| 66 | + [self.imageView addGestureRecognizer:panGesture]; | ||
| 67 | + /// 保存 | ||
| 68 | + UIView *bottomView = [[UIView alloc] init]; | ||
| 69 | + bottomView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:0.9]; | ||
| 70 | + [self addSubview:bottomView]; | ||
| 71 | + | ||
| 72 | + bottomView.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 87, [UIScreen mainScreen].bounds.size.width, 87); | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + UIButton *saveBtn = [UIButton buttonWithType:UIButtonTypeCustom]; | ||
| 76 | + [saveBtn setBackgroundColor:[UIColor yellowColor]]; | ||
| 77 | + saveBtn.frame = CGRectMake(0, 0, 87, 87); | ||
| 78 | + [bottomView addSubview:saveBtn]; | ||
| 79 | + [saveBtn addTarget:self action:@selector(save) forControlEvents:UIControlEventTouchUpInside]; | ||
| 80 | + | ||
| 81 | +// /// 关闭 | ||
| 82 | +// UIButton *closeBtn = [UIButton zz_buttonWithTitle:nil imageName:@"home_customCamera_close" target:self action:@selector(close)]; | ||
| 83 | +// [bottomView addSubview:closeBtn]; | ||
| 84 | +// | ||
| 85 | +// [closeBtn mas_makeConstraints:^(MASConstraintMaker *make) { | ||
| 86 | +// make.centerY.equalTo(saveBtn); | ||
| 87 | +// make.right.equalTo(bottomView).offset(-10); | ||
| 88 | +// make.width.height.equalTo(@47); | ||
| 89 | +// }]; | ||
| 90 | + | ||
| 91 | + /// 图片裁剪 | ||
| 92 | + _gridLayer = [[CNLiveCutGridLayer alloc] init]; | ||
| 93 | + _gridLayer.frame = self.imageView.bounds; | ||
| 94 | + _gridLayer.bgColor = [[UIColor blackColor] colorWithAlphaComponent:.5]; | ||
| 95 | + _gridLayer.gridColor = [UIColor whiteColor]; | ||
| 96 | + [self.imageView.layer addSublayer:_gridLayer]; | ||
| 97 | + | ||
| 98 | + _ltView = [self clippingCircleWithTag:kLeftTopCircleView]; | ||
| 99 | + _lbView = [self clippingCircleWithTag:kLeftBottomCircleView]; | ||
| 100 | + _rtView = [self clippingCircleWithTag:kRightTopCircleView]; | ||
| 101 | + _rbView = [self clippingCircleWithTag:kRightBottomCircleView]; | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +/// 设置 ImageViewFrame | ||
| 105 | +- (void)setImageViewFrame | ||
| 106 | +{ | ||
| 107 | + CGFloat maxH = kScreenH - 87 - 20; | ||
| 108 | + CGFloat imgW = self.image.size.width; | ||
| 109 | + CGFloat imgH = self.image.size.height; | ||
| 110 | + CGFloat w = kScreenW - 20; | ||
| 111 | + CGFloat h = w * imgH / imgW; | ||
| 112 | + if (h > maxH) { | ||
| 113 | + h = maxH; | ||
| 114 | + w = h * imgW / imgH; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + CGRect frame = CGRectMake((kScreenW - w) * 0.5, (maxH - h) * 0.5 + 10, w, h); | ||
| 118 | + self.imageView.frame = frame; | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +-(void)setSelectClipRatio:(CGFloat)selectClipRatio | ||
| 122 | +{ | ||
| 123 | + _selectClipRatio = selectClipRatio; | ||
| 124 | + CGRect rect = _imageView.bounds; | ||
| 125 | + if (self.selectClipRatio != 0) { | ||
| 126 | + CGFloat H = rect.size.width * self.selectClipRatio; | ||
| 127 | + if (H <= rect.size.height) { | ||
| 128 | + rect.size.height = H; | ||
| 129 | + } else { | ||
| 130 | + rect.size.width *= rect.size.height / H; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + rect.origin.x = (_imageView.bounds.size.width - rect.size.width) / 2; | ||
| 134 | + rect.origin.y = (_imageView.bounds.size.height - rect.size.height) / 2; | ||
| 135 | + } | ||
| 136 | + self.clippingRect = rect; | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +// 4个角的拖动圆球 | ||
| 140 | +- (CNLiveCutSquareView *)clippingCircleWithTag:(NSInteger)tag | ||
| 141 | +{ | ||
| 142 | + CNLiveCutSquareView *view = [[CNLiveCutSquareView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; | ||
| 143 | + view.tag = tag; | ||
| 144 | + | ||
| 145 | + UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panCircleView:)]; | ||
| 146 | + [view addGestureRecognizer:panGesture]; | ||
| 147 | + | ||
| 148 | + [self addSubview:view]; | ||
| 149 | + | ||
| 150 | + return view; | ||
| 151 | +} | ||
| 152 | + | ||
| 153 | +/// 设置裁剪区域 | ||
| 154 | +- (void)setClippingRect:(CGRect)clippingRect | ||
| 155 | +{ | ||
| 156 | + _clippingRect = clippingRect; | ||
| 157 | + _ltView.center = [self convertPoint:CGPointMake(clippingRect.origin.x, clippingRect.origin.y) fromView:_imageView]; | ||
| 158 | + _lbView.center = [self convertPoint:CGPointMake(clippingRect.origin.x, clippingRect.origin.y+clippingRect.size.height) fromView:_imageView]; | ||
| 159 | + _rtView.center = [self convertPoint:CGPointMake(clippingRect.origin.x+clippingRect.size.width, clippingRect.origin.y) fromView:_imageView]; | ||
| 160 | + _rbView.center = [self convertPoint:CGPointMake(clippingRect.origin.x+clippingRect.size.width, clippingRect.origin.y+clippingRect.size.height) fromView:_imageView]; | ||
| 161 | + | ||
| 162 | + _gridLayer.clippingRect = clippingRect; | ||
| 163 | + [self setNeedsDisplay]; | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +- (void)setNeedsDisplay | ||
| 167 | +{ | ||
| 168 | + [super setNeedsDisplay]; | ||
| 169 | + [_gridLayer setNeedsDisplay]; | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | + | ||
| 173 | +#pragma mark - 拖动 | ||
| 174 | +// 拖动4个角 | ||
| 175 | +- (void)panCircleView:(UIPanGestureRecognizer*)sender | ||
| 176 | +{ | ||
| 177 | + CGPoint point = [sender locationInView:_imageView]; | ||
| 178 | + CGPoint dp = [sender translationInView:_imageView]; | ||
| 179 | + | ||
| 180 | + CGRect rct = self.clippingRect; | ||
| 181 | + | ||
| 182 | + const CGFloat W = _imageView.frame.size.width; | ||
| 183 | + const CGFloat H = _imageView.frame.size.height; | ||
| 184 | + CGFloat minX = 0; | ||
| 185 | + CGFloat minY = 0; | ||
| 186 | + CGFloat maxX = W; | ||
| 187 | + CGFloat maxY = H; | ||
| 188 | + | ||
| 189 | + CGFloat ratio = (sender.view.tag == 1 || sender.view.tag == 2) ? -self.selectClipRatio : self.selectClipRatio; | ||
| 190 | + | ||
| 191 | + switch (sender.view.tag) { | ||
| 192 | + case 0: // upper left | ||
| 193 | + { | ||
| 194 | + maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W); | ||
| 195 | + maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H); | ||
| 196 | + | ||
| 197 | + if (ratio!=0) { | ||
| 198 | + CGFloat y0 = rct.origin.y - ratio * rct.origin.x; | ||
| 199 | + CGFloat x0 = -y0 / ratio; | ||
| 200 | + minX = MAX(x0, 0); | ||
| 201 | + minY = MAX(y0, 0); | ||
| 202 | + | ||
| 203 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 204 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 205 | + | ||
| 206 | + if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; } | ||
| 207 | + else{ point.y = point.x * ratio + y0; } | ||
| 208 | + } else { | ||
| 209 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 210 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + rct.size.width = rct.size.width - (point.x - rct.origin.x); | ||
| 214 | + rct.size.height = rct.size.height - (point.y - rct.origin.y); | ||
| 215 | + rct.origin.x = point.x; | ||
| 216 | + rct.origin.y = point.y; | ||
| 217 | + break; | ||
| 218 | + } | ||
| 219 | + case 1: // lower left | ||
| 220 | + { | ||
| 221 | + maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W); | ||
| 222 | + minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H); | ||
| 223 | + | ||
| 224 | + if (ratio!=0) { | ||
| 225 | + CGFloat y0 = (rct.origin.y + rct.size.height) - ratio* rct.origin.x ; | ||
| 226 | + CGFloat xh = (H - y0) / ratio; | ||
| 227 | + minX = MAX(xh, 0); | ||
| 228 | + maxY = MIN(y0, H); | ||
| 229 | + | ||
| 230 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 231 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 232 | + | ||
| 233 | + if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; } | ||
| 234 | + else{ point.y = point.x * ratio + y0; } | ||
| 235 | + } else { | ||
| 236 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 237 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + rct.size.width = rct.size.width - (point.x - rct.origin.x); | ||
| 241 | + rct.size.height = point.y - rct.origin.y; | ||
| 242 | + rct.origin.x = point.x; | ||
| 243 | + break; | ||
| 244 | + } | ||
| 245 | + case 2: // upper right | ||
| 246 | + { | ||
| 247 | + minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W); | ||
| 248 | + maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H); | ||
| 249 | + | ||
| 250 | + if (ratio!=0) { | ||
| 251 | + CGFloat y0 = rct.origin.y - ratio * (rct.origin.x + rct.size.width); | ||
| 252 | + CGFloat yw = ratio * W + y0; | ||
| 253 | + CGFloat x0 = -y0 / ratio; | ||
| 254 | + maxX = MIN(x0, W); | ||
| 255 | + minY = MAX(yw, 0); | ||
| 256 | + | ||
| 257 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 258 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 259 | + | ||
| 260 | + if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; } | ||
| 261 | + else{ point.y = point.x * ratio + y0; } | ||
| 262 | + } else { | ||
| 263 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 264 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + rct.size.width = point.x - rct.origin.x; | ||
| 268 | + rct.size.height = rct.size.height - (point.y - rct.origin.y); | ||
| 269 | + rct.origin.y = point.y; | ||
| 270 | + break; | ||
| 271 | + } | ||
| 272 | + case 3: // lower right | ||
| 273 | + { | ||
| 274 | + minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W); | ||
| 275 | + minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H); | ||
| 276 | + | ||
| 277 | + if (ratio!=0) { | ||
| 278 | + CGFloat y0 = (rct.origin.y + rct.size.height) - ratio * (rct.origin.x + rct.size.width); | ||
| 279 | + CGFloat yw = ratio * W + y0; | ||
| 280 | + CGFloat xh = (H - y0) / ratio; | ||
| 281 | + maxX = MIN(xh, W); | ||
| 282 | + maxY = MIN(yw, H); | ||
| 283 | + | ||
| 284 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 285 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 286 | + | ||
| 287 | + if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; } | ||
| 288 | + else{ point.y = point.x * ratio + y0; } | ||
| 289 | + } else { | ||
| 290 | + point.x = MAX(minX, MIN(point.x, maxX)); | ||
| 291 | + point.y = MAX(minY, MIN(point.y, maxY)); | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + rct.size.width = point.x - rct.origin.x; | ||
| 295 | + rct.size.height = point.y - rct.origin.y; | ||
| 296 | + break; | ||
| 297 | + } | ||
| 298 | + default: | ||
| 299 | + break; | ||
| 300 | + } | ||
| 301 | + self.clippingRect = rct; | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +//移动裁剪view | ||
| 305 | +- (void)panGridView:(UIPanGestureRecognizer*)sender | ||
| 306 | +{ | ||
| 307 | + static BOOL dragging = NO; | ||
| 308 | + static CGRect initialRect; | ||
| 309 | + | ||
| 310 | + if (sender.state==UIGestureRecognizerStateBegan) { | ||
| 311 | + CGPoint point = [sender locationInView:_imageView]; | ||
| 312 | + dragging = CGRectContainsPoint(_clippingRect, point); | ||
| 313 | + initialRect = self.clippingRect; | ||
| 314 | + } else if(dragging) { | ||
| 315 | + CGPoint point = [sender translationInView:_imageView]; | ||
| 316 | + CGFloat left = MIN(MAX(initialRect.origin.x + point.x, 0), _imageView.frame.size.width-initialRect.size.width); | ||
| 317 | + CGFloat top = MIN(MAX(initialRect.origin.y + point.y, 0), _imageView.frame.size.height-initialRect.size.height); | ||
| 318 | + | ||
| 319 | + CGRect rct = self.clippingRect; | ||
| 320 | + rct.origin.x = left; | ||
| 321 | + rct.origin.y = top; | ||
| 322 | + self.clippingRect = rct; | ||
| 323 | + } | ||
| 324 | +} | ||
| 325 | + | ||
| 326 | + | ||
| 327 | +/// 裁剪 | ||
| 328 | +-(void)executeCutCompletion | ||
| 329 | +{ | ||
| 330 | + CGFloat zoomScale = self.imageView.frame.size.width / self.imageView.image.size.width; | ||
| 331 | + CGRect rct = _gridLayer.clippingRect; | ||
| 332 | + rct.size.width /= zoomScale; | ||
| 333 | + rct.size.height /= zoomScale; | ||
| 334 | + rct.origin.x /= zoomScale; | ||
| 335 | + rct.origin.y /= zoomScale; | ||
| 336 | + CGPoint origin = CGPointMake(-rct.origin.x, -rct.origin.y); | ||
| 337 | + UIGraphicsBeginImageContextWithOptions(rct.size, NO, self.imageView.image.scale); | ||
| 338 | + [self.imageView.image drawAtPoint:origin]; | ||
| 339 | + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 340 | + UIGraphicsEndImageContext(); | ||
| 341 | + !self.finishBlock ? : self.finishBlock(img); | ||
| 342 | +} | ||
| 343 | + | ||
| 344 | +/// 保存 | ||
| 345 | +-(void)save | ||
| 346 | +{ | ||
| 347 | + [self executeCutCompletion]; | ||
| 348 | + [self removeFromSuperview]; | ||
| 349 | +} | ||
| 350 | + | ||
| 351 | +/// 关闭 | ||
| 352 | +-(void)close | ||
| 353 | +{ | ||
| 354 | + !self.cancelBlock ? : self.cancelBlock(); | ||
| 355 | + [self removeFromSuperview]; | ||
| 356 | +} | ||
| 357 | + | ||
| 358 | ++(instancetype)showViewWithImg:(UIImage *)image andSelectClipRatio:(CGFloat)selectClipRatio | ||
| 359 | +{ | ||
| 360 | + UIView *keyWindow = [UIApplication sharedApplication].keyWindow; | ||
| 361 | + | ||
| 362 | + CNLiveCutImageToolView *view = [[CNLiveCutImageToolView alloc] initWithFrame:keyWindow.bounds withImg:image andSelectClipRatio:selectClipRatio]; | ||
| 363 | + [keyWindow addSubview:view]; | ||
| 364 | + | ||
| 365 | + return view; | ||
| 366 | +} | ||
| 367 | + | ||
| 368 | +@end |
CNLiveScanGoodsCamera/Classes/CNLiveCutSquareView.h
0 → 100644
CNLiveScanGoodsCamera/Classes/CNLiveCutSquareView.m
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveCutSquareView.m | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import "CNLiveCutSquareView.h" | ||
| 9 | + | ||
| 10 | +@implementation CNLiveCutSquareView | ||
| 11 | + | ||
| 12 | +- (id)initWithFrame:(CGRect)frame | ||
| 13 | +{ | ||
| 14 | + self = [super initWithFrame:frame]; | ||
| 15 | + if (self) { | ||
| 16 | + self.backgroundColor = [UIColor clearColor]; | ||
| 17 | + } | ||
| 18 | + return self; | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +- (void)drawRect:(CGRect)rect | ||
| 22 | +{ | ||
| 23 | + CGContextRef context = UIGraphicsGetCurrentContext(); | ||
| 24 | + | ||
| 25 | + CGRect rct = self.bounds; | ||
| 26 | + rct.origin.x = rct.size.width / 2 - rct.size.width / 6; | ||
| 27 | + rct.origin.y = rct.size.height / 2 - rct.size.height / 6; | ||
| 28 | + rct.size.width /= 3; | ||
| 29 | + rct.size.height /= 3; | ||
| 30 | + | ||
| 31 | + CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor); | ||
| 32 | + CGContextFillEllipseInRect(context, rct); | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +@end |
CNLiveScanGoodsCamera/Classes/CNLiveScanGoodsCameraControlView.h
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveScanGoodsCameraControlView.h | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import <UIKit/UIKit.h> | ||
| 9 | + | ||
| 10 | +@class CNLiveScanGoodsCameraControlView; | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +NS_ASSUME_NONNULL_BEGIN | ||
| 14 | + | ||
| 15 | +typedef void(^ClickTakePhotoBlock)(CNLiveScanGoodsCameraControlView * controlView,UIButton * takePhotoBtn); | ||
| 16 | + | ||
| 17 | +@interface CNLiveScanGoodsCameraControlView : UIView | ||
| 18 | + | ||
| 19 | +@property (nonatomic, copy) ClickTakePhotoBlock clickTakePhotoBlock; | ||
| 20 | + | ||
| 21 | +@end | ||
| 22 | + | ||
| 23 | +NS_ASSUME_NONNULL_END |
CNLiveScanGoodsCamera/Classes/CNLiveScanGoodsCameraControlView.m
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveScanGoodsCameraControlView.m | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/9. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import "CNLiveScanGoodsCameraControlView.h" | ||
| 9 | + | ||
| 10 | +@interface CNLiveScanGoodsCameraControlView () | ||
| 11 | +/// 拍照 | ||
| 12 | +@property (nonatomic, strong) UIButton *takePhotoBtn; | ||
| 13 | +///// 相册 | ||
| 14 | +//@property (nonatomic, strong) UIButton *photoBtn; | ||
| 15 | +///// 关闭 | ||
| 16 | +//@property (nonatomic, strong) UIButton *closeBtn; | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +@end | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +@implementation CNLiveScanGoodsCameraControlView | ||
| 23 | + | ||
| 24 | +- (instancetype)initWithFrame:(CGRect)frame | ||
| 25 | +{ | ||
| 26 | + self = [super initWithFrame:frame]; | ||
| 27 | + if (self) { | ||
| 28 | + | ||
| 29 | + [self setupUI]; | ||
| 30 | + } | ||
| 31 | + return self; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +#pragma mark - setupUI | ||
| 35 | +- (void)setupUI { | ||
| 36 | + [self addSubview:self.takePhotoBtn]; | ||
| 37 | + self.takePhotoBtn.frame = CGRectMake(100, 300, 100, 100); | ||
| 38 | + [self.takePhotoBtn setBackgroundColor:[UIColor yellowColor]]; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +#pragma mark - 实现 | ||
| 42 | +- (void)takePhotoAction:(UIButton *)btn { | ||
| 43 | + | ||
| 44 | + if (self.clickTakePhotoBlock) { | ||
| 45 | + self.clickTakePhotoBlock(self, btn); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | + | ||
| 51 | +#pragma mark - 懒加载 | ||
| 52 | +- (UIButton *)takePhotoBtn { | ||
| 53 | + | ||
| 54 | + if (!_takePhotoBtn) { | ||
| 55 | + _takePhotoBtn = [UIButton buttonWithType:UIButtonTypeCustom]; | ||
| 56 | + [_takePhotoBtn addTarget:self action:@selector(takePhotoAction:) forControlEvents:UIControlEventTouchUpInside]; | ||
| 57 | + | ||
| 58 | + } | ||
| 59 | + return _takePhotoBtn; | ||
| 60 | + | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +@end |
CNLiveScanGoodsCamera/Classes/CNLiveScanGoodsCameraController.h
0 → 100644
CNLiveScanGoodsCamera/Classes/CNLiveScanGoodsCameraController.m
0 → 100644
| 1 | +// | ||
| 2 | +// CNLiveScanGoodsCameraController.m | ||
| 3 | +// CNLiveScanGoodsCamera | ||
| 4 | +// | ||
| 5 | +// Created by 梁星国 on 2020/5/8. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import "CNLiveScanGoodsCameraController.h" | ||
| 9 | +#import <AVFoundation/AVFoundation.h> | ||
| 10 | +#import "CNLiveScanGoodsCameraControlView.h" | ||
| 11 | +#import "CNLiveCutImageToolView.h" | ||
| 12 | +#import <AFNetworking/AFNetworking.h> | ||
| 13 | + | ||
| 14 | +#define RESOLUTION_ARRAY [NSMutableArray arrayWithObjects:/*@"3840*2160",*/ @"1920*1080", @"1280*720", /*@"960*540", */@"640*480", @"352*288", /*@"320x240",*/ nil] | ||
| 15 | + | ||
| 16 | +@interface CNLiveScanGoodsCameraController () <AVCaptureAudioDataOutputSampleBufferDelegate, AVCaptureVideoDataOutputSampleBufferDelegate>{ | ||
| 17 | + int mWidth; | ||
| 18 | + int mHeight; | ||
| 19 | + int mFps; | ||
| 20 | + BOOL mFrontCamera; | ||
| 21 | + BOOL mStarted; | ||
| 22 | + | ||
| 23 | + NSDictionary *mOptions; | ||
| 24 | + CIContext *mContext; | ||
| 25 | + | ||
| 26 | + /* picture */ | ||
| 27 | + BOOL mGetPicture; | ||
| 28 | + UIImage *mCurrentImage; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +/// 捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入) | ||
| 32 | +@property (nonatomic, strong) AVCaptureDevice *device; | ||
| 33 | +/// session:由他把输入输出结合在一起,并开始启动捕获设备(摄像头) | ||
| 34 | +@property (nonatomic, strong) AVCaptureSession *session; | ||
| 35 | + | ||
| 36 | +/// AVCaptureDeviceInput 代表输入设备,他使用AVCaptureDevice 来初始化 | ||
| 37 | +@property (nonatomic, strong) AVCaptureDeviceInput *input; | ||
| 38 | +/// 照片输出流 | ||
| 39 | +@property (nonatomic ,strong) AVCaptureStillImageOutput *imageOutput; | ||
| 40 | +/// 图像预览层,实时显示捕获的图像 | ||
| 41 | +@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer; | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +/// 闪光灯 | ||
| 45 | +@property (nonatomic, assign) BOOL isflashOn; | ||
| 46 | +/// 聚焦 | ||
| 47 | +@property (nonatomic, strong) UIView *focusView; | ||
| 48 | +/// 拍照控制 | ||
| 49 | +@property (nonatomic, strong) CNLiveScanGoodsCameraControlView *controlView; | ||
| 50 | +/// 放大系数 | ||
| 51 | +@property (nonatomic, assign) CGFloat initialPinchZoom; | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + | ||
| 55 | +/// 预览图片内容 | ||
| 56 | +@property (nonatomic, strong) UIImageView *imageView; | ||
| 57 | +/// 拍照的照片 | ||
| 58 | +@property (nonatomic, strong) UIImage *takedImage; | ||
| 59 | + | ||
| 60 | + | ||
| 61 | +@end | ||
| 62 | + | ||
| 63 | +@implementation CNLiveScanGoodsCameraController | ||
| 64 | + | ||
| 65 | +- (void)dealloc | ||
| 66 | +{ | ||
| 67 | + if ([self.session isRunning]) { | ||
| 68 | + [self stopVideoCapture]; | ||
| 69 | + } | ||
| 70 | + self.session = nil; | ||
| 71 | + self->mOptions = nil; | ||
| 72 | + self->mContext = nil; | ||
| 73 | + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]]; | ||
| 74 | + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]]; | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +- (void)viewDidLoad { | ||
| 78 | + [super viewDidLoad]; | ||
| 79 | + | ||
| 80 | + [self initContent]; | ||
| 81 | + [self startVideoCapture]; | ||
| 82 | + [self initUI]; | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +- (BOOL)prefersStatusBarHidden | ||
| 89 | +{ | ||
| 90 | + return true; | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +-(void)viewWillAppear:(BOOL)animated | ||
| 94 | +{ | ||
| 95 | + [super viewWillAppear:animated]; | ||
| 96 | + [self setNeedsStatusBarAppearanceUpdate]; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | + | ||
| 100 | +#pragma mark - 初始化 | ||
| 101 | +/// 初始化 | ||
| 102 | +- (void)initContent { | ||
| 103 | + self->mWidth = 640; | ||
| 104 | + self->mHeight = 480; | ||
| 105 | + self->mFps = 30; | ||
| 106 | + self->mFrontCamera = NO; | ||
| 107 | + self->mStarted = NO; | ||
| 108 | + self->mGetPicture = NO; | ||
| 109 | + self->mCurrentImage = nil; | ||
| 110 | + | ||
| 111 | + self->mOptions = @{ kCIContextWorkingColorSpace : [NSNull null], kCIContextOutputColorSpace : [NSNull null] }; | ||
| 112 | + self->mContext = [CIContext contextWithEAGLContext:[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] options:self->mOptions]; | ||
| 113 | + | ||
| 114 | + [[NSNotificationCenter defaultCenter] addObserver:self | ||
| 115 | + selector:@selector(applicationDidEnterBackground) | ||
| 116 | + name:UIApplicationDidEnterBackgroundNotification | ||
| 117 | + object:[UIApplication sharedApplication]]; | ||
| 118 | + [[NSNotificationCenter defaultCenter] addObserver:self | ||
| 119 | + selector:@selector(applicationWillEnterForeground) | ||
| 120 | + name:UIApplicationWillEnterForegroundNotification | ||
| 121 | + object:[UIApplication sharedApplication]]; | ||
| 122 | + | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +/// 初始化UI | ||
| 126 | +-(void)initUI | ||
| 127 | +{ | ||
| 128 | + /// 焦点视图 | ||
| 129 | + self.focusView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)]; | ||
| 130 | + self.focusView.layer.borderWidth = 1.0; | ||
| 131 | + self.focusView.layer.borderColor = [UIColor greenColor].CGColor; | ||
| 132 | + [self.view addSubview:self.focusView]; | ||
| 133 | + self.focusView.hidden = YES; | ||
| 134 | + | ||
| 135 | + self.controlView = [[CNLiveScanGoodsCameraControlView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width)]; | ||
| 136 | + __weak typeof(self) weakSelf = self; | ||
| 137 | + /// 拍照 | ||
| 138 | + self.controlView.clickTakePhotoBlock = ^(CNLiveScanGoodsCameraControlView * _Nonnull controlView, UIButton * _Nonnull takePhotoBtn) { | ||
| 139 | + [weakSelf onTakePicture]; | ||
| 140 | + }; | ||
| 141 | + | ||
| 142 | + // /// 相册 | ||
| 143 | + // self.contentView.openPhotoBlock = ^{ | ||
| 144 | + // [weakSelf openPhotoLibrary]; | ||
| 145 | + // }; | ||
| 146 | + // /// 关闭 | ||
| 147 | + // self.contentView.closeBlock = ^{ | ||
| 148 | + // [weakSelf dismissViewControllerAnimated:true completion:nil]; | ||
| 149 | + // }; | ||
| 150 | + // /// 跳过 | ||
| 151 | + // self.contentView.skipBlock = ^{ | ||
| 152 | + // NSLog(@"跳过"); | ||
| 153 | + // }; | ||
| 154 | + | ||
| 155 | + [self.view addSubview:self.controlView]; | ||
| 156 | + | ||
| 157 | + ///捏合手势 | ||
| 158 | + UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchDetected:)]; | ||
| 159 | + [self.view addGestureRecognizer:pinch]; | ||
| 160 | + /// 点击手势_对焦 | ||
| 161 | + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(focusGesture:)]; | ||
| 162 | + [self.view addGestureRecognizer:tapGesture]; | ||
| 163 | +} | ||
| 164 | + | ||
| 165 | + | ||
| 166 | +#pragma mark - 私有方法 | ||
| 167 | + | ||
| 168 | +#pragma mark - | ||
| 169 | +#pragma mark - 开始拍摄 | ||
| 170 | +- (void) startVideoCapture { | ||
| 171 | + [[UIApplication sharedApplication] setIdleTimerDisabled:YES];/*Open anti-lock*/ | ||
| 172 | + /*if open , set nil;*/ | ||
| 173 | + if (self.device || self.session) { | ||
| 174 | + self.device = nil; | ||
| 175 | + self.session = nil; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + if ((self.device = [self getAVCaptureDeviceCamera]) == nil) { | ||
| 179 | + /*If the open fails, the return;*/ | ||
| 180 | + return; | ||
| 181 | + } | ||
| 182 | + /*set frame rate*/ | ||
| 183 | + NSError *error = nil; | ||
| 184 | + if ([self.device lockForConfiguration:&error]) { | ||
| 185 | + [self.device setActiveVideoMaxFrameDuration:CMTimeMake(1, self->mFps)]; | ||
| 186 | + [self.device setActiveVideoMinFrameDuration:CMTimeMake(1, self->mFps)]; | ||
| 187 | + [self.device unlockForConfiguration]; | ||
| 188 | + } else { | ||
| 189 | + NSLog(@"videoDevice lockForConfiguration returned error %@", error); | ||
| 190 | + } | ||
| 191 | + /*init device input*/ | ||
| 192 | + error = nil; | ||
| 193 | + AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error]; | ||
| 194 | + self.input = videoInput; | ||
| 195 | + if (!videoInput) { | ||
| 196 | + self.device = nil; | ||
| 197 | + return; | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + /// 照片输出流 | ||
| 201 | + AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc]init]; | ||
| 202 | + self.imageOutput = imageOutput; | ||
| 203 | + | ||
| 204 | + /*init capture session*/ | ||
| 205 | + self.session = [[AVCaptureSession alloc] init]; | ||
| 206 | + if ([self.session canAddOutput:imageOutput]) { | ||
| 207 | + [self.session addOutput:imageOutput]; | ||
| 208 | + } | ||
| 209 | + if ([self.session canAddInput:videoInput]) { | ||
| 210 | + [self.session addInput:videoInput]; | ||
| 211 | + } | ||
| 212 | + /*set resolution*/ | ||
| 213 | + NSString *captureQuality = [NSString stringWithString:[self getCaptureQuality]]; | ||
| 214 | + /*begin configuration for the AVCaptureSession*/ | ||
| 215 | + [self.session beginConfiguration]; | ||
| 216 | + /*quality*/ | ||
| 217 | + [self.session setSessionPreset:captureQuality]; | ||
| 218 | + | ||
| 219 | + /* Currently, the only supported key is kCVPixelBufferPixelFormatTypeKey. Recommended pixel format choices are | ||
| 220 | + kCVPixelFormatType_420YpCbCr8BiPlanarFullRange(420f:YUV type) or kCVPixelFormatType_32BGRA(32 byte BGRA)... | ||
| 221 | + On iPhone 3G, the recommended pixel format choices are kCVPixelFormatType_422YpCbCr8 or kCVPixelFormatType_32BGRA. | ||
| 222 | + */ | ||
| 223 | + AVCaptureVideoDataOutput *avCaptureVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; | ||
| 224 | + NSString *key = (NSString *)kCVPixelBufferPixelFormatTypeKey;//only supported key; | ||
| 225 | + NSNumber *val = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];//h264 used YUV; | ||
| 226 | + NSDictionary *settings = [NSDictionary dictionaryWithObject:val forKey:key]; | ||
| 227 | + avCaptureVideoDataOutput.videoSettings = settings; | ||
| 228 | + | ||
| 229 | + /*we create a serial queue to handle the processing of our frames*/ | ||
| 230 | + dispatch_queue_t queue = dispatch_queue_create("com.QuinnQiu.class.video2", NULL); | ||
| 231 | + [avCaptureVideoDataOutput setSampleBufferDelegate:self queue:queue]; | ||
| 232 | + | ||
| 233 | + /* default orientation portrait*/ | ||
| 234 | + [[avCaptureVideoDataOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:AVCaptureVideoOrientationPortrait]; | ||
| 235 | + [self.session addOutput:avCaptureVideoDataOutput]; | ||
| 236 | + /* preview */ | ||
| 237 | + AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; | ||
| 238 | + previewLayer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height); | ||
| 239 | + previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; | ||
| 240 | + [self.view.layer addSublayer:previewLayer]; | ||
| 241 | + self.previewLayer = previewLayer; | ||
| 242 | + | ||
| 243 | + /* start */ | ||
| 244 | + self->mStarted = YES; | ||
| 245 | + /* commit configuration */ | ||
| 246 | + [self.session commitConfiguration]; | ||
| 247 | + [self.session startRunning]; | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +#pragma mark - 关闭拍摄 | ||
| 251 | +- (void) stopVideoCapture { | ||
| 252 | + [[UIApplication sharedApplication] setIdleTimerDisabled:NO]; | ||
| 253 | + | ||
| 254 | + if ([self.session isRunning]) { | ||
| 255 | + [self.session stopRunning]; | ||
| 256 | + } | ||
| 257 | + self.session = nil; | ||
| 258 | + self.device = nil; | ||
| 259 | + self->mStarted = NO; | ||
| 260 | + | ||
| 261 | +} | ||
| 262 | + | ||
| 263 | +#pragma mark Get the camera device | ||
| 264 | +- (AVCaptureDevice *)getAVCaptureDeviceCamera{ | ||
| 265 | + return [self cameraAtPosition:mFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack]; | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +#pragma mark - get the current camera device | ||
| 269 | +- (AVCaptureDevice *)cameraAtPosition:(AVCaptureDevicePosition)position{ | ||
| 270 | + NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];//set type with AVMediaTypeVideo | ||
| 271 | + for (AVCaptureDevice *device in cameras){ | ||
| 272 | + if (device.position == position){ | ||
| 273 | + return device; | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; | ||
| 277 | +} | ||
| 278 | + | ||
| 279 | +#pragma get capture resulotion string | ||
| 280 | +-(NSString *) getCaptureQuality{ | ||
| 281 | + NSString *captureQuality = AVCaptureSessionPreset640x480; | ||
| 282 | + switch (self->mWidth) { | ||
| 283 | + case 352: | ||
| 284 | + captureQuality = AVCaptureSessionPreset352x288; | ||
| 285 | + break; | ||
| 286 | + case 640: | ||
| 287 | + captureQuality = AVCaptureSessionPreset640x480; | ||
| 288 | + break; | ||
| 289 | + case 960: | ||
| 290 | + captureQuality = AVCaptureSessionPresetiFrame960x540; | ||
| 291 | + break; | ||
| 292 | + case 1280: | ||
| 293 | + captureQuality = AVCaptureSessionPreset1280x720; | ||
| 294 | + break; | ||
| 295 | + case 1920: | ||
| 296 | + captureQuality = AVCaptureSessionPreset1920x1080; | ||
| 297 | + break; | ||
| 298 | + case 3840: | ||
| 299 | + if (@available(iOS 9.0, *)) { | ||
| 300 | + captureQuality = AVCaptureSessionPreset3840x2160; | ||
| 301 | + } else { | ||
| 302 | + // Fallback on earlier versions | ||
| 303 | + } | ||
| 304 | + break; | ||
| 305 | + default: | ||
| 306 | + break; | ||
| 307 | + } | ||
| 308 | + return captureQuality; | ||
| 309 | +} | ||
| 310 | + | ||
| 311 | +#pragma mark determint whether the current camera front camera | ||
| 312 | +- (BOOL) determineTheCurrentCameraIsFront { | ||
| 313 | + return mFrontCamera; | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +#pragma mark set the front camera | ||
| 317 | +- (BOOL) setFrontCamera { | ||
| 318 | + if (self->mFrontCamera) { | ||
| 319 | + return YES; | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + [self stopVideoCapture]; | ||
| 323 | + self->mFrontCamera = YES; | ||
| 324 | + [self startVideoCapture]; | ||
| 325 | + return YES; | ||
| 326 | +} | ||
| 327 | + | ||
| 328 | +#pragma mark set the back camera | ||
| 329 | +- (BOOL) setBackCamera { | ||
| 330 | + if (!self->mFrontCamera) { | ||
| 331 | + return YES; | ||
| 332 | + } | ||
| 333 | + | ||
| 334 | + [self stopVideoCapture]; | ||
| 335 | + mFrontCamera = NO; | ||
| 336 | + [self startVideoCapture]; | ||
| 337 | + return YES; | ||
| 338 | +} | ||
| 339 | + | ||
| 340 | +#pragma mark set capture resolution | ||
| 341 | +- (void) setPrepareVideoCaptureResolution: (int)width andHeight: (int)height { | ||
| 342 | + self->mWidth = width; | ||
| 343 | + self->mHeight = height; | ||
| 344 | + /*If you are running must be stopped*/ | ||
| 345 | + if ([self.session isRunning]) { | ||
| 346 | + [self stopVideoCapture]; | ||
| 347 | + [self startVideoCapture]; | ||
| 348 | + } else { | ||
| 349 | + [self startVideoCapture]; | ||
| 350 | + } | ||
| 351 | + mStarted = NO; | ||
| 352 | +} | ||
| 353 | + | ||
| 354 | +#pragma mark - get resolution array of the current camera | ||
| 355 | +- (NSMutableArray *) getCurrentCameraResolutionArray { | ||
| 356 | + NSMutableArray *resoluArray = nil; | ||
| 357 | + if (self.session) { | ||
| 358 | + NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:AVCaptureSessionPreset1920x1080, AVCaptureSessionPreset1280x720, AVCaptureSessionPreset640x480, AVCaptureSessionPreset352x288, nil]; | ||
| 359 | + resoluArray = [[NSMutableArray alloc] initWithCapacity:1]; | ||
| 360 | + | ||
| 361 | + for (int i = 0; i < array.count; i++) { | ||
| 362 | + if ([self.session canSetSessionPreset:[array objectAtIndex:i]]) { | ||
| 363 | + [resoluArray addObject:[RESOLUTION_ARRAY objectAtIndex:i]]; | ||
| 364 | + } | ||
| 365 | + } | ||
| 366 | + | ||
| 367 | + } else { | ||
| 368 | + resoluArray = [[NSMutableArray alloc] initWithObjects:AVCaptureSessionPreset640x480, nil]; | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + return resoluArray; | ||
| 372 | +} | ||
| 373 | + | ||
| 374 | + | ||
| 375 | +#pragma mark - 通知 | ||
| 376 | +#pragma mark Enter background | ||
| 377 | +- (void)applicationDidEnterBackground{ | ||
| 378 | + [self stopVideoCapture]; | ||
| 379 | +} | ||
| 380 | + | ||
| 381 | +#pragma mark enter foreground | ||
| 382 | +- (void)applicationWillEnterForeground{ | ||
| 383 | + [self startVideoCapture]; | ||
| 384 | +} | ||
| 385 | + | ||
| 386 | + | ||
| 387 | +#pragma mark rotate picture | ||
| 388 | +- (UIImage *)fixOrientation:(UIImage *)image { | ||
| 389 | + long double rotate = 0.0; | ||
| 390 | + CGRect rect; | ||
| 391 | + float translateX = 0; | ||
| 392 | + float translateY = 0; | ||
| 393 | + float scaleX = 1.0; | ||
| 394 | + float scaleY = 1.0; | ||
| 395 | + | ||
| 396 | + CGSize newSize; | ||
| 397 | + | ||
| 398 | + if (image.size.width < image.size.height) { | ||
| 399 | + newSize.width = image.size.width; | ||
| 400 | + newSize.height = image.size.width / 4 * 3;//this attention;4:3 | ||
| 401 | + }else{ | ||
| 402 | + newSize = image.size; | ||
| 403 | + } | ||
| 404 | + /* current device orientation */ | ||
| 405 | + UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation]; | ||
| 406 | + if (self->mFrontCamera) { | ||
| 407 | + switch (deviceOrientation) { | ||
| 408 | + case UIDeviceOrientationLandscapeRight: | ||
| 409 | + rotate = 0; | ||
| 410 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 411 | + translateX = 0; | ||
| 412 | + translateY = 0; | ||
| 413 | + break; | ||
| 414 | + case UIDeviceOrientationPortraitUpsideDown: | ||
| 415 | + rotate = M_PI_2; | ||
| 416 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 417 | + translateX = 0; | ||
| 418 | + translateY = -rect.size.width; | ||
| 419 | + scaleY = rect.size.width/rect.size.height; | ||
| 420 | + scaleX = rect.size.height/rect.size.width; | ||
| 421 | + break; | ||
| 422 | + case UIDeviceOrientationLandscapeLeft: | ||
| 423 | + rotate = M_PI; | ||
| 424 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 425 | + translateX = -rect.size.width; | ||
| 426 | + translateY = -rect.size.height; | ||
| 427 | + break; | ||
| 428 | + default: | ||
| 429 | + rotate = -M_PI_2; | ||
| 430 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 431 | + translateX = -rect.size.height; | ||
| 432 | + translateY = 0; | ||
| 433 | + scaleY = rect.size.width/rect.size.height; | ||
| 434 | + scaleX = rect.size.height/rect.size.width; | ||
| 435 | + break; | ||
| 436 | + } | ||
| 437 | + }else{ | ||
| 438 | + switch (deviceOrientation) { | ||
| 439 | + case UIDeviceOrientationLandscapeRight: | ||
| 440 | + rotate = M_PI; | ||
| 441 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 442 | + translateX = -rect.size.width; | ||
| 443 | + translateY = -rect.size.height; | ||
| 444 | + break; | ||
| 445 | + case UIDeviceOrientationPortraitUpsideDown: | ||
| 446 | + rotate = M_PI_2; | ||
| 447 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 448 | + translateX = 0; | ||
| 449 | + translateY = -rect.size.width; | ||
| 450 | + scaleY = rect.size.width/rect.size.height; | ||
| 451 | + scaleX = rect.size.height/rect.size.width; | ||
| 452 | + break; | ||
| 453 | + case UIDeviceOrientationLandscapeLeft: | ||
| 454 | + rotate = 0; | ||
| 455 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 456 | + translateX = 0; | ||
| 457 | + translateY = 0; | ||
| 458 | + break; | ||
| 459 | + default: | ||
| 460 | + rotate = -M_PI_2; | ||
| 461 | + rect = CGRectMake(0, 0, newSize.width, newSize.height); | ||
| 462 | + translateX = -rect.size.height; | ||
| 463 | + translateY = 0; | ||
| 464 | + scaleY = rect.size.width/rect.size.height; | ||
| 465 | + scaleX = rect.size.height/rect.size.width; | ||
| 466 | + break; | ||
| 467 | + } | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + UIGraphicsBeginImageContext(rect.size); | ||
| 471 | + CGContextRef context = UIGraphicsGetCurrentContext(); | ||
| 472 | + /* Do CTM conversion */ | ||
| 473 | + CGContextTranslateCTM(context, 0.0, rect.size.height); | ||
| 474 | + CGContextScaleCTM(context, 1.0, -1.0); | ||
| 475 | + CGContextRotateCTM(context, rotate); | ||
| 476 | + CGContextTranslateCTM(context, translateX, translateY); | ||
| 477 | + | ||
| 478 | + CGContextScaleCTM(context, scaleX, scaleY); | ||
| 479 | + /* draw image */ | ||
| 480 | + CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage); | ||
| 481 | + | ||
| 482 | + UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 483 | + UIGraphicsEndImageContext(); | ||
| 484 | + return newPic; | ||
| 485 | +} | ||
| 486 | + | ||
| 487 | + | ||
| 488 | + | ||
| 489 | +#pragma mark - | ||
| 490 | +#pragma mark - 功能 | ||
| 491 | + | ||
| 492 | +- (void)captureOutput:(AVCaptureFileOutput *)output | ||
| 493 | +didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer | ||
| 494 | + fromConnection:(AVCaptureConnection *)connection { | ||
| 495 | + | ||
| 496 | + if (self->mGetPicture) { | ||
| 497 | + return; | ||
| 498 | + }else { | ||
| 499 | + self->mGetPicture = YES; | ||
| 500 | + } | ||
| 501 | + | ||
| 502 | + /* Here only handles video stream, audio stream based on connection to distinguish */ | ||
| 503 | + /* Since 32BGRA very simple, here only deal with YUV format */ | ||
| 504 | + const int kFlags = 0; | ||
| 505 | + CVImageBufferRef videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer); | ||
| 506 | + | ||
| 507 | + if (CVPixelBufferLockBaseAddress(videoFrame, kFlags) != kCVReturnSuccess) { | ||
| 508 | + return; | ||
| 509 | + } | ||
| 510 | + | ||
| 511 | +// const int kYPlaneIndex = 0; | ||
| 512 | +// const int kUVPlaneIndex = 1; | ||
| 513 | + | ||
| 514 | +// uint8_t *baseAddress = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(videoFrame, kYPlaneIndex); | ||
| 515 | +// size_t yPlaneBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(videoFrame, kYPlaneIndex); | ||
| 516 | +// size_t yPlaneHeight = CVPixelBufferGetHeightOfPlane(videoFrame, kYPlaneIndex); | ||
| 517 | +// size_t uvPlaneBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(videoFrame, kUVPlaneIndex); | ||
| 518 | +// size_t uvPlaneHeight = CVPixelBufferGetHeightOfPlane(videoFrame, kUVPlaneIndex); | ||
| 519 | +// size_t frameSize = yPlaneBytesPerRow * yPlaneHeight + uvPlaneBytesPerRow * uvPlaneHeight; | ||
| 520 | + | ||
| 521 | + CVPixelBufferUnlockBaseAddress(videoFrame, kFlags); | ||
| 522 | + | ||
| 523 | + /* get picture */ | ||
| 524 | + UIImage *image = [self getCurrentImageWith:sampleBuffer]; | ||
| 525 | + if (!image) { | ||
| 526 | + self->mGetPicture = NO; | ||
| 527 | + return; | ||
| 528 | + } | ||
| 529 | + self->mCurrentImage = [self fixOrientation:image]; | ||
| 530 | + | ||
| 531 | + dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
| 532 | + dispatch_async(dispatch_get_main_queue(), ^{ | ||
| 533 | + | ||
| 534 | + [self.view addSubview:self.imageView]; | ||
| 535 | + self.imageView.image = self->mCurrentImage; | ||
| 536 | + | ||
| 537 | + [self requestWithImage:self.imageView.image type:@"1"]; | ||
| 538 | + | ||
| 539 | + }); | ||
| 540 | + }); | ||
| 541 | + | ||
| 542 | + | ||
| 543 | + | ||
| 544 | + | ||
| 545 | +} | ||
| 546 | + | ||
| 547 | +#pragma mark get iamge with CMSampleBufferRef | ||
| 548 | +- (UIImage *) getCurrentImageWith: (CMSampleBufferRef)sampleBuffer { | ||
| 549 | + | ||
| 550 | + CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(sampleBuffer); | ||
| 551 | + CIImage *ciImage = [CIImage imageWithCVPixelBuffer:buffer]; | ||
| 552 | + | ||
| 553 | + CGImageRef cgImage = [mContext createCGImage:ciImage fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(buffer), CVPixelBufferGetHeight(buffer))]; | ||
| 554 | + | ||
| 555 | + UIImage *image = [UIImage imageWithCGImage:cgImage]; | ||
| 556 | + | ||
| 557 | + CGImageRelease(cgImage); | ||
| 558 | + return image; | ||
| 559 | +} | ||
| 560 | + | ||
| 561 | + | ||
| 562 | +#pragma mark - 拖拽放大 | ||
| 563 | +- (void)pinchDetected:(UIPinchGestureRecognizer*)recogniser | ||
| 564 | +{ | ||
| 565 | + if (recogniser.state == UIGestureRecognizerStateBegan) | ||
| 566 | + { | ||
| 567 | + _initialPinchZoom = self.device.videoZoomFactor; | ||
| 568 | + } | ||
| 569 | + | ||
| 570 | + NSError *error = nil; | ||
| 571 | + [self.device lockForConfiguration:&error]; | ||
| 572 | + | ||
| 573 | + if (!error) { | ||
| 574 | + CGFloat zoomFactor; | ||
| 575 | + CGFloat scale = recogniser.scale; | ||
| 576 | + if (scale < 1.0f) { | ||
| 577 | + zoomFactor = _initialPinchZoom - pow(self.device.activeFormat.videoMaxZoomFactor, 1.0f - recogniser.scale); | ||
| 578 | + } else { | ||
| 579 | + zoomFactor = _initialPinchZoom + pow(self.device.activeFormat.videoMaxZoomFactor, (recogniser.scale - 1.0f) / 2.0f); | ||
| 580 | + } | ||
| 581 | + | ||
| 582 | + zoomFactor = MIN(10.0f, zoomFactor); | ||
| 583 | + zoomFactor = MAX(1.0f, zoomFactor); | ||
| 584 | + | ||
| 585 | + self.device.videoZoomFactor = zoomFactor; | ||
| 586 | + [self.device unlockForConfiguration]; | ||
| 587 | + } | ||
| 588 | +} | ||
| 589 | +#pragma mark - 对焦 | ||
| 590 | +/// 对焦 | ||
| 591 | +- (void)focusGesture:(UITapGestureRecognizer*)gesture | ||
| 592 | +{ | ||
| 593 | + CGPoint point = [gesture locationInView:gesture.view]; | ||
| 594 | + [self focusAtPoint:point]; | ||
| 595 | +} | ||
| 596 | + | ||
| 597 | +- (void)focusAtPoint:(CGPoint)point | ||
| 598 | +{ | ||
| 599 | + CGSize size = self.view.bounds.size; | ||
| 600 | + // focusPoint 函数后面Point取值范围是取景框左上角(0,0)到取景框右下角(1,1)之间,按这个来但位置就是不对,只能按上面的写法才可以。前面是点击位置的y/PreviewLayer的高度,后面是1-点击位置的x/PreviewLayer的宽度 | ||
| 601 | + CGPoint focusPoint = CGPointMake( point.y /size.height ,1 - point.x/size.width ); | ||
| 602 | + NSError *error; | ||
| 603 | + if ([self.device lockForConfiguration:&error]) { | ||
| 604 | + if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) { | ||
| 605 | + [self.device setFocusPointOfInterest:focusPoint]; | ||
| 606 | + [self.device setFocusMode:AVCaptureFocusModeAutoFocus]; | ||
| 607 | + } | ||
| 608 | + | ||
| 609 | + if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose ]) { | ||
| 610 | + [self.device setExposurePointOfInterest:focusPoint]; | ||
| 611 | + // 曝光量调节 | ||
| 612 | + [self.device setExposureMode:AVCaptureExposureModeAutoExpose]; | ||
| 613 | + } | ||
| 614 | + | ||
| 615 | + [self.device unlockForConfiguration]; | ||
| 616 | + self.focusView.center = point; | ||
| 617 | + self.focusView.hidden = NO; | ||
| 618 | + [UIView animateWithDuration:0.3 animations:^{ | ||
| 619 | + self.focusView.transform = CGAffineTransformMakeScale(1.25, 1.25); | ||
| 620 | + }completion:^(BOOL finished) { | ||
| 621 | + [UIView animateWithDuration:0.5 animations:^{ | ||
| 622 | + self.focusView.transform = CGAffineTransformIdentity; | ||
| 623 | + } completion:^(BOOL finished) { | ||
| 624 | + self.focusView.hidden = YES; | ||
| 625 | + }]; | ||
| 626 | + }]; | ||
| 627 | + } | ||
| 628 | +} | ||
| 629 | + | ||
| 630 | +#pragma mark - 闪光灯 | ||
| 631 | +- (void)FlashOn | ||
| 632 | +{ | ||
| 633 | + NSError *error; | ||
| 634 | + if ([_device lockForConfiguration:&error]) { | ||
| 635 | + if (_isflashOn) { | ||
| 636 | + if ([_device isFlashModeSupported:AVCaptureFlashModeOff]) { | ||
| 637 | + [_device setFlashMode:AVCaptureFlashModeOff]; | ||
| 638 | + _isflashOn = NO; | ||
| 639 | + | ||
| 640 | + } | ||
| 641 | + }else{ | ||
| 642 | + if ([_device isFlashModeSupported:AVCaptureFlashModeOn]) { | ||
| 643 | + [_device setFlashMode:AVCaptureFlashModeOn]; | ||
| 644 | + _isflashOn = YES; | ||
| 645 | + } | ||
| 646 | + } | ||
| 647 | + [_device unlockForConfiguration]; | ||
| 648 | + } | ||
| 649 | +} | ||
| 650 | + | ||
| 651 | +#pragma mark - 切换摄像头 | ||
| 652 | + | ||
| 653 | +-(void)changeCamera | ||
| 654 | +{ | ||
| 655 | + //获取摄像头的数量 | ||
| 656 | + NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count]; | ||
| 657 | + //摄像头小于等于1的时候直接返回 | ||
| 658 | + if (cameraCount <= 1) return; | ||
| 659 | + | ||
| 660 | + AVCaptureDevice *newCamera = nil; | ||
| 661 | + AVCaptureDeviceInput *newInput = nil; | ||
| 662 | + //获取当前相机的方向(前还是后) | ||
| 663 | + AVCaptureDevicePosition position = [[self.input device] position]; | ||
| 664 | + | ||
| 665 | + //为摄像头的转换加转场动画 | ||
| 666 | + CATransition *animation = [CATransition animation]; | ||
| 667 | + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; | ||
| 668 | + animation.duration = 0.5; | ||
| 669 | + animation.type = @"oglFlip"; | ||
| 670 | + | ||
| 671 | + if (position == AVCaptureDevicePositionFront) { | ||
| 672 | + //获取后置摄像头 | ||
| 673 | + newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack]; | ||
| 674 | + animation.subtype = kCATransitionFromLeft; | ||
| 675 | + }else{ | ||
| 676 | + //获取前置摄像头 | ||
| 677 | + newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront]; | ||
| 678 | + animation.subtype = kCATransitionFromRight; | ||
| 679 | + } | ||
| 680 | + | ||
| 681 | + [self.previewLayer addAnimation:animation forKey:nil]; | ||
| 682 | + //输入流 | ||
| 683 | + newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil]; | ||
| 684 | + | ||
| 685 | + if (newInput != nil) { | ||
| 686 | + | ||
| 687 | + [self.session beginConfiguration]; | ||
| 688 | + //先移除原来的input | ||
| 689 | + [self.session removeInput:self.input]; | ||
| 690 | + | ||
| 691 | + if ([self.session canAddInput:newInput]) { | ||
| 692 | + [self.session addInput:newInput]; | ||
| 693 | + self.input = newInput; | ||
| 694 | + | ||
| 695 | + } else { | ||
| 696 | + //如果不能加现在的input,就加原来的input | ||
| 697 | + [self.session addInput:self.input]; | ||
| 698 | + } | ||
| 699 | + [self.session commitConfiguration]; | ||
| 700 | + } | ||
| 701 | +} | ||
| 702 | + | ||
| 703 | +- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position | ||
| 704 | +{ | ||
| 705 | + NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; | ||
| 706 | + for ( AVCaptureDevice *device in devices ) | ||
| 707 | + if ( device.position == position ) return device; | ||
| 708 | + return nil; | ||
| 709 | +} | ||
| 710 | + | ||
| 711 | +#pragma mark - 拍照 | ||
| 712 | +/// 拍照 | ||
| 713 | +-(void)onTakePicture | ||
| 714 | +{ | ||
| 715 | + AVCaptureConnection * videoConnection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo]; | ||
| 716 | + if (videoConnection == nil) return; | ||
| 717 | + __weak typeof(self) weakSelf = self; | ||
| 718 | + [self.imageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { | ||
| 719 | + if (imageDataSampleBuffer == NULL) return; | ||
| 720 | + NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; | ||
| 721 | + UIImage * image = [UIImage imageWithData:imageData]; | ||
| 722 | + [self stopVideoCapture]; | ||
| 723 | + [weakSelf openEditToolWithImg:image]; | ||
| 724 | + }]; | ||
| 725 | +} | ||
| 726 | + | ||
| 727 | +#pragma mark - 裁剪图片 | ||
| 728 | +/// 裁剪图片 | ||
| 729 | +-(void)openEditToolWithImg:(UIImage *)image | ||
| 730 | +{ | ||
| 731 | + __weak typeof(self) weakSelf = self; | ||
| 732 | + CNLiveCutImageToolView *tool = [CNLiveCutImageToolView showViewWithImg:image andSelectClipRatio:0]; | ||
| 733 | + // tool.cancelBlock = ^{ | ||
| 734 | + // /// 重拍 | ||
| 735 | + // [weakSelf onRetake]; | ||
| 736 | + // }; | ||
| 737 | + tool.finishBlock = ^(UIImage *image) { | ||
| 738 | + /// 保存图片 | ||
| 739 | + weakSelf.takedImage = image; | ||
| 740 | + [weakSelf requestWithImage:image type:@"2"]; | ||
| 741 | + }; | ||
| 742 | +} | ||
| 743 | + | ||
| 744 | +#pragma mark - 打开相册 | ||
| 745 | +-(void)openPhotoLibrary | ||
| 746 | +{ | ||
| 747 | + // TZImagePickerController *imagePickerVC = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:nil]; | ||
| 748 | + // // 在内部显示拍照按钮 | ||
| 749 | + // imagePickerVC.allowTakePicture = false; | ||
| 750 | + // // 设置是否可以选择视频 | ||
| 751 | + // imagePickerVC.allowPickingVideo = false; | ||
| 752 | + // imagePickerVC.autoDismiss = false; | ||
| 753 | + // | ||
| 754 | + // WeakSelf; | ||
| 755 | + // __weak typeof(imagePickerVC) weakVC = imagePickerVC; | ||
| 756 | + // [imagePickerVC setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { | ||
| 757 | + // [weakSelf openEditToolWithImg:photos.lastObject]; | ||
| 758 | + // [weakVC dismissViewControllerAnimated:true completion:nil]; | ||
| 759 | + // }]; | ||
| 760 | + // | ||
| 761 | + // [imagePickerVC setImagePickerControllerDidCancelHandle:^{ | ||
| 762 | + // [weakVC dismissViewControllerAnimated:true completion:nil]; | ||
| 763 | + // }]; | ||
| 764 | + // | ||
| 765 | + // [self presentViewController:imagePickerVC animated:true completion:nil]; | ||
| 766 | +} | ||
| 767 | + | ||
| 768 | + | ||
| 769 | + | ||
| 770 | +//重新拍照或录制 | ||
| 771 | +- (void)onRetake | ||
| 772 | +{ | ||
| 773 | + [self.session startRunning]; | ||
| 774 | + [self focusAtPoint:self.view.center]; | ||
| 775 | + | ||
| 776 | + /// 摄像头缩放 | ||
| 777 | + NSError *error = nil; | ||
| 778 | + [self.device lockForConfiguration:&error]; | ||
| 779 | + if (!error) { | ||
| 780 | + self.device.videoZoomFactor = 1.0f; | ||
| 781 | + [self.device unlockForConfiguration]; | ||
| 782 | + } | ||
| 783 | +} | ||
| 784 | + | ||
| 785 | +#pragma mark - 请求测试 | ||
| 786 | + | ||
| 787 | +- (void)requestWithImage:(UIImage *)image type:(NSString *)type{ | ||
| 788 | + | ||
| 789 | + NSData *imageData = UIImageJPEGRepresentation(image, 1.0f); | ||
| 790 | + NSString *encodedImageStr = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; | ||
| 791 | + | ||
| 792 | + NSString *picStr = encodedImageStr; | ||
| 793 | + picStr = [picStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //去除掉首尾的空白字符和换行字符 | ||
| 794 | + picStr = [picStr stringByReplacingOccurrencesOfString:@"\r" withString:@""]; | ||
| 795 | + picStr = [picStr stringByReplacingOccurrencesOfString:@"\n" withString:@""]; | ||
| 796 | + //str就是去掉的string | ||
| 797 | + | ||
| 798 | + NSDictionary *params = @{ | ||
| 799 | + @"activityId":@"27", | ||
| 800 | + @"appid":@"NTY=", | ||
| 801 | + @"appsecret":@"271c9c71d9c107997cf4074d652f4262", | ||
| 802 | + @"picStr":picStr | ||
| 803 | + }.copy; | ||
| 804 | + | ||
| 805 | + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil]; | ||
| 806 | + NSString *jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]; | ||
| 807 | + | ||
| 808 | + NSString *url = @"http://wmgjmewtest.iseasoon.com/mobile-web-user/ws/mobile/v1/active/scan"; | ||
| 809 | + | ||
| 810 | + | ||
| 811 | + AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; | ||
| 812 | + NSMutableURLRequest*request = [[AFHTTPRequestSerializer serializer]requestWithMethod:@"post" URLString:url parameters:nil error:nil]; | ||
| 813 | + | ||
| 814 | + request.timeoutInterval=20; | ||
| 815 | + | ||
| 816 | + [request setValue:@"application/json"forHTTPHeaderField:@"Content-Type"]; | ||
| 817 | + | ||
| 818 | + //设置body | ||
| 819 | + NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; | ||
| 820 | + [request setHTTPBody:data]; | ||
| 821 | + | ||
| 822 | + // AFHTTPResponseSerializer *responseSerializer = [AFHTTPResponseSerializer serializer]; | ||
| 823 | + // responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", | ||
| 824 | + // @"text/html", | ||
| 825 | + // @"text/json", | ||
| 826 | + // @"text/javascript", | ||
| 827 | + // @"text/plain", | ||
| 828 | + // nil]; | ||
| 829 | + // manager.responseSerializer = responseSerializer; | ||
| 830 | + [[manager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) { | ||
| 831 | + | ||
| 832 | + } downloadProgress:^(NSProgress * _Nonnull downloadProgress) { | ||
| 833 | + | ||
| 834 | + } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { | ||
| 835 | + | ||
| 836 | + [self.imageView removeFromSuperview]; | ||
| 837 | + | ||
| 838 | + self -> mGetPicture = NO; | ||
| 839 | + | ||
| 840 | + if (error) { | ||
| 841 | + NSLog(@"有错误"); | ||
| 842 | + }else { | ||
| 843 | + NSLog(@"没错误"); | ||
| 844 | + NSLog(@"输出内容%@",responseObject[@"msg"]); | ||
| 845 | + | ||
| 846 | + if ( [[NSString stringWithFormat:@"%@",responseObject[@"code"]] isEqualToString:@"1"]) { | ||
| 847 | + | ||
| 848 | + }else { | ||
| 849 | + if ([type isEqualToString:@"2"]) { | ||
| 850 | + [self startVideoCapture]; | ||
| 851 | + } | ||
| 852 | + | ||
| 853 | + } | ||
| 854 | + | ||
| 855 | + } | ||
| 856 | + | ||
| 857 | + | ||
| 858 | + | ||
| 859 | + }] resume]; | ||
| 860 | + | ||
| 861 | + | ||
| 862 | + | ||
| 863 | +} | ||
| 864 | + | ||
| 865 | +- (NSString *)jsonToString:(id)data { | ||
| 866 | + if(data == nil) { return nil; } | ||
| 867 | + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:NSJSONWritingPrettyPrinted error:nil]; | ||
| 868 | + return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; | ||
| 869 | +} | ||
| 870 | + | ||
| 871 | + | ||
| 872 | +#pragma mark - 懒加载 | ||
| 873 | +- (UIImageView *)imageView { | ||
| 874 | + if (!_imageView) { | ||
| 875 | + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 200, 0,200, 200)]; | ||
| 876 | + [_imageView setBackgroundColor:[UIColor yellowColor]]; | ||
| 877 | + _imageView.contentMode = UIViewContentModeScaleToFill; | ||
| 878 | + } | ||
| 879 | + return _imageView; | ||
| 880 | + | ||
| 881 | + | ||
| 882 | +} | ||
| 883 | + | ||
| 884 | +- (void)didReceiveMemoryWarning { | ||
| 885 | + [super didReceiveMemoryWarning]; | ||
| 886 | + // Dispose of any resources that can be recreated. | ||
| 887 | +} | ||
| 888 | + | ||
| 889 | + | ||
| 890 | +@end |
CNLiveScanGoodsCamera/Classes/ReplaceMe.m deleted
100644 → 0
Example/CNLiveScanGoodsCamera.xcodeproj/project.pbxproj
| @@ -37,11 +37,11 @@ | @@ -37,11 +37,11 @@ | ||
| 37 | /* End PBXContainerItemProxy section */ | 37 | /* End PBXContainerItemProxy section */ |
| 38 | 38 | ||
| 39 | /* Begin PBXFileReference section */ | 39 | /* Begin PBXFileReference section */ |
| 40 | - 0219BFEFD039D44D84A6C11A /* CNLiveScanGoodsCamera.podspec */ = {isa = PBXFileReference; includeInIndex = 1; name = CNLiveScanGoodsCamera.podspec; path = ../CNLiveScanGoodsCamera.podspec; sourceTree = "<group>"; }; | 40 | + 0219BFEFD039D44D84A6C11A /* CNLiveScanGoodsCamera.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLiveScanGoodsCamera.podspec; path = ../CNLiveScanGoodsCamera.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; |
| 41 | 02994EFFD2FA8A034AD1D0B9 /* Pods-CNLiveScanGoodsCamera_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveScanGoodsCamera_Example.release.xcconfig"; path = "Target Support Files/Pods-CNLiveScanGoodsCamera_Example/Pods-CNLiveScanGoodsCamera_Example.release.xcconfig"; sourceTree = "<group>"; }; | 41 | 02994EFFD2FA8A034AD1D0B9 /* Pods-CNLiveScanGoodsCamera_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveScanGoodsCamera_Example.release.xcconfig"; path = "Target Support Files/Pods-CNLiveScanGoodsCamera_Example/Pods-CNLiveScanGoodsCamera_Example.release.xcconfig"; sourceTree = "<group>"; }; |
| 42 | 219C510B7AE998A3840A1604 /* Pods_CNLiveScanGoodsCamera_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveScanGoodsCamera_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | 42 | 219C510B7AE998A3840A1604 /* Pods_CNLiveScanGoodsCamera_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveScanGoodsCamera_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 43 | - 44D8FE3B8C9004785D9E092E /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; name = README.md; path = ../README.md; sourceTree = "<group>"; }; | ||
| 44 | - 4B4229A5D728BDAC6B4394CD /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; }; | 43 | + 44D8FE3B8C9004785D9E092E /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; |
| 44 | + 4B4229A5D728BDAC6B4394CD /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; }; | ||
| 45 | 6003F58A195388D20070C39A /* CNLiveScanGoodsCamera_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CNLiveScanGoodsCamera_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; | 45 | 6003F58A195388D20070C39A /* CNLiveScanGoodsCamera_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CNLiveScanGoodsCamera_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 46 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; | 46 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; |
| 47 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; | 47 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; |
| @@ -193,7 +193,6 @@ | @@ -193,7 +193,6 @@ | ||
| 193 | 9C1C101E0458C2E2EE15B370 /* Pods-CNLiveScanGoodsCamera_Tests.debug.xcconfig */, | 193 | 9C1C101E0458C2E2EE15B370 /* Pods-CNLiveScanGoodsCamera_Tests.debug.xcconfig */, |
| 194 | E2A9C3755B8BC2060481853A /* Pods-CNLiveScanGoodsCamera_Tests.release.xcconfig */, | 194 | E2A9C3755B8BC2060481853A /* Pods-CNLiveScanGoodsCamera_Tests.release.xcconfig */, |
| 195 | ); | 195 | ); |
| 196 | - name = Pods; | ||
| 197 | path = Pods; | 196 | path = Pods; |
| 198 | sourceTree = "<group>"; | 197 | sourceTree = "<group>"; |
| 199 | }; | 198 | }; |
| @@ -248,6 +247,9 @@ | @@ -248,6 +247,9 @@ | ||
| 248 | LastUpgradeCheck = 0720; | 247 | LastUpgradeCheck = 0720; |
| 249 | ORGANIZATIONNAME = "梁星国"; | 248 | ORGANIZATIONNAME = "梁星国"; |
| 250 | TargetAttributes = { | 249 | TargetAttributes = { |
| 250 | + 6003F589195388D20070C39A = { | ||
| 251 | + DevelopmentTeam = 94X49GG3ZW; | ||
| 252 | + }; | ||
| 251 | 6003F5AD195388D20070C39A = { | 253 | 6003F5AD195388D20070C39A = { |
| 252 | TestTargetID = 6003F589195388D20070C39A; | 254 | TestTargetID = 6003F589195388D20070C39A; |
| 253 | }; | 255 | }; |
| @@ -258,6 +260,7 @@ | @@ -258,6 +260,7 @@ | ||
| 258 | developmentRegion = English; | 260 | developmentRegion = English; |
| 259 | hasScannedForEncodings = 0; | 261 | hasScannedForEncodings = 0; |
| 260 | knownRegions = ( | 262 | knownRegions = ( |
| 263 | + English, | ||
| 261 | en, | 264 | en, |
| 262 | Base, | 265 | Base, |
| 263 | ); | 266 | ); |
| @@ -302,10 +305,14 @@ | @@ -302,10 +305,14 @@ | ||
| 302 | ); | 305 | ); |
| 303 | inputPaths = ( | 306 | inputPaths = ( |
| 304 | "${PODS_ROOT}/Target Support Files/Pods-CNLiveScanGoodsCamera_Example/Pods-CNLiveScanGoodsCamera_Example-frameworks.sh", | 307 | "${PODS_ROOT}/Target Support Files/Pods-CNLiveScanGoodsCamera_Example/Pods-CNLiveScanGoodsCamera_Example-frameworks.sh", |
| 308 | + "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework", | ||
| 309 | + "${BUILT_PRODUCTS_DIR}/CNLiveRequestBastKit/CNLiveRequestBastKit.framework", | ||
| 305 | "${BUILT_PRODUCTS_DIR}/CNLiveScanGoodsCamera/CNLiveScanGoodsCamera.framework", | 310 | "${BUILT_PRODUCTS_DIR}/CNLiveScanGoodsCamera/CNLiveScanGoodsCamera.framework", |
| 306 | ); | 311 | ); |
| 307 | name = "[CP] Embed Pods Frameworks"; | 312 | name = "[CP] Embed Pods Frameworks"; |
| 308 | outputPaths = ( | 313 | outputPaths = ( |
| 314 | + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework", | ||
| 315 | + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveRequestBastKit.framework", | ||
| 309 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveScanGoodsCamera.framework", | 316 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveScanGoodsCamera.framework", |
| 310 | ); | 317 | ); |
| 311 | runOnlyForDeploymentPostprocessing = 0; | 318 | runOnlyForDeploymentPostprocessing = 0; |
| @@ -494,6 +501,7 @@ | @@ -494,6 +501,7 @@ | ||
| 494 | baseConfigurationReference = E9D98969971014AB6E456E8F /* Pods-CNLiveScanGoodsCamera_Example.debug.xcconfig */; | 501 | baseConfigurationReference = E9D98969971014AB6E456E8F /* Pods-CNLiveScanGoodsCamera_Example.debug.xcconfig */; |
| 495 | buildSettings = { | 502 | buildSettings = { |
| 496 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 503 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 504 | + DEVELOPMENT_TEAM = 94X49GG3ZW; | ||
| 497 | GCC_PRECOMPILE_PREFIX_HEADER = YES; | 505 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
| 498 | GCC_PREFIX_HEADER = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Prefix.pch"; | 506 | GCC_PREFIX_HEADER = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Prefix.pch"; |
| 499 | INFOPLIST_FILE = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Info.plist"; | 507 | INFOPLIST_FILE = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Info.plist"; |
| @@ -510,6 +518,7 @@ | @@ -510,6 +518,7 @@ | ||
| 510 | baseConfigurationReference = 02994EFFD2FA8A034AD1D0B9 /* Pods-CNLiveScanGoodsCamera_Example.release.xcconfig */; | 518 | baseConfigurationReference = 02994EFFD2FA8A034AD1D0B9 /* Pods-CNLiveScanGoodsCamera_Example.release.xcconfig */; |
| 511 | buildSettings = { | 519 | buildSettings = { |
| 512 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 520 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 521 | + DEVELOPMENT_TEAM = 94X49GG3ZW; | ||
| 513 | GCC_PRECOMPILE_PREFIX_HEADER = YES; | 522 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
| 514 | GCC_PREFIX_HEADER = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Prefix.pch"; | 523 | GCC_PREFIX_HEADER = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Prefix.pch"; |
| 515 | INFOPLIST_FILE = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Info.plist"; | 524 | INFOPLIST_FILE = "CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Info.plist"; |
Example/CNLiveScanGoodsCamera/CNLIVEViewController.m
| @@ -7,9 +7,12 @@ | @@ -7,9 +7,12 @@ | ||
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | #import "CNLIVEViewController.h" | 9 | #import "CNLIVEViewController.h" |
| 10 | +#import "CNLiveScanGoodsCameraController.h" | ||
| 10 | 11 | ||
| 11 | @interface CNLIVEViewController () | 12 | @interface CNLIVEViewController () |
| 12 | 13 | ||
| 14 | +@property (strong, nonatomic) UIButton *enterBtn; | ||
| 15 | + | ||
| 13 | @end | 16 | @end |
| 14 | 17 | ||
| 15 | @implementation CNLIVEViewController | 18 | @implementation CNLIVEViewController |
| @@ -18,6 +21,23 @@ | @@ -18,6 +21,23 @@ | ||
| 18 | { | 21 | { |
| 19 | [super viewDidLoad]; | 22 | [super viewDidLoad]; |
| 20 | // Do any additional setup after loading the view, typically from a nib. | 23 | // Do any additional setup after loading the view, typically from a nib. |
| 24 | + | ||
| 25 | + [self.view addSubview:self.enterBtn]; | ||
| 26 | + | ||
| 27 | + [self.enterBtn addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +- (void)buttonAction:(UIButton *)sender { | ||
| 33 | + CNLiveScanGoodsCameraController *vc = [[CNLiveScanGoodsCameraController alloc]init]; | ||
| 34 | + vc.modalPresentationStyle = UIModalPresentationFullScreen; | ||
| 35 | + [self presentViewController:vc animated:YES completion:^{ | ||
| 36 | + | ||
| 37 | + }]; | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 21 | } | 41 | } |
| 22 | 42 | ||
| 23 | - (void)didReceiveMemoryWarning | 43 | - (void)didReceiveMemoryWarning |
| @@ -26,4 +46,16 @@ | @@ -26,4 +46,16 @@ | ||
| 26 | // Dispose of any resources that can be recreated. | 46 | // Dispose of any resources that can be recreated. |
| 27 | } | 47 | } |
| 28 | 48 | ||
| 49 | + | ||
| 50 | +- (UIButton *)enterBtn { | ||
| 51 | + if (!_enterBtn) { | ||
| 52 | + _enterBtn = [UIButton buttonWithType:UIButtonTypeCustom]; | ||
| 53 | + _enterBtn.frame = CGRectMake(100, 100, 100, 100); | ||
| 54 | + [_enterBtn setBackgroundColor:[UIColor yellowColor]]; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + return _enterBtn;; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | + | ||
| 29 | @end | 61 | @end |
Example/CNLiveScanGoodsCamera/CNLiveScanGoodsCamera-Info.plist
| @@ -2,8 +2,35 @@ | @@ -2,8 +2,35 @@ | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 3 | <plist version="1.0"> | 3 | <plist version="1.0"> |
| 4 | <dict> | 4 | <dict> |
| 5 | + <key>NSBluetoothAlwaysUsageDescription</key> | ||
| 6 | + <string>需要允许开启蓝牙才能对音箱使用配对及配网功能</string> | ||
| 7 | + <key>NSBluetoothPeripheralUsageDescription</key> | ||
| 8 | + <string>需要允许开启蓝牙才能对音箱使用配对及配网功能</string> | ||
| 9 | + <key>NSCameraUsageDescription</key> | ||
| 10 | + <string>需要允许开启相机才能在发布生活圈或聊天时使用录制视频和拍照功能</string> | ||
| 11 | + <key>NSContactsUsageDescription</key> | ||
| 12 | + <string>需要允许访问通讯录才能获取手机联系人中的网家家用户</string> | ||
| 13 | + <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> | ||
| 14 | + <string>需要允许使用您的位置信息才能获取您所在的城市</string> | ||
| 15 | + <key>NSLocationAlwaysUsageDescription</key> | ||
| 16 | + <string>需要允许使用您的位置信息才能获取您所在的城市</string> | ||
| 17 | + <key>NSLocationWhenInUseUsageDescription</key> | ||
| 18 | + <string>需要允许使用您的位置信息才能获取您所在的城市</string> | ||
| 19 | + <key>NSMicrophoneUsageDescription</key> | ||
| 20 | + <string>需要允许开启麦克风才能使用录制视频和语音等服务</string> | ||
| 21 | + <key>NSMotionUsageDescription</key> | ||
| 22 | + <string>需要允许访问运动与健身才能在参加线上跑步赛事时记录您的步数信息</string> | ||
| 23 | + <key>NSPhotoLibraryAddUsageDescription</key> | ||
| 24 | + <string>需要允许打开相册才能访问相册照片和保存照片</string> | ||
| 25 | + <key>NSPhotoLibraryUsageDescription</key> | ||
| 26 | + <string>需要允许打开相册才能访问相册照片和保存照片</string> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | 27 | <key>CFBundleDevelopmentRegion</key> |
| 6 | <string>en</string> | 28 | <string>en</string> |
| 29 | + <key>NSAppTransportSecurity</key> | ||
| 30 | + <dict> | ||
| 31 | + <key>NSAllowsArbitraryLoads</key> | ||
| 32 | + <true/> | ||
| 33 | + </dict> | ||
| 7 | <key>CFBundleDisplayName</key> | 34 | <key>CFBundleDisplayName</key> |
| 8 | <string>${PRODUCT_NAME}</string> | 35 | <string>${PRODUCT_NAME}</string> |
| 9 | <key>CFBundleExecutable</key> | 36 | <key>CFBundleExecutable</key> |
Example/Podfile
| 1 | use_frameworks! | 1 | use_frameworks! |
| 2 | 2 | ||
| 3 | -platform :ios, '8.0' | 3 | +platform :ios, '9.0' |
| 4 | + | ||
| 5 | +source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git' | ||
| 6 | +#source 'https://github.com/CocoaPods/Specs.git' | ||
| 7 | +source 'http://bj.gitlab.cnlive.com/ios-team/CNLiveRepos.git' | ||
| 8 | +source 'http://bj.gitlab.cnlive.com/DSIOSTeam/DSSpecRepos.git' | ||
| 4 | 9 | ||
| 5 | target 'CNLiveScanGoodsCamera_Example' do | 10 | target 'CNLiveScanGoodsCamera_Example' do |
| 6 | pod 'CNLiveScanGoodsCamera', :path => '../' | 11 | pod 'CNLiveScanGoodsCamera', :path => '../' |