// // LBXScanWrapper.m // // // Created by lbxia on 15/3/4. // Copyright (c) 2015年 lbxia. All rights reserved. // #import "LBXScanWrapper.h" #import "LBXScanNative.h" #import "ZXingWrapper.h" #import "ZXBarcodeFormat.h" #import #import @interface LBXScanWrapper() { } //ios7之后native封装 @property(nonatomic,strong)LBXScanNative* scanNativeObj; //ZXing封装 @property(nonatomic,strong)ZXingWrapper *scanZXingObj; /** @brief 扫码类型 */ @property(nonatomic,strong)NSArray* arrayBarCodeType; //是否指定使用ZXing库 @property(nonatomic,assign)BOOL isUseZXingLib; @end @implementation LBXScanWrapper + (BOOL)isSysIos7Later { // return NO; if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) return YES; return NO; } + (BOOL)isSysIos8Later { // return NO; if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) return YES; return NO; } - (void)setNeedCaptureImage:(BOOL)isNeedCaputureImg { if (_scanNativeObj) { [_scanNativeObj setNeedCaptureImage:isNeedCaputureImg]; } } - (instancetype)initWithPreView:(UIView*)preView ArrayObjectType:(NSArray*)arrayBarCodeType cropRect:(CGRect)cropRect success:(void(^)(NSArray *array))blockScanResult { if (self = [super init]) { self.isUseZXingLib = NO; self.arrayBarCodeType = arrayBarCodeType; CGRect frame = preView.frame; frame.origin = CGPointZero; if ( [LBXScanWrapper isSysIos7Later] ) { _scanNativeObj = [[LBXScanNative alloc]initWithPreView:preView ObjectType:arrayBarCodeType cropRect:cropRect success:^(NSArray *array) { if (blockScanResult) { blockScanResult(array); } }]; } else { _scanZXingObj = [[ZXingWrapper alloc]initWithPreView:preView block:^(ZXBarcodeFormat barcodeFormat, NSString *str, UIImage *scanImg) { //TODO:ZXing统一识别所有的码 if ( blockScanResult ) { NSString *barCodeType = [LBXScanWrapper convertZXBarcodeFormat:barcodeFormat]; LBXScanResult *result = [[LBXScanResult alloc]initWithScanString:str imgScan:scanImg barCodeType:barCodeType]; blockScanResult(@[result]); } }]; } } return self; } /** @brief 初始化相机,并指定使用ZXing库识别各种码 @param preView 视频显示View @param blockScanResult 返回结果 @return LBXScanVendor */ - (instancetype)initZXingWithPreView:(UIView *)preView success:(void(^)(NSArray *array))blockScanResult { if (self = [super init]) { self.isUseZXingLib = YES; _scanZXingObj = [[ZXingWrapper alloc]initWithPreView:preView block:^(ZXBarcodeFormat barcodeFormat, NSString *str, UIImage *scanImg) { NSString *barCodeType = [LBXScanWrapper convertZXBarcodeFormat:barcodeFormat]; if (blockScanResult) { blockScanResult(@[str,scanImg,barCodeType]); } }]; } return self; } /*! * 开始扫码 */ - (void)startScan { if ( [LBXScanWrapper isSysIos7Later] && !_isUseZXingLib ) [_scanNativeObj startScan]; else [_scanZXingObj start]; } /*! * 停止扫码 */ - (void)stopScan { if ( [LBXScanWrapper isSysIos7Later] && !_isUseZXingLib ) [_scanNativeObj stopScan]; else [_scanZXingObj stop]; } - (void)openFlash:(BOOL)bOpen { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if ([device hasTorch] && [device hasFlash]) { if ([LBXScanWrapper isSysIos7Later] && !_isUseZXingLib ) [_scanNativeObj setTorch:bOpen]; else [_scanZXingObj openTorch:bOpen]; } } - (void)openOrCloseFlash { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if ([device hasTorch] && [device hasFlash]) { if ([LBXScanWrapper isSysIos7Later] && !_isUseZXingLib ) [_scanNativeObj changeTorch]; else [_scanZXingObj openOrCloseTorch]; } } /*! * 修改扫码类型 * * @param objType 扫码类型 */ - (void)changeScanObjType:(NSArray*)objType { if ( [LBXScanWrapper isSysIos7Later] && !_isUseZXingLib ) { [_scanNativeObj changeScanType:objType]; } } //识别图片上的二维码 /*! * 识别各种码图片 * * @param image 图像 * @param block 返回识别结果 */ + (void)recognizeImage:(UIImage*)image success:(void(^)(NSArray *array))block; { __block UIImage* tmpImg = image; [ZXingWrapper recognizeImage:image block:^(ZXBarcodeFormat barCodeFormat,NSString* str) { NSString *barCodeType = [LBXScanWrapper convertZXBarcodeFormat:barCodeFormat]; if (block) { LBXScanResult *result = [[LBXScanResult alloc]initWithScanString:str imgScan:tmpImg barCodeType:barCodeType]; block(@[result]); } }]; } #pragma mark- 震动、声音效果 #define SOUNDID 1109 //1012 -iphone 1152 ipad 1109 ipad + (void)systemVibrate { AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } + (void)systemSound { AudioServicesPlaySystemSound(SOUNDID); } #pragma mark -相机、相册权限 + (BOOL)isGetCameraPermission { BOOL isCameraValid = YES; //ios7之前系统默认拥有权限 if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (authStatus == AVAuthorizationStatusDenied) { isCameraValid = NO; } } return isCameraValid; } + (BOOL)isGetPhotoPermission { if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) { ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus]; if ( author == ALAuthorizationStatusDenied ) { return NO; } return YES; } PHAuthorizationStatus authorStatus = [PHPhotoLibrary authorizationStatus]; if ( authorStatus == PHAuthorizationStatusDenied ) { return NO; } return YES; } + (NSString*)convertZXBarcodeFormat:(ZXBarcodeFormat)barCodeFormat { NSString *strAVMetadataObjectType = nil; switch (barCodeFormat) { case kBarcodeFormatQRCode: strAVMetadataObjectType = AVMetadataObjectTypeQRCode; break; case kBarcodeFormatEan13: strAVMetadataObjectType = AVMetadataObjectTypeEAN13Code; break; case kBarcodeFormatEan8: strAVMetadataObjectType = AVMetadataObjectTypeEAN8Code; break; case kBarcodeFormatPDF417: strAVMetadataObjectType = AVMetadataObjectTypePDF417Code; break; case kBarcodeFormatAztec: strAVMetadataObjectType = AVMetadataObjectTypeAztecCode; break; case kBarcodeFormatCode39: strAVMetadataObjectType = AVMetadataObjectTypeCode39Code; break; case kBarcodeFormatCode93: strAVMetadataObjectType = AVMetadataObjectTypeCode93Code; break; case kBarcodeFormatCode128: strAVMetadataObjectType = AVMetadataObjectTypeCode128Code; break; case kBarcodeFormatDataMatrix: strAVMetadataObjectType = AVMetadataObjectTypeDataMatrixCode; break; case kBarcodeFormatITF: strAVMetadataObjectType = AVMetadataObjectTypeITF14Code; break; case kBarcodeFormatRSS14: break; case kBarcodeFormatRSSExpanded: break; case kBarcodeFormatUPCA: break; case kBarcodeFormatUPCE: strAVMetadataObjectType = AVMetadataObjectTypeUPCECode; break; default: break; } return strAVMetadataObjectType; } + (ZXBarcodeFormat)convertCodeFomratToZXBarcodeFormat:(NSString*)strCodeType { if ([strCodeType isEqualToString:AVMetadataObjectTypeQRCode]) { return kBarcodeFormatQRCode; } if ([strCodeType isEqualToString:AVMetadataObjectTypeEAN13Code]) { return kBarcodeFormatEan13; } if ([strCodeType isEqualToString:AVMetadataObjectTypeEAN8Code]) { return kBarcodeFormatEan8; } if ([strCodeType isEqualToString:AVMetadataObjectTypePDF417Code]) { return kBarcodeFormatPDF417; } if ([strCodeType isEqualToString:AVMetadataObjectTypeAztecCode]) { return kBarcodeFormatAztec; } if ([strCodeType isEqualToString:AVMetadataObjectTypeCode39Code]) { return kBarcodeFormatCode39; } if ([strCodeType isEqualToString:AVMetadataObjectTypeCode93Code]) { return kBarcodeFormatCode93; } //支付宝付款码条形码格式 if ([strCodeType isEqualToString:AVMetadataObjectTypeCode128Code]) { return kBarcodeFormatCode128; } if ([strCodeType isEqualToString:AVMetadataObjectTypeDataMatrixCode]) { return kBarcodeFormatDataMatrix; } if ([strCodeType isEqualToString:AVMetadataObjectTypeUPCECode]) { return kBarcodeFormatUPCE; } return kBarcodeFormatQRCode; } #pragma mark -生成二维码 /*! * 生成二维码 * * @param str 二维码字符串 * @param size 二维码图片大小 * * @return 返回生成的图像 */ + (UIImage*)createQRWithString:(NSString*)str size:(CGSize)size { if ([LBXScanWrapper isSysIos7Later]) { return [LBXScanWrapper createNonInterpolatedUIImageFormCIImage:[LBXScanWrapper createQRForString:str] withSize:size.width]; } else return [ZXingWrapper createCodeWithString:str size:size CodeFomart:kBarcodeFormatQRCode]; } + (UIImage*)createCodeWithString:(NSString*)str size:(CGSize)size CodeFomart:(NSString*)format { ZXBarcodeFormat zxformat = [LBXScanWrapper convertCodeFomratToZXBarcodeFormat:format]; return [ZXingWrapper createCodeWithString:str size:size CodeFomart:zxformat]; } /** @brief 图像中间加logo图片 @param srcImg 原图像 @param LogoImage logo图像 @param logoSize logo图像尺寸 @return 加Logo的图像 */ + (UIImage*)addImageLogo:(UIImage*)srcImg centerLogoImage:(UIImage*)LogoImage logoSize:(CGSize)logoSize { //UIGraphicsBeginImageContext(srcImg.size); UIGraphicsBeginImageContextWithOptions(srcImg.size, NO, [[UIScreen mainScreen] scale]); [srcImg drawInRect:CGRectMake(0, 0, srcImg.size.width, srcImg.size.height)]; CGRect rect = CGRectMake(srcImg.size.width/2 - logoSize.width/2, srcImg.size.height/2-logoSize.height/2, logoSize.width, logoSize.height); [LogoImage drawInRect:rect]; UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return resultingImage; } /** * 通过UIImageView形式添加Logo * * @param srcImgView 显示二维码的UIImageView * @param logoView logo的UIImageView * @param logoSize logo大小 */ + (void)addImageViewLogo:(UIImageView*)srcImgView centerLogoImageView:(UIImageView*)logoView logoSize:(CGSize)logoSize { logoView.center = srcImgView.center; logoView.bounds = CGRectMake(0, 0, logoSize.width, logoSize.height); [srcImgView addSubview:logoView]; } #pragma mark --UIImage 圆角 + (UIImage *)roundedCornerImageWithCornerRadius:(CGFloat)cornerRadius srcImg:(UIImage*)srcImg { CGFloat w = srcImg.size.width; CGFloat h = srcImg.size.height; CGFloat scale = [UIScreen mainScreen].scale; // 防止圆角半径小于0,或者大于宽/高中较小值的一半。 if (cornerRadius < 0) cornerRadius = 0; else if (cornerRadius > MIN(w, h)) cornerRadius = MIN(w, h) / 2.; UIImage *image = nil; CGRect imageFrame = CGRectMake(0., 0., w, h); UIGraphicsBeginImageContextWithOptions(srcImg.size, NO, scale); [[UIBezierPath bezierPathWithRoundedRect:imageFrame cornerRadius:cornerRadius] addClip]; [srcImg drawInRect:imageFrame]; image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } //下面引用自 https://github.com/yourtion/Demo_CustomQRCode #pragma mark - InterpolatedUIImage + (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size { CGRect extent = CGRectIntegral(image.extent); CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent)); // 创建bitmap; size_t width = CGRectGetWidth(extent) * scale; size_t height = CGRectGetHeight(extent) * scale; CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone); CGColorSpaceRelease(cs); CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef bitmapImage = [context createCGImage:image fromRect:extent]; CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone); CGContextScaleCTM(bitmapRef, scale, scale); CGContextDrawImage(bitmapRef, extent, bitmapImage); // 保存bitmap到图片 CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef); CGContextRelease(bitmapRef); CGImageRelease(bitmapImage); UIImage *aImage = [UIImage imageWithCGImage:scaledImage]; CGImageRelease(scaledImage); return aImage; } #pragma mark - QRCodeGenerator + (CIImage *)createQRForString:(NSString *)qrString { NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding]; // 创建filter CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; // 设置内容和纠错级别 [qrFilter setValue:stringData forKey:@"inputMessage"]; [qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"]; // 返回CIImage return qrFilter.outputImage; } #pragma mark - imageToTransparent void ProviderReleaseData (void *info, const void *data, size_t size){ free((void*)data); } + (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{ const int imageWidth = image.size.width; const int imageHeight = image.size.height; size_t bytesPerRow = imageWidth * 4; uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast); CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage); // 遍历像素 int pixelNum = imageWidth * imageHeight; uint32_t* pCurPtr = rgbImageBuf; for (int i = 0; i < pixelNum; i++, pCurPtr++){ if ((*pCurPtr & 0xFFFFFF00) < 0x99999900) // 将白色变成透明 { // 改成下面的代码,会将图片转成想要的颜色 uint8_t* ptr = (uint8_t*)pCurPtr; ptr[3] = red; //0~255 ptr[2] = green; ptr[1] = blue; } else { uint8_t* ptr = (uint8_t*)pCurPtr; ptr[0] = 0; } } // 输出图片 CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData); CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, NULL, true, kCGRenderingIntentDefault); CGDataProviderRelease(dataProvider); UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef]; // 清理空间 CGImageRelease(imageRef); CGContextRelease(context); CGColorSpaceRelease(colorSpace); return resultUIImage; } #pragma mark - 生成二维码,背景色及二维码颜色设置 //引用自:http://www.jianshu.com/p/e8f7a257b612 + (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size QRColor:(UIColor*)qrColor bkColor:(UIColor*)bkColor { NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding]; //生成 CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; [qrFilter setValue:stringData forKey:@"inputMessage"]; [qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"]; //上色 CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor" keysAndValues: @"inputImage",qrFilter.outputImage, @"inputColor0",[CIColor colorWithCGColor:qrColor.CGColor], @"inputColor1",[CIColor colorWithCGColor:bkColor.CGColor], nil]; CIImage *qrImage = colorFilter.outputImage; //绘制 CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent]; UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage); UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGImageRelease(cgImage); return codeImage; } /** @brief 获取摄像机最大拉远镜头 @return 放大系数 */ - (CGFloat)getVideoMaxScale { if (self.scanNativeObj) { return [self.scanNativeObj getVideoMaxScale]; } return 1.0; } /** @brief 拉近拉远镜头 @param scale 系数 */ - (void)setVideoScale:(CGFloat)scale { if (self.scanNativeObj) { [self.scanNativeObj setVideoScale:scale]; } } @end