IOS自定义相机,使用AVFoundation(附实现部分腾讯水印相机功能demo)

在项目中当我们遇到拍照的功能模块的时候,如果仅仅是用来拍照,系统提供的UIImagePickerController足够用来完成我们的任务。但是当我们的应用场景稍稍复杂点的时候,如要实现类似水印相机、美颜相机的时候,UIImagePickerController就有点力不从心了,需要自己去diy一个自定义相机。

UIImagePickerController使用起来比较简单易用,拍照,录制视频、控制闪光灯,前后摄像头的切换一应俱全。但是相机支持ui界面的自定义并不好(虽然可以支持自定义),在不同的系统下相机的功能界面还有所差别。

以水印相机为例,在水印相机中我们需要能够让水印模式实时的显示在相机的取景框中,而且水印模式还要可以左右滑动切换,在横屏的时候水印也要跟着横屏,还要有放大缩小镜头的以及点击屏幕能够聚焦等功能。

腾讯水印相机.gif

当然有人可能会想,将水印模式分成一个视图层然后放到相机的最上层不就行了吗?当然是不行的,首先UIImagePickerController在不同系统中的封装是略微不一样的,ui界面有所差别,界面不能够统一,即便是现在花了很过代码一个系统一个系统的适配,也很难保证以后不出问题,其次是手势的识别也有问题,即便是对手势进行了拦截处理,也不能解决,说白了也就是不是自己封装的东西,难以得到完美的掌控。

下面就开始自定义一个相机,并实现拍照、取消、闪光灯控制、前后摄像头控制、聚焦、放大缩小、拍照后预览、重拍、使用照片等功能。

@property (nonatomic, strong) ZTImagePickerOverLayView  *overlayView;//预览图层

@property (nonatomic) dispatch_queue_t sessionQueue;

@property (nonatomic, strong) AVCaptureSession* session;//用于捕捉视频和音频,协调视频和音频的输入和输出流

@property (nonatomic, strong) AVCaptureDeviceInput* videoInput;

@property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput;//输出静态影像

@property (nonatomic, strong) AVCaptureDevice             *device;//主要用来获取iphone一些关于相机设备的属性
@property (nonatomic, strong) AVCaptureVideoPreviewLayer* previewLayer;//预览图层layer

这里将相机的控件以及相机的实时显示的图层放在一个视图类ZTImagePickerOverLayView中,拍完照后的图层放在另外一个类ZTImagePickerPreImageView中,各个视图间的协调及部分逻辑放在控制器中ZTImagePickerController。封装完整个相机不过用了几百行代码。

1.初始化

 self.session = [[AVCaptureSession alloc] init];
    [self.session setSessionPreset:AVCaptureSessionPresetPhoto];
    
    NSError *error;
    
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    
    self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:&error];
   
    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    //输出设置。AVVideoCodecJPEG   输出jpeg格式图片
    NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
    [self.stillImageOutput setOutputSettings:outputSettings];
    
    if ([self.session canAddInput:self.videoInput]) {
        [self.session addInput:self.videoInput];
    }
    if ([self.session canAddOutput:self.stillImageOutput]) {
        [self.session addOutput:self.stillImageOutput];
    }
    
    //初始化预览图层
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    NSLog(@"%f",ScreenWidth);
    self.previewLayer.frame = CGRectMake(0, 0,ScreenWidth, ScreenHeight);
    self.preview = [[ZTImagePickerOverLayView alloc] init];
    self.preview.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
    [self.preview layoutSubviews];
    [self.preview.layer addSublayer:self.previewLayer];
    [self.view addSubview:self.preview];
    
    //添加顶部以及底部的自定义工具条
    [self.view addSubview:self.preview.topbar];
    [self.view addSubview:self.preview.buttomBar];
    self.preview.topbar.frame = CGRectMake(0, 0, self.view.width, 64 * ScreenWidth/320.0);
    self.preview.buttomBar.frame = CGRectMake(0, self.view.height - 70 * ScreenWidth/320.0 , self.view.width, 70* ScreenWidth/320.0);
    [self.preview layoutSubviews];
    //设置闪关灯模式
    if(self.device.isFlashAvailable)
        [self.preview setFlashModel:self.device.flashMode];
    else{
        self.preview.flashButton.hidden = YES;
        self.preview.cameraSwitchButton.hidden = YES;
    }
    
    //设置拍照后预览图层
    self.preImageView = [[ZTImagePickerPreImageView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)];
    [self.preImageView layoutSubviews];
    self.preImageView.hidden = YES;
    [self.view addSubview:self.preImageView];

2.添加手势
给预览层添加捏合手势控制放大缩小,添加点击手势来聚焦

 UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handlePinchGesture:)];
    pinch.delegate = self;
    [self.preview addGestureRecognizer:pinch];
    
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(focusAction:)];
    [self.preview addGestureRecognizer:tap];

3.给控件添加响应事件
闪光灯打开、关闭、自动,摄像头切换、取消、拍照、重新拍照、使用照片等按钮添加响应事件

[self.preview.cameraSwitchButton addTarget:self action:@selector(switchCameraSegmentedControlClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.preview.flashAutoButton addTarget:self action:@selector(flashButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.preview.flashOpeanButton addTarget:self action:@selector(flashButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.preview.flashCloseButton addTarget:self action:@selector(flashButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.preview.takePictureButton addTarget:self action:@selector(takePhotoButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.preview.cancelButton addTarget:self action:@selector(cancelButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.preImageView.reTakeButton addTarget:self action:@selector(retakeButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.preImageView.useImageButton addTarget:self action:@selector(useImageButtonClick:) forControlEvents:UIControlEventTouchUpInside];

4.闪光灯控制

- (void)flashButtonClick:(UIButton *)sender {
    //[self.preview reSetTopbar];
    [self.preview chosedFlashButton:sender];
    
    NSLog(@"flashButtonClick");
    
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    //修改前必须先锁定
    [device lockForConfiguration:nil];
    //必须判定是否有闪光灯,否则如果没有闪光灯会崩溃
    if ([device hasFlash]) {
        if([sender.titleLabel.text isEqualToString:@"打开"]){
            if([device isFlashModeSupported:AVCaptureFlashModeOn])
                [device setFlashMode:AVCaptureFlashModeOn];
        }else if ([sender.titleLabel.text isEqualToString:@"自动"]){
            if([device isFlashModeSupported:AVCaptureFlashModeAuto])
                [device setFlashMode:AVCaptureFlashModeAuto];
            
        }else if ([sender.titleLabel.text isEqualToString:@"关闭"]){
            if([device isFlashModeSupported:AVCaptureFlashModeOff])
                [device setFlashMode:AVCaptureFlashModeOff];
        }
    } else {
        
        NSLog(@"设备不支持闪光灯");
    }
    [device unlockForConfiguration];
}

5.前后摄像头切换

- (void)switchCameraSegmentedControlClick:(id)sender {
    
    //NSLog(@"%ld",(long)sender.selectedSegmentIndex);
    
    AVCaptureDevicePosition desiredPosition;
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (isUsingFrontFacingCamera){
        
        if(device.isFlashAvailable) self.preview.flashButton.hidden = NO;
        desiredPosition = AVCaptureDevicePositionBack;
        
    }else{
        desiredPosition = AVCaptureDevicePositionFront;
        [self.preview reSetTopbar];
        self.preview.flashButton.hidden = YES;
        
        
    }
    
    
    for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
        if ([d position] == desiredPosition) {
            [self.previewLayer.session beginConfiguration];
            AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
            for (AVCaptureInput *oldInput in self.previewLayer.session.inputs) {
                [[self.previewLayer session] removeInput:oldInput];
            }
            [self.previewLayer.session addInput:input];
            [self.previewLayer.session commitConfiguration];
            break;
        }
    }
    
    isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
}

6.拍照

- (void)takePhotoButtonClick:(id )sender{
    
    AVCaptureConnection *stillImageConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation];
    AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation];
    [stillImageConnection setVideoOrientation:avcaptureOrientation];
    [stillImageConnection setVideoScaleAndCropFactor:self.effectiveScale];
    
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        
        NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        self.imageData = jpegData;
        CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault,
                                                                    imageDataSampleBuffer,
                                                                    kCMAttachmentMode_ShouldPropagate);
        UIImage *image = [UIImage imageWithData:jpegData];
        [self waterMarkFixed];
        self.preImageView.imageView.image = image;
        [self.preview hiddenSelfAndBars:YES];
        self.preImageView.hidden = NO;
        
        ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
            if (author == ALAuthorizationStatusRestricted || author ==ALAuthorizationStatusDenied){
                    //无权限
                    return ;
                }
        //保存到相册
//            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
//            [library writeImageDataToSavedPhotosAlbum:jpegData metadata:(__bridge id)attachments completionBlock:^(NSURL *assetURL, NSError *error) {
//        
//            }];
        
    }];
    
    if([self.delegate respondsToSelector:@selector(imagePickerControllerTakePhoto:)])
        [self.delegate imagePickerControllerTakePhoto:self];
    
}

7.放大缩小

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer{
    
    BOOL allTouchesAreOnThePreviewLayer = YES;
    NSUInteger numTouches = [recognizer numberOfTouches], i;
    for ( i = 0; i < numTouches; ++i ) {
        CGPoint location = [recognizer locationOfTouch:i inView:self.preview];
        CGPoint convertedLocation = [self.previewLayer convertPoint:location fromLayer:self.previewLayer.superlayer];
        if ( ! [self.previewLayer containsPoint:convertedLocation] ) {
            allTouchesAreOnThePreviewLayer = NO;
            break;
        }
    }
    
    if ( allTouchesAreOnThePreviewLayer ) {
        
        
        self.effectiveScale = self.beginGestureScale * recognizer.scale;
        if (self.effectiveScale < 1.0){
            self.effectiveScale = 1.0;
        }
        
        CGFloat maxScaleAndCropFactor = [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor];
        
        
        if (self.effectiveScale > maxScaleAndCropFactor)
            self.effectiveScale = maxScaleAndCropFactor;
        
        [CATransaction begin];
        [CATransaction setAnimationDuration:.025];
        [self.previewLayer setAffineTransform:CGAffineTransformMakeScale(self.effectiveScale, self.effectiveScale)];
        [CATransaction commit];
        
    }
}

8.照片方向修正
拍完照的时候,拍出的照片你会发现呈现的方向不对,需要对照片的方向进行修正。

 AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation];
    [stillImageConnection setVideoOrientation:avcaptureOrientation];

- (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation
{
    AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)deviceOrientation;
    if ( deviceOrientation == UIDeviceOrientationLandscapeLeft )
        result = AVCaptureVideoOrientationLandscapeRight;
    else if ( deviceOrientation == UIDeviceOrientationLandscapeRight )
        result = AVCaptureVideoOrientationLandscapeLeft;
    return result;
}

这里需要注意的是如果想要拍完照的效果和UIimagePickerController的效果一样,即在横屏下拍完照,照片要旋转显示并且显示的小一些,那么就要对拍完照预览图层进行修改。

图片

在预览图层中修改imageview的大小。(这部分代码我并没有加到demo中,如果想实现拍完照后照片的方向与系统相机的一样,可以在ZTImagePickerPreImageView中加上)

- (void)changeImageViewFrameIfNeeded:(UIDeviceOrientation)orientation{
    if(orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){
    
        self.imageView.frame = CGRectMake(0, 0, self.width, 240 * [UIScreen mainScreen].bounds.size.width / 320.0);
        self.imageView.centerY = self.height / 2.0;
    }else{
        _imageView.frame = CGRectMake(0, 0, self.width, 418 * [UIScreen mainScreen].bounds.size.width / 320.0);
        _imageView.centerY = self.height / 2.0;
    }
}

仅仅是这样还不够,还要对设备方向的获取进行改进。
通常我们获取设备方向是通过[[UIDevice currentDevice] orientation] 或者通过[UIApplication sharedApplication].statusBarOrientation的方式来获取。但这两种方式有一个缺点,在竖排方向开关关闭的时候,获取到的方向是正确的,在开关打开的时候获取到的方向是竖直方向,在横屏等情况下获取的方向不正确。这时候就要通过CMMotionManager来获取方向了。(下面这段代码也没有加到demo中,如果有这样的功能需求,可以在ZTImagePickerController中加上这段代码)

- (void)p_startMotionManager{
    self.deviceOrientation = UIDeviceOrientationPortrait;
    if (_motionManager == nil) {
        _motionManager = [[CMMotionManager alloc] init];
    }
    _motionManager.deviceMotionUpdateInterval = 1/15.0;
    if (_motionManager.deviceMotionAvailable) {
        NSLog(@"Device Motion Available");
        [_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                            withHandler: ^(CMDeviceMotion *motion, NSError *error){
                                                [self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
                                                
                                            }];
    } else {
        NSLog(@"No device motion on device.");
    }
}

- (void)p_stopMonotionManager{
    [_motionManager stopDeviceMotionUpdates];
    _motionManager = nil;
}

二、添加水印
如果要实现类似腾讯的水印相机形式的水印,需要对水印专门做一个图层来进行管理。将水印图层放在相机的最上层就可以实时看到水印了,并且可以左右切换水印。这里使用scrollview来容纳每种水印样式,如果水印样式比较多当然可以使用collectionView来容纳。

为了让水印图层的手势(scrollView的左右滑动,每种水印样式视图中的控件响应手势)响应不与相机图层的手势响应不冲突,在水印图层可以将手势进行拦截,根据实际情况来返回响应手势的视图控件。

这里的代码根据实际情况修改
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    
    UIView *view = [super hitTest:point withEvent:event];
    
    CGPoint tempPoint = [self.reportView convertPoint:point fromView:self];
    if(CGRectContainsPoint(self.reportView.reportTypeLb.frame, tempPoint)){
        view = self.reportView.reportTypeLb;
        return view;
    }
    
    NSInteger left = 0,top = 0, height = 0,width = self.contentSize.width;
     height = MAX(self.reportView.xmNameLb.top, self.handleProblemView.userLb.top);
    if([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft){
        left = self.height - height;
        width = self.width;
    }

    if(CGRectContainsPoint(CGRectMake(left, top, width, height), point)){
            view = [self.superview.subviews objectAtIndex:0];
            view = [view hitTest:point withEvent:event];
        }else{

    }
    return view;
}

拍完照选择好水印样式后,将水印样式用的空间绘制到照片上,就形成了水印照片

- (UIImage *)markedImageWithType:(XBWaterMark )waterMarkType date:(NSDate *)date user:(NSString *)user placLocation:(ZTLocationModel *)locationModel withPhone:(NSString *)phone xmType:(NSString *)xmType{
    
    if (self.size.width == 0.0 || self.size.height == 0.0) return nil;
    
    UIImage *defaultImage = nil;
    
    CGFloat scale = [UIScreen mainScreen].scale;
    if(scale >= 3) scale = 2;
    
    UIImage *image = [self thumbnailForMaxWidth:1024/scale maxHeight:1024/scale];
    
    CGSize newSize = CGSizeMake(image.size.width*image.scale/scale, image.size.height*image.scale/scale);
    
    UIView *waterMarkView = [self p_markWaterMarkView:waterMarkType date:date user:user
                                            placLocation:locationModel  withPhone:phone newSize:newSize xmType:xmType];
    //将水印样式中的控件绘制到图片
    UIGraphicsBeginImageContextWithOptions(newSize, YES, 0.0);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    [image drawInRect:CGRectMake(0.0, 0.0, newSize.width, newSize.height)];
    
    for (UIView *view in waterMarkView.subviews) {
        if([view isKindOfClass:[UIImageView class]]){
            UIImageView *iv = (UIImageView *)view;
            [iv.image drawInRect:CGRectMake(iv.left,iv.top, iv.width, iv.height)];
        }else if ([view isKindOfClass:[UILabel class]]){
            UILabel *lb = (UILabel *)view;
            UIImage *lbImage = [lb imageByRenderingView];
            [lbImage drawInRect:CGRectMake(lb.left, lb.top, lb.width, lb.height)];
        }
    }
    
    CGContextRestoreGState(context);
    
    defaultImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return defaultImage;
}

效果图

自定义水印相机.gif

自定义相机demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,611评论 4 59
  • iOS 苹果官方Demo合集 字数10517阅读21059评论18喜欢144 其实, 开发了这么久, 不得不说, ...
    bingo居然被占了阅读 9,848评论 2 31
  • 2013-09-27 自我管理能力就是领导力 ——小城散漫表达系列之“领导力” 火山 社会在物质文明的推动和深入发...
    朱明云阅读 458评论 0 3
  • 真的好久没有码字了。离开上一个公司也差不多一个月了。 在这段不长的工作(实习)时间里,也认识了许多优秀的人...
    冰美式乌龙阅读 209评论 0 1
  • 在喧闹的大街上漫无目的地走着,在人潮人海的都市里糜烂的生活着,在夜深人静时倍感寂寥的徘徊着,在去往顿悟的漫漫长路中...
    暧昧__阅读 295评论 0 0