iOS開(kāi)發(fā)--二維碼/條形碼(掃描(可區(qū)域)和生成)

關(guān)于二維碼(或者條形碼,以下歸類(lèi)簡(jiǎn)稱(chēng)二維碼)掃描和生成的,我相信網(wǎng)絡(luò)上相關(guān)的文章層數(shù)不窮,但是,大部分都是直接粘貼上代碼,不去解釋,這樣導(dǎo)致每次遇到諸如此類(lèi)的功能行的問(wèn)題,簡(jiǎn)單方便的CV工程師程序,久而久之,對(duì)于程序開(kāi)發(fā)更局限于表面,開(kāi)發(fā)這條道路也會(huì)越來(lái)越局限了.
好了,言歸正傳,接下來(lái)我就分享一下,自己在二維碼開(kāi)發(fā)的過(guò)程中遇到的問(wèn)題和一些經(jīng)驗(yàn)吧.
注:這里的掃描僅限于相機(jī)掃描,所以建議各位開(kāi)發(fā)者,需要在真機(jī)上進(jìn)行測(cè)試

一. 二維碼的掃描

0.準(zhǔn)備工作

  • 1).宏定義
    定義當(dāng)前頁(yè)面的寬和高,通過(guò)delegate.window獲取frame
    #define SCREEN_WIDTH [UIApplication sharedApplication].delegate.window.frame.size.width
    #define SCREEN_HEIGHT [UIApplication sharedApplication].delegate.window.frame.size.height
  • 2).協(xié)議
    • AVCaptureMetadataOutputObjectsDelegate

這是有關(guān)攝像設(shè)備輸出的相關(guān)的代理,這里我們需要用到掃描后的結(jié)果,后面會(huì)做出詳細(xì)的解釋

  • UIAlertViewDelegate

主要是顯示出來(lái)掃描的結(jié)果,可以看做相對(duì)的輔助

1.依賴(lài)庫(kù)

因?yàn)槎S碼的掃描是基于真機(jī)上的相機(jī),我們需要引入<AVFoundation/AVFoundation.h>

#import <AVFoundation/AVFoundation.h>

關(guān)于這個(gè)庫(kù)的介紹,相信很多做過(guò)視頻和音頻播放的童鞋們并不陌生,這個(gè)也是基于cocoa下比較常用的庫(kù)

2.定義對(duì)應(yīng)變量屬性

關(guān)于屬性的創(chuàng)建,我們需要了解到每個(gè)屬性的作用和相關(guān)操作

1).創(chuàng)建相機(jī)AVCaptureDevice

AVCaptureDevice的每個(gè)實(shí)例對(duì)應(yīng)一個(gè)設(shè)備,如攝像頭或麥克風(fēng)。集體的信息可以參考蘋(píng)果相關(guān)API.

@property (strong,nonatomic)AVCaptureDevice * device;
2).創(chuàng)建輸入設(shè)備AVCaptureDeviceInput

AVCaptureDeviceInput是AVCaptureInput子類(lèi)提供一個(gè)接口,用于捕獲從一個(gè)AVCaptureDevice媒體甩卓。AVCaptureDeviceInput是AVCaptureSession實(shí)例的輸入源,提供媒體數(shù)據(jù)從設(shè)備連接到系統(tǒng)狸演。

@property (strong,nonatomic)AVCaptureDeviceInput * input;
3).創(chuàng)建輸出設(shè)備AVCaptureMetadataOutput

AVCaptureMetadataOutput對(duì)象攔截元數(shù)據(jù)對(duì)象發(fā)出的相關(guān)捕獲連接,并將它們轉(zhuǎn)發(fā)給委托對(duì)象進(jìn)行處理责语。您可以使用這個(gè)類(lèi)的實(shí)例來(lái)處理特定類(lèi)型的元數(shù)據(jù)中包含的輸入數(shù)據(jù)。你使用這個(gè)類(lèi)你做其他的輸出對(duì)象的方式,通常是通過(guò)添加一個(gè)AVCaptureSession對(duì)象作為輸出槐壳。簡(jiǎn)單而言就是,AVCaptureMetadataOutput將獲取到的元數(shù)據(jù)交給AVCaptureSession進(jìn)行處理的途徑.

@property (strong,nonatomic)AVCaptureMetadataOutput * output;
4).創(chuàng)建AVFoundation中央樞紐捕獲類(lèi)AVCaptureSession。

下面的是關(guān)于AVCaptureSession的原生API

To perform a real-time capture, a client may instantiate AVCaptureSession and add appropriate AVCaptureInputs, such as AVCaptureDeviceInput, and outputs, such as AVCaptureMovieFileOutput. [AVCaptureSession startRunning] starts the flow of data from the inputs to the outputs, and [AVCaptureSession stopRunning] stops the flow. A client may set the sessionPreset property to customize the quality level or bitrate of the output.

在蘋(píng)果的API中大致是這樣重點(diǎn)解釋的:

  • 執(zhí)行實(shí)時(shí)捕獲,一個(gè)客戶可以實(shí)例化AVCaptureSession并添加適當(dāng)AVCaptureInputs,AVCaptureDeviceInput和相關(guān)的輸出,如AVCaptureMovieFileOutput喜每。
  • [AVCaptureSession startRunning]開(kāi)始的數(shù)據(jù)流從輸入到輸出
  • [AVCaptureSession stopRunning]停止流動(dòng)务唐。
  • 客戶端可以設(shè)置sessionPreset屬性定制質(zhì)量水平或輸出的比特率
    @property (strong,nonatomic)AVCaptureSession * session;
5).創(chuàng)建AVCaptureSession預(yù)覽視覺(jué)輸出AVCaptureVideoPreviewLayer,在API介紹中,我們不難發(fā)現(xiàn),他是繼承自CoreAnimation的CALayer的子類(lèi),,這里我們可以看做是將圖片輸出的一個(gè)平臺(tái)(搭載), 因此適合插入在一層的層次結(jié)構(gòu)作為一個(gè)圖形界面的一部分。
  • 在蘋(píng)果原生API介紹中,我們可以了解到,我們可以通過(guò)創(chuàng)建+ layerWithSession:或-initWithSession:對(duì)AVCaptureVideoPreviewLayer進(jìn)行實(shí)例與捕獲會(huì)話預(yù)覽带兜。
  • 使用"videoGravity”屬性,可以影響內(nèi)容是如何看待相對(duì)于層界限枫笛。
  • 在某些硬件配置,層可以使用"orientation"(操縱的方向) 和 "mirrored"(鏡像)等進(jìn)行操作.
    @property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;

3.初始化變量

確定了相關(guān)屬性,接下來(lái),我們對(duì)相關(guān)變量進(jìn)行初始化,就好比原料我們有了,接下來(lái)我們對(duì)這些材料進(jìn)行粗略的加工.
至于初始化的位置,一般情況下我們將一個(gè)頁(yè)面作為二維碼操作的,這邊算作是一個(gè)模塊處理,所以,建議在ViewDidLoad方法(生命周期)里面進(jìn)行創(chuàng)建.如果需要特殊處理,具體情況具體分析吧,因?yàn)樾枨蟛灰粯?所以,下面的栗子采用在ViewDidLoad中進(jìn)行.

1).初始化基礎(chǔ)"引擎"Device
// Device,這里需要注意的是AVCaptureDevice不能直接創(chuàng)建的實(shí)例
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
2).初始化輸入流 Input,并添加Device
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
3).初始化輸出流Output
self.output = [[AVCaptureMetadataOutput alloc] init];

下面,敲黑板了,
這里需要注意的是:在輸出流的設(shè)置中,如果不對(duì)AVCaptureMetadataOutput的屬性rectOfInterest進(jìn)行設(shè)置,掃描的區(qū)域默認(rèn)是展示的AVCaptureVideoPreviewLayer全部區(qū)域.這里我們采用區(qū)域掃描,也就是所謂的條框掃描,提高用戶體驗(yàn)度.

// 創(chuàng)建view,通過(guò)layer層進(jìn)行設(shè)置邊框?qū)挾群皖伾?用來(lái)輔助展示掃描的區(qū)域
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 100)];
redView.layer.borderWidth = 2;
redView.layer.borderColor = [UIColor cyanColor].CGColor;
[self.view addSubview:redView];
//設(shè)置輸出流的相關(guān)屬性
// 確定輸出流的代理和所在的線程,這里代理遵循的就是上面我們?cè)跍?zhǔn)備工作中提到的第一個(gè)代理,至于線程的選擇,建議選在主線程,這樣方便當(dāng)前頁(yè)面對(duì)數(shù)據(jù)的捕獲.
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
3+). 設(shè)置掃描區(qū)域的大小(這個(gè)也是我在開(kāi)發(fā)中,遇到的最*最^n坑爹的問(wèn)題,標(biāo)注一下)

為什么是"3+"呢,主要是本來(lái)想將這部分放在后面單獨(dú)講,但是考慮到連貫性,就單獨(dú)做一個(gè)補(bǔ)充小節(jié)來(lái)講吧,而且屬于設(shè)置session層的部分.

self.output.rectOfInterest = CGRectMake((100)/(SCREEN_HEIGHT),(SCREEN_WIDTH - 100 - 200)/SCREEN_WIDTH,100/SCREEN_HEIGHT,200/SCREEN_WIDTH);

其實(shí)呢,我是想在當(dāng)前view創(chuàng)建一塊CGRectMake(100, 100, 200, 100)的掃描區(qū)域,如下圖的掃描區(qū)域框:

掃描區(qū)域.PNG

但是呢,這里需要說(shuō)明的一點(diǎn)就是,我們?nèi)绻凑粘R?guī)的CGRect創(chuàng)建方式去設(shè)置,是肯定不對(duì)的,他會(huì)出現(xiàn)掃描區(qū)域不是預(yù)設(shè)的,為什么呢?
原因很蛋疼,因?yàn)槲覀兤匠5脑O(shè)置CGRect是以左上角為原點(diǎn),橫向增加為+x,縱向增加為+y,橫向?yàn)閷挾葁idth,縱向?yàn)楦叨萮eight,沒(méi)毛病吧,但是,坑爹的就是output的rectOfInterest是以左上角為原點(diǎn),x與y數(shù)值對(duì)調(diào),width和height數(shù)值對(duì)調(diào),并且,x,y,width和height的數(shù)值為0 ~ 1.如下對(duì)比圖:
常規(guī)坐標(biāo)CGRect坐標(biāo)計(jì)算體系.png

output的rectOfInterest坐標(biāo)計(jì)算體系.png

說(shuō)明一下:這里的計(jì)算對(duì)比,針對(duì)的是,知道掃描框相對(duì)于父視圖的位置,我們根據(jù)掃描框的CGRect可以計(jì)算出需要設(shè)置的output的rectOfInterest的CGRect.至于為什么需要對(duì)調(diào)原理,最近有時(shí)間研究研究(蘋(píng)果這個(gè)設(shè)計(jì)讓很多人不解),目前僅供參考.大家要是有相關(guān)的方案或者明確為何這樣,希望在下面留言,我們一起深究一下.


對(duì)比.png

這里的概念區(qū)別于我們所認(rèn)知的CGRect的設(shè)置,建議童鞋們還是手動(dòng)算一下,之后進(jìn)行邊緣化測(cè)試,就是測(cè)試二維碼從邊緣完全進(jìn)入掃描區(qū)域并且存在掃描任務(wù)的位置.

4).初始化捕獲數(shù)據(jù)類(lèi)AVCaptureSession
// 初始化session
self.session = [[AVCaptureSession alloc]init];
// 設(shè)置session類(lèi)型,AVCaptureSessionPresetHigh 是 sessionPreset 的默認(rèn)值。
[_session setSessionPreset:AVCaptureSessionPresetHigh];

補(bǔ)充:這里簡(jiǎn)單對(duì)sessionPreset的屬性值進(jìn)行以下說(shuō)明:
蘋(píng)果API中提供了如下的四種方式:

// AVCaptureSession 預(yù)設(shè)適用于高分辨率照片質(zhì)量的輸出
AVF_EXPORT NSString *const AVCaptureSessionPresetPhoto NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;
// AVCaptureSession 預(yù)設(shè)適用于高分辨率照片質(zhì)量的輸出
AVF_EXPORT NSString *const AVCaptureSessionPresetHigh NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;
// AVCaptureSession 預(yù)設(shè)適用于中等質(zhì)量的輸出刚照。 實(shí)現(xiàn)的輸出適合于在無(wú)線網(wǎng)絡(luò)共享的視頻和音頻比特率崇堰。
AVF_EXPORT NSString *const AVCaptureSessionPresetMedium NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;
// AVCaptureSession 預(yù)設(shè)適用于低質(zhì)量的輸出。為了實(shí)現(xiàn)的輸出視頻和音頻比特率適合共享 3G涩咖。
AVF_EXPORT NSString *const AVCaptureSessionPresetLow NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;

PS:在API的介紹中,除了以上的跡象,我們還會(huì)看到好幾種類(lèi)型,不過(guò)不是針對(duì) ipad iphone 的海诲。針對(duì) MAC_OS,不便介紹,感興趣的可以查看相關(guān)API

5).將輸入流和輸出流添加到session中

這里可以看做是集成,就好比是,我們現(xiàn)在正在建造一輛汽車(chē),我們的原件已經(jīng)做好了,現(xiàn)在要放到汽車(chē)的骨架上.

// 添加輸入流
if ([_session canAddInput:self.input]) {
    [_session addInput:self.input];
}
// 添加輸出流
if ([_session canAddOutput:self.output]) {
    [_session addOutput:self.output];
}
// 下面的是比較重要的,也是最容易出現(xiàn)崩潰的原因,就是我們的輸出流的類(lèi)型
// 1.這里可以設(shè)置多種輸出類(lèi)型,這里必須要保證session層包括輸出流
// 2.必須要當(dāng)前項(xiàng)目訪問(wèn)相機(jī)權(quán)限必須通過(guò),所以最好在程序進(jìn)入當(dāng)前頁(yè)面的時(shí)候進(jìn)行一次權(quán)限訪問(wèn)的判斷(在文章的最后,我會(huì)貼出相關(guān)的代買(mǎi))
   self.output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
6).設(shè)置輸出展示平臺(tái)AVCaptureVideoPreviewLayer
// 初始化
self.preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
// 設(shè)置Video Gravity,顧名思義就是視頻播放時(shí)的拉伸方式,默認(rèn)是AVLayerVideoGravityResizeAspect
// AVLayerVideoGravityResizeAspect 保持視頻的寬高比并使播放內(nèi)容自動(dòng)適應(yīng)播放窗口的大小。
// AVLayerVideoGravityResizeAspectFill 和前者類(lèi)似檩互,但它是以播放內(nèi)容填充而不是適應(yīng)播放窗口的大小特幔。最后一個(gè)值會(huì)拉伸播放內(nèi)容以適應(yīng)播放窗口.
// 因?yàn)榭紤]到全屏顯示以及設(shè)備自適應(yīng),這里我們采用fill填充
self.preview.videoGravity =AVLayerVideoGravityResizeAspectFill;
// 設(shè)置展示平臺(tái)的frame
self.preview.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// 因?yàn)?AVCaptureVideoPreviewLayer是繼承CALayer,所以添加到當(dāng)前view的layer層
[self.view.layer insertSublayer:self.preview atIndex:0];
7).一切準(zhǔn)備就去,開(kāi)始運(yùn)行
[self.session startRunning];
4.掃描結(jié)果處理

這里就需要用到我們之前設(shè)置的兩個(gè)代理AVCaptureMetadataOutputObjectsDelegate和UIAlertViewDelegate
在AVCaptureMetadataOutputObjectsDelegate的代理方法中,有didOutputMetadataObjects這個(gè)方法,表示輸出的結(jié)果,我們掃描二維碼的結(jié)果將要在這里進(jìn)行處理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
// 判斷掃描結(jié)果的數(shù)據(jù)是否存在
if ([metadataObjects count] >0){
// 如果存在數(shù)據(jù),停止掃描
[self.session stopRunning];
// AVMetadataMachineReadableCodeObject是AVMetadataObject的具體子類(lèi)定義的特性檢測(cè)一維或二維條形碼。
// AVMetadataMachineReadableCodeObject代表一個(gè)單一的照片中發(fā)現(xiàn)機(jī)器可讀的代碼闸昨。這是一個(gè)不可變對(duì)象描述條碼的特性和載荷蚯斯。
// 在支持的平臺(tái)上,AVCaptureMetadataOutput輸出檢測(cè)機(jī)器可讀的代碼對(duì)象的數(shù)組
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
// 獲取掃描到的信息
NSString *stringValue = metadataObject.stringValue;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"掃描結(jié)果"
message:stringValue
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"確定", nil];
[self.view addSubview:alert];
[alert show];
}
}

在UIAlertViewDelegate代理方法中,我們確認(rèn)信息后,可以對(duì)信息有相應(yīng)的操作,這里我只是簡(jiǎn)單的進(jìn)行了繼續(xù)進(jìn)行數(shù)據(jù)捕捉(掃描)
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[self.session startRunning];
}

5.運(yùn)行展示

下面我們看看運(yùn)行的結(jié)果,這里測(cè)試過(guò)程包括區(qū)域掃描的邊緣化測(cè)試:


區(qū)域掃描.gif

二.二維碼的生成

講完了二維碼的掃描,接下來(lái)我們接著講講二維碼的生成.
二維碼的生成的核心在于圖形的繪制,我們通過(guò)濾鏡CIFilter和圖形繪制的上下文方式生成二維碼.

0.準(zhǔn)備工作

1.依賴(lài)庫(kù)

二維碼的生成區(qū)別于二維碼的掃描,因?yàn)樗暮诵氖腔趫D形的繪制完成的,所以需要導(dǎo)入CoreImage框架
#import <CoreImage/CoreImage.h>

2.創(chuàng)建濾鏡CIFilte

1.創(chuàng)建濾鏡CIFilter實(shí)例對(duì)象,并通過(guò)類(lèi)方法,將filter的名稱(chēng)指定為CIQRCodeGenerator
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
2.由于filter的強(qiáng)大,我們目前僅是實(shí)現(xiàn)簡(jiǎn)單的二維碼的生成,所以,我們將filter的各項(xiàng)屬性均設(shè)置成默認(rèn)
[filter setDefaults];
3.給過(guò)濾器CIFilter添加數(shù)據(jù)

這里需要說(shuō)明的是,二維碼的主要內(nèi)容可以是如下幾種類(lèi)型(傳統(tǒng)的條形碼只能放數(shù)字):

  • 純文本
  • URL
  • 名片(這個(gè)有待考證,表示我并沒(méi)有試驗(yàn)過(guò))
// 基于多種類(lèi)型,我們簡(jiǎn)單的生成字符串的二維碼
// 創(chuàng)建字符串
NSString *dataString = @"鋒繪動(dòng)漫"; 
// 將字符串轉(zhuǎn)換成date類(lèi)型,并通過(guò)KVO的形式保存至濾鏡CIFilter(目前指定為二維碼)的inputMessage中
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
[filter setValue:data forKeyPath:@"inputMessage"];
4.獲取輸出的二維碼
CIImage *outputImage = [filter outputImage];
5.獲取高清的二維碼,并展示

因?yàn)镃IFilter生成的二維碼相對(duì)而言模糊,達(dá)不到設(shè)備快速識(shí)別的需求,同時(shí)用戶體驗(yàn)差.
所以通過(guò)圖像繪制的上下文來(lái)獲得高清的二維碼圖片.
PS:由于獲取高清圖片不是該章節(jié)的重點(diǎn),相關(guān)的代碼部分來(lái)自網(wǎng)絡(luò),放到文章的最后,僅供看考

// 獲取二維碼
self.imageView.image = [self createErWeiMaImageFormCIImage:outputImage withSize:200];
6.運(yùn)行結(jié)果

掃描的內(nèi)容請(qǐng)參考第一節(jié)"二維碼生成"的運(yùn)行結(jié)果


二維碼生成.gif

我是調(diào)皮的分割線


小結(jié)

這就是我理解的二維碼的生成和二維碼的掃描,其中主要的還是針對(duì)兩個(gè)框架的研究,讓我學(xué)到了很多東西.
在學(xué)習(xí)的過(guò)程中,比較建議大家多去查看蘋(píng)果原生的API,這個(gè)對(duì)自我理解是比較重要的,網(wǎng)絡(luò)上的總結(jié)出來(lái)的,只能作為自己的參考,切不可取而代之,最大的禁忌就是CV工程師的道路,再簡(jiǎn)單的代碼也要自己敲出來(lái).
有什么問(wèn)題歡迎大家留言多多留言,多多交流
下面附上demo地址(本人的github上):
二維碼掃描(可區(qū)域)和生成的Demo地址

PS:相關(guān)代碼

1.權(quán)限訪問(wèn)

NSString *mediaType =AVMediaTypeVideo;
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
if(authStatus ==AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied){
        UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@“項(xiàng)目名稱(chēng)”
                                                       message:@"請(qǐng)?jiān)趇Phone的“設(shè)置”-“隱私”-“相機(jī)”功能中薄风,找到“項(xiàng)目名稱(chēng)”打開(kāi)相機(jī)訪問(wèn)權(quán)限"
                                                      delegate:nil
                                             cancelButtonTitle:@"確定"
                                             otherButtonTitles: nil];
        [alert show];
        return;
    }

2.獲取高清圖片

- (UIImage *)getErWeiMaImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));

    // 1.創(chuàng)建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);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);

    // 2.保存bitmap到圖片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拍嵌,隨后出現(xiàn)的幾起案子遭赂,更是在濱河造成了極大的恐慌,老刑警劉巖横辆,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撇他,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡狈蚤,警方通過(guò)查閱死者的電腦和手機(jī)困肩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脆侮,“玉大人锌畸,你說(shuō)我怎么就攤上這事【副埽” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵幻捏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我粘咖,道長(zhǎng),這世上最難降的妖魔是什么瓮下? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任翰铡,我火速辦了婚禮讽坏,結(jié)果婚禮上锭魔,老公的妹妹穿的比我還像新娘路呜。我一直安慰自己迷捧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布胀葱。 她就那樣靜靜地躺著,像睡著了一般抵屿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轧葛,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天艇搀,我揣著相機(jī)與錄音求晶,去河邊找鬼。 笑死芳杏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚜锨。 我是一名探鬼主播慢蜓,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼氛悬!你這毒婦竟也來(lái)了耘柱?” 一聲冷哼從身側(cè)響起如捅,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤调煎,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后悲关,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寓辱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年赤拒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挎挖。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖崔涂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堪伍,我是刑警寧澤锚烦,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布帝雇,位于F島的核電站涮俄,受9級(jí)特大地震影響尸闸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吮廉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一宦芦、第九天 我趴在偏房一處隱蔽的房頂上張望宙址。 院中可真熱鬧调卑,春花似錦、人聲如沸恬涧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至啤月,卻和暖如春碳锈,著一層夾襖步出監(jiān)牢的瞬間顽冶,已是汗流浹背售碳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留间景,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓倘要,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親封拧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容