//
|
// 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 <AssetsLibrary/AssetsLibrary.h>
|
#import <Photos/Photos.h>
|
|
@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<LBXScanResult*> *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<LBXScanResult*> *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<LBXScanResult*> *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<LBXScanResult*> *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
|