zoukankan      html  css  js  c++  java
  • iOS自定义拍照框拍照&裁剪(一)

    • 卡片机时代

    很重要的一点是,相机本身是没有方向概念的,它不理解拍摄的内容,只会以相机自己的坐标系去保存数据,下图展示了相机对“F”进行四个角度拍摄时返回的图片数据。
    

    最初的卡片机时代,照片都会经由底片洗出来,那时不存在照片的方向问题,我们总可以把洗出来的照片通过简单的旋转来进行观看。比如这张照片墙中的照片,你能否说哪些照片是横着?哪些颠倒着?你甚至都无法判断每张照片相机是以何种角度拍摄的,因为每张都已经旋转至适合观看的角度。
    

    • 数码时代

    可是到了数码时代,不再需要底片,照片需要被存成一个图像文件。对于上面的拍摄角度,存储方式并没有变化,所有的场景仍然是以相机的坐标系来保存。于是这些照片仍像上面一样,原封不动的保存了下来。
    
    虽然存储方式不变,和卡机机时代的实体相片不同的是,由于电子设备可不知道照片应该如何旋转,只能够以它存储于磁盘中的方向来展示。这便是为何照片传到电脑上之后,会出现横了,或者颠倒的情况。
    
    • 方向传感器

    为了克服这一情况,让照片可以真实的反应人们拍摄时看到的场景,现在很多相机中就加入了方向传感器,它能够记录下拍摄时相机的方向,并将这一信息保存在照片中。照片的存储方式还是没有任何改变,它仍然是以相机的坐标系来保存,只是当相机来浏览这些照片时,相机可以根据照片中的方向信息,结合此时相机的方向,对照片进行旋转,从而转到适合人们观看的角度。
    
    • iPhone上的情况

    在iOS的设备中也包含了方向传感器,它但是它默认的照片方向并不是竖着拿手机时的情况,而是横向,即Home键在右侧,如下:
    

    如此一来,如果竖着拿手机拍摄时,就相当于对手机顺时针旋转了90度,也即上面相机图片中的最后一幅
    

    • iPhone拍照方向问题处理

    iPhone通过API获取到的是图片内容数据,不带方向信息,此时,我们需要手动的根据传感器方向将方向信息填充进去,并且根据方向信息对照片进行相应的旋转,得到人类视角正向的图片。代码如下:

    //iOS11以上支持AVCapturePhotoOutput代理
    - (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo
                    error:(NSError *)error {
        if (error) {
                NSLog(@"获取图片错误 --- %@",error.localizedDescription);
            }
            if (photo) {
               UIImageOrientation orient = UIImageOrientationUp;
                //后置摄像头
                if (self.shootingOrientation == UIDeviceOrientationLandscapeRight){
                    orient = UIImageOrientationDown;
                }else if(self.shootingOrientation == UIDeviceOrientationPortrait){
                    orient = UIImageOrientationRight;
                }else if(self.shootingOrientation == UIDeviceOrientationLandscapeLeft){
                    orient = UIImageOrientationUp;
                }else if(self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown){
                    orient = UIImageOrientationLeft;
                }
                //前置摄像头
                AVCaptureDevice *currentDevice = [self.videoWriterManager.videoInput device];
                AVCaptureDevicePosition currentPosition = [currentDevice position];
                if (currentPosition == AVCaptureDevicePositionFront){
                    //前置摄像头
                    if (self.shootingOrientation == UIDeviceOrientationLandscapeRight){
                        orient = UIImageOrientationUp;
                    }else if(self.shootingOrientation == UIDeviceOrientationLandscapeLeft){
                        orient = UIImageOrientationDown;
                    }
                }
                UIImage *image = [UIImage imageWithCGImage:photo.CGImageRepresentation scale:1 orientation:orient];
                //图片修正为人类视角看起来正向的图片
                //[self fixOrientation:image];
            }
    }
    
    
    //将原始图片数据调整为 人类视角正向的图片
    - (UIImage *)fixOrientation:(UIImage *)image{
        // No-op if the orientation is already correct
        if (image.imageOrientation == UIImageOrientationUp) return image;
        
        // We need to calculate the proper transformation to make the image upright.
        // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
        CGAffineTransform transform = CGAffineTransformIdentity;
        CGFloat imageWidth = CGImageGetWidth(image.CGImage);
        CGFloat imageHeight = CGImageGetHeight(image.CGImage);
        //创建的位图宽高
        CGFloat contextWidth = imageWidth < imageHeight ? imageWidth : imageHeight;
        CGFloat contextHeight = imageWidth > imageHeight ? imageWidth : imageHeight;
        
    
        switch (image.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:{
                    //创建横着显示的位图上下文,宽大于高
                    CGFloat temp = contextWidth;
                    contextWidth = contextHeight;
                    contextHeight = temp;
                    //旋转180度
                    transform = CGAffineTransformTranslate(transform, contextWidth, contextHeight);
                    transform = CGAffineTransformRotate(transform, M_PI);
                }
                break;
                
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                //逆时针旋转90度
                transform = CGAffineTransformTranslate(transform, contextWidth, 0);
                transform = CGAffineTransformRotate(transform, M_PI_2);
                break;
                
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                //顺时针90度
                transform = CGAffineTransformTranslate(transform, 0, contextHeight);
                transform = CGAffineTransformRotate(transform, -M_PI_2);
                break;
                
            default:
                break;
        }
        
        switch (image.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                //镜像图片Y轴翻转坐标系
                transform = CGAffineTransformTranslate(transform, contextWidth, 0);
                transform = CGAffineTransformScale(transform, -1, 1);
                break;
                
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                //镜像图片Y轴翻转坐标系
                transform = CGAffineTransformTranslate(transform, contextHeight, 0);
                transform = CGAffineTransformScale(transform, -1, 1);
                break;
                
            default:
                break;
        }
        
        //创建竖直显示的画布
        CGContextRef ctx = CGBitmapContextCreate(NULL, contextWidth, contextHeight,
                                                 CGImageGetBitsPerComponent(image.CGImage), 0,
                                                 CGImageGetColorSpace(image.CGImage),
                                                 CGImageGetBitmapInfo(image.CGImage));
    
        CGContextConcatCTM(ctx, transform);
        CGContextDrawImage(ctx, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
        
        // And now we just create a new UIImage from the drawing context
        CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
        UIImage *img = [UIImage imageWithCGImage:cgimg];
        CGContextRelease(ctx);
        CGImageRelease(cgimg);
        return img;
    }
    

    图片来源于(https://feihu.me/blog/2015/how-to-handle-image-orientation-on-iOS/)

    参考 https://feihu.me/blog/2015/how-to-handle-image-orientation-on-iOS/

  • 相关阅读:
    construction of tuples containing 0 or 1 items
    globals()
    __new__
    ubuntu系统安装mysql登陆提示 解决Mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'问题
    ubuntu系统更新源
    Python Web开发问题收集(二)
    linux后台执行./run.py提示python syntax error near unexpected token `('
    linux下执行scrapy的爬虫定时任务
    ubuntu系统中crontab的使用介绍
    JMeter BeanShell断言使用
  • 原文地址:https://www.cnblogs.com/xiongwj0910/p/15409637.html
Copyright © 2011-2022 走看看