iOS QRcode識別及相冊圖片二維碼讀取識別

https://www.jianshu.com/p/48e44fe67c1dhtml

2016.03.30 10:32* 字數 892 閱讀 16197評論 5

最近碰到一個用戶 在使用咱們 微鏈App 的時候,在分辨率低或者頻率低的顯示器上掃不出二維碼。而後網上找了不少,試了不少,仍是沒有找出合適的方法,想一想把三種掃描(系統原生API,ZBar,ZXing)寫個Demo,作個小總結,看看從什麼地方能夠找到解決方法,也但願各位大神能給我指條明路😄。ios

對二維碼的處理及系統原生API掃描、 Zbar掃描和Zing掃描 比較git

iOS原生API

系統掃描的效率是最高,反正包括各類你見過的沒見過的碼,可是有一點我不是很清楚 iOS7 掃描二維碼能夠,但從相冊照片讀取二維碼蘋果不支持,必須是iOS8+。
https://github.com/yannickl/QRCodeReaderViewController
https://github.com/zhengjinghua/MQRCodeReaderViewControllergithub

這兩個例子已經寫的很是清楚了web

// 對於識別率的精度 就是屏幕有波浪同樣[self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];// 改爲了 下降採集頻率[self.captureSession setSessionPreset:AVCaptureSessionPreset640x480];

// 對於識別率的精度 就是屏幕有波浪同樣api

    [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];緩存

   // 改爲了 下降採集頻率app

    [self.captureSession setSessionPreset:AVCaptureSessionPreset640x480];ui

不知道 有什麼好的方法lua

/ZXing 和 ZBar

具體代碼 我就不在這裏寫了,Demo裏 都寫了,並且百度谷歌千篇一概,說說ZXing的一些用到的特色:

 

對那種小圓點的二維碼 ZXing和原生API 都是支持的,而ZBar 貌似不是支持的,反正我沒搞定。

ZXing 如今還在繼續維護 ZBar 而已經中止了

ZXing 能夠識別圖片中多個二維碼

 

ZBar中的識別率 本人以爲仍是比較低

 

//ZBar 中對 圖片中二維碼 識別

    UIImage * aImage = #所獲取的圖片#

    ZBarReaderController *read = [ZBarReaderController new];

    CGImageRef cgImageRef = aImage.CGImage;

    ZBarSymbol* symbol = nil;

    for(symbol in [read scanImage:cgImageRef]){

        qrResult = symbol.data ;

        NSLog(@"qrResult = symbol.data %@",qrResult);

    }

 

ZXing 對圓點二維碼的支持 及可以識別圖片中多個二維碼

// ZXing 只識別單個二維碼

    UIImage *image = #須要識別的圖片# 

    ZXCGImageLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:image.CGImage]; 

   ZXHybridBinarizer *binarizer = [[ZXHybridBinarizer alloc] initWithSource: source];

    ZXBinaryBitmap *bitmap = [[ZXBinaryBitmap alloc] initWithBinarizer:binarizer];

    

    NSError *error;

    

    id<ZXReader> reader;   

    if (NSClassFromString(@"ZXMultiFormatReader")) {

        reader = [NSClassFromString(@"ZXMultiFormatReader") performSelector:@selector(reader)];

    }

    ZXDecodeHints *_hints = [ZXDecodeHints hints];

    ZXResult *result = [reader decode:bitmap hints:_hints error:&error];

    if (result == nil) {

        NSLog(@"無QRCode");

        return;

    }

    NSLog(@"QRCode = %d,%@",result.barcodeFormat,result.text);

 ZXing 識別圖片中多個二維碼

UIImage *image = #須要識別的圖片# 

    ZXCGImageLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:image.CGImage]; 

   ZXHybridBinarizer *binarizer = [[ZXHybridBinarizer alloc] initWithSource: source];

   ZXBinaryBitmap *bitmap = [[ZXBinaryBitmap alloc] initWithBinarizer:binarizer];

   ZXDecodeHints *hints = [ZXDecodeHints hints];

 

    NSError *error = nil;

    ZXQRCodeMultiReader * reader2 = [[ZXQRCodeMultiReader alloc]init];

    NSArray *rs = [reader2 decodeMultiple:bitmap error:&error];

    // 或者  NSArray *rs =[reader2 decodeMultiple:bitmap hints:hints error:&error];

    NSLog(@" err = %@",error);

    for (ZXResult *resul in rs) {

        NSLog(@" ---%@",resul.text);

    }

 

後面 就看你需求了

iOS WebView中 長按二維碼的識別

思路:

  1. 長按webView 的過程當中 截屏,再去解析是否有二維碼,可是有個缺點 就是 萬一截了一個 一半的二維碼 那就無解了。
  2. 在webview中 注入獲取點擊圖片的JS 獲取圖片,再解析。缺點:萬一圖片過大 須要下載,勢必會影響用戶體驗。
  3. webview 加載完成圖片以後,圖片勢必緩存在 webview裏,有什麼方法能夠獲取webview 裏的緩存圖片。

本人目前用的是 第二種方式。求大神教我第三種...
我在TOWebViewController作了類擴展


//要注入的 js 代碼

static NSString* const kTouchJavaScriptString=

@"document.ontouchstart=function(event){\

x=event.targetTouches[0].clientX;\

y=event.targetTouches[0].clientY;\

document.location=\"myweb:touch:start:\"+x+\":\"+y;};\

document.ontouchmove=function(event){\

x=event.targetTouches[0].clientX;\

y=event.targetTouches[0].clientY;\

document.location=\"myweb:touch:move:\"+x+\":\"+y;};\

document.ontouchcancel=function(event){\

document.location=\"myweb:touch:cancel\";};\

document.ontouchend=function(event){\

document.location=\"myweb:touch:end:\"+x+\":\"+y;};";

 

//部分核心代碼

  • (BOOL)ad_webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

    NSString *requestString = [[request URL] absoluteString];
    NSArray *components = [requestString componentsSeparatedByString:@":"];
    if ([components count] > 1 && [(NSString *)[components objectAtIndex:0]
    isEqualToString:@"myweb"]) {
    if([(NSString *)[components objectAtIndex:1] isEqualToString:@"touch"])
    {
    if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"start"])
    {
    self.gesState = GESTURE_STATE_START;
    NSLog(@"touch start!");

     

          self.gesState = GESTURE_STATE_MOVE;

          NSLog(@"you are move");

      }

      

  }

  

  if ([(NSString*)[components objectAtIndex:2]isEqualToString:@"end"]) {

      [self.timer invalidate];

      self.timer = nil;

      self.gesState = GESTURE_STATE_END;

      NSLog(@"touch end");

  }

  

  

float ptX = [[components objectAtIndex:3]floatValue];

          float ptY = [[components objectAtIndex:4]floatValue];

          NSLog(@"touch point (%f, %f)", ptX, ptY);

          

          NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).tagName", ptX, ptY];

          NSString * tagName = [self.webView stringByEvaluatingJavaScriptFromString:js];

          self.imgURL = nil;

          if ([tagName isEqualToString:@"IMG"]) {

              self.imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", ptX, ptY];

          }

          if (self.imgURL) {

              self.timer = [NSTimer scheduledTimerWithTimeInterval:longGestureInterval target:self selector:@selector(handleLongTouch) userInfo:nil repeats:NO];

          }

      }

      else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"move"])

      {

          self.gesState = GESTURE_STATE_MOVE;

          NSLog(@"you are move");

      }

      

  }

  

  if ([(NSString*)[components objectAtIndex:2]isEqualToString:@"end"]) {

      [self.timer invalidate];

      self.timer = nil;

      self.gesState = GESTURE_STATE_END;

      NSLog(@"touch end");

  }

  

  if (self.imgURL && self.gesState == GESTURE_STATE_END) {

      NSLog(@"點的是圖片");

  }

  

  return NO;

 

 }
// return YES;
return [self ad_webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}

 
 
 

(void)ad_webViewDidFinishLoad:(UIWebView *)webView{
//控制緩存
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];

// 響應touch事件,以及得到點擊的座標位置,用於保存圖片
[webView stringByEvaluatingJavaScriptFromString:kTouchJavaScriptString];

[self ad_webViewDidFinishLoad:webView];
}

基本就能夠了。

 * 終於找到取 webView 緩存的圖片的方法了。 用的是 NSURLProtocol 方式,在github上找了一個 [RNCachingURLProtocol](https://github.com/rnapier/RNCachingURLProtocol),基本原理是:webView 在處理請求的過程當中會調用

 

 

  • (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response

URLProtocol 把webView請求返回來的 data 用壓縮的方式的存儲在 cache的文件夾下, 發出請求的時候會先去讀取緩存。本人對 RNCachingURLProtocol 作過修改 具體請看Demo

 

* 轉載請註明 做者:好迪 [文章地址](http://ihaodi.net/2016/03/21/iOS-QRcode%E8%AF%86%E5%88%AB%E5%8F%8A%E7%9B%B8%E5%86%8C%E5%9B%BE%E7%89%87%E4%BA%8C%E7%BB%B4%E7%A0%81%E8%AF%86%E5%88%AB/)

* 水平有限 歡迎批評指正評論

 

## Demo地址

<https://github.com/cuiwe000/QRCodeDemo.git>

 

## 參考文檔

* <http://blog.cnbluebox.com/blog/2014/08/26/ioser-wei-ma-sao-miao/>

* <https://github.com/MxABC/LBXScan> 這個很全

* [Apple CSS](https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariCSSRef/Articles/StandardCSSProperties.html#/apple_ref/doc/uid/TP30001266-SW1)

* <http://my.oschina.net/hmj/blog/111344>

* [stackoverflow](http://stackoverflow.com/questions/5995210/disabling-user-selection-in-uiwebview)

* [CSS 參考](https://developer.mozilla.org/en-US/docs/CSS/:not)

* <http://robnapier.net/offline-uiwebview-nsurlprotocol>

相關文章
相關標籤/搜索