iOS 二維碼掃描

首先我們來想一想具體的步驟,大概流程應該是:1.打開設備的攝像頭-->2.進行二維碼圖像捕獲-->3.獲取捕獲的圖像進行解析-->4.取得解析結果進行后續處理。這些流程需要用到AVFoundation這個庫,注意導入。

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//獲取一個AVCaptureDeviceInput對象,將上面的'攝像頭'作為輸入設備
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil];
//拍完照片以后,需要一個AVCaptureMetadataOutput對象將獲取的'圖像'輸出,以便進行對其解析
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
//獲取輸出需要設置代理,在代理方法中獲取
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//設置輸出類型,如AVMetadataObjectTypeQRCode是二維碼類型,下面還增加了條形碼。如果掃描的是條形碼也能識別
output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                    AVMetadataObjectTypeEAN8Code,
                                    AVMetadataObjectTypeCode128Code,
                                    AVMetadataObjectTypeQRCode];
 //設置掃描區域
//               Y <------------------+ 坐標軸
//                                    |
//                                    |
//                                    |
//                                    |
//                                    |
//                                    |
//                                    |
//                                    V
//                                    X
                //設置要點 x和y互換 H和W互換
CGFloat leadSpace = (kScreenWidth - MiddleWidth)/ 2;
[_output setRectOfInterest:CGRectMake(0.2, leadSpace / kScreenWidth ,0.8 * kScreenWidth / kScreenHeight, 0.8)];

上面完成了捕獲的設置,但是并未正在開始'掃描',要完成一次掃描的過程,需要用到AVCaptureSession這個類,這個session類把一次掃描看做一次會話,會話開始后才是正在的'掃描'開始,具體代碼如下。

AVCaptureSession *session = [[AVCaptureSession alloc]init];
[session setSessionPreset:AVCaptureSessionPresetHigh];//掃描的質量
if ([session canAddInput:input]){
   [session addInput:input];//將輸入添加到會話中
}  
if ([session canAddOutput:output]){
   [session addOutput:output];//將輸出添加到會話中
}

接下來我們要做的不是立即開始會話(開始掃描),如果你現在調用會話的startRunning方法的話,你會發現屏幕是一片黑,這時由于我們還沒有設置相機的取景器的大小。設置取景器需要用到AVCaptureVideoPreviewLayer這個類。具體代碼如下:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    [self.session stopRunning];//停止會話

    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
        NSString *result = obj.stringValue;//這就是掃描的結果啦
        //對結果進行處理...
    }
}

加入照明功能能讓用戶在光照條件不好的情況下順利的進行進行掃描操作,代碼如下:

////設置閃光燈
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSError *error;
    if (_device.hasTorch) {  // 判斷設備是否有閃光燈
        BOOL b = [_device lockForConfiguration:&error];
        if (!b) {
            if (error) {
                NSLog(@"lock torch configuration error:%@", error.localizedDescription);
            }
            return;
        }
        _device.torchMode = (_device.torchMode == AVCaptureTorchModeOff ? AVCaptureTorchModeOn : AVCaptureTorchModeOff);
        [_device unlockForConfiguration];
    }
}

從圖片中直接讀取二維碼的功能在iOS7上面蘋果沒有實現,不過在iOS上已經填補了這一功能。主要用到的是讀取主要用到CoreImage。

//獲取圖片中的二維碼信息
- (NSString *)scQRReaderForImage:(UIImage *)qrimage{
    CIContext *context = [CIContext contextWithOptions:nil];
    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
    CIImage *image = [CIImage imageWithCGImage:qrimage.CGImage];
    NSArray *features = [detector featuresInImage:image];
    CIQRCodeFeature *feature = [features firstObject];
    NSString *result = feature.messageString;
    return result;
}

生成二維碼和從圖片中讀取二維碼一樣要用到CoreImage,具體步驟如下:

- (UIImage *)makeQRCodeForString:(NSString *)string{
    NSString *text = string;
    NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
    //生成
    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [qrFilter setValue:stringData forKey:@"inputMessage"];//通過kvo方式給一個字符串,生成二維碼
    [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];//設置二維碼的糾錯水平,越高糾錯水平越高,可以污損的范圍越大 L:7% M:15% Q:25% H:30%
    //二維碼顏色
    UIColor *onColor = [UIColor redColor];
    UIColor *offColor = [UIColor blueColor];
    //上色,如果只要白底黑塊的QRCode可以跳過這一步
    CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
                                       keysAndValues:
                             @"inputImage",qrFilter.outputImage,
                             @"inputColor0",[CIColor colorWithCGColor:onColor.CGColor],
                             @"inputColor1",[CIColor colorWithCGColor:offColor.CGColor],
                             nil];
    CIImage *qrImage = colorFilter.outputImage;//拿到二維碼圖片
    //放大更清楚
    qrImage = [qrImage imageByApplyingTransform:CGAffineTransformMakeScale(20, 20)];
    NSLog(@"%@",qrImage);
    //繪制
    CGSize size = [[UIImage imageWithCIImage:qrImage] size];
    CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage  fromRect:qrImage.extent];
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    CGContextScaleCTM(context, 1.0, -1.0);//生成的QRCode就是上下顛倒的,需要翻轉一下
    CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
    
    UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRelease(cgImage);
    
    return codeImage;
}

對圖片添加水印

- (UIImage *)addImageToSuperImage:(UIImage *)superImage withSubImage:(UIImage *)subImage andSubImagePosition:(CGRect)posRect{
    
    UIGraphicsBeginImageContext(superImage.size);
    [superImage drawInRect:CGRectMake(0, 0, superImage.size.width, superImage.size.height)];
    //四個參數為水印圖片的位置
    [subImage drawInRect:posRect];
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resultingImage;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容

  • 一、掃描 1、 ZBar ZBar在掃描的靈敏度上,和內存的使用上相對于ZXing上都是較優的,但是對于 “圓角二...
    空白Null閱讀 1,076評論 0 2
  • 這段時間有個二維碼掃描的需求,gitHub上大神做的SDK一堆堆。不在累贅敘述。 微信的掃碼功能中,在光線很弱時,...
    浮萍兒閱讀 3,643評論 2 5
  • 以前就寫過二維碼掃描的文章,今天難得抽出來時間重新整理了一下,把所有用都的關于二維碼的都寫在這了,二維碼問題,看了...
    WWest閱讀 50,371評論 94 287
  • 相信很多小伙伴都做過二維碼的掃描生成,網上也有很多相關的Demo和博客從一開始的三方架構到后來用原生的都有,我之前...
    fuaiyi閱讀 5,308評論 1 16
  • 公司最近要添加一個二維碼掃描網頁登錄的功能,所以最近研究了一下iOS關于二維碼掃描的功能因為移動端不涉及二維碼的生...
    QL_fish閱讀 1,383評論 0 1