【问题标题】:Capturing photos with specific resolution using the UIImagePickerController使用 UIImagePickerController 捕获具有特定分辨率的照片
【发布时间】:2012-08-28 19:20:36
【问题描述】:

我想拍一张写有字的A4纸。重要的是,我希望文本可读,但我不希望图像分辨率为 2592x1936 像素或 3264x2448 像素,因为那样会太大。另外,我认为在拍摄后重新缩放照片需要额外的时间,所以我也想避免这种情况。

我们可以选择以下品质:

UIImagePickerControllerQualityTypeHigh = 0   
UIImagePickerControllerQualityTypeMedium          = 1  default value   
UIImagePickerControllerQualityTypeLow            = 2   
UIImagePickerControllerQualityType640x480         = 3,   
UIImagePickerControllerQualityTypeIFrame1280x720  = 4,   
UIImagePickerControllerQualityTypeIFrame960x540   = 5 

如果我们使用AVFoundation,我们可以从this nice table 中选择分辨率(在标题“捕获静止图像”下)。

但是UIImagePickerController 是否有类似的表,例如,UIImagePickerControllerQualityTypeHigh 在 iPhone 3gs 上等于 1920x1080?

【问题讨论】:

    标签: iphone ios ios4 uiimagepickercontroller


    【解决方案1】:

    UIImagepickerController quality 用于视频录制(在 UIImagepickerController 属性“videoQuality”中使用)。

    我想如果你想指定确切的照片分辨率应该是什么,你应该使用 AV Foundation 框架而不是 UIImagepickerController。或者如你所说,之后转换图片。

    之后调整它的大小(找到here):

    //  ==============================================================
    //  resizedImage
    //  ==============================================================
    // Return a scaled down copy of the image.  
    
    UIImage* resizedImage(UIImage *inImage, CGRect thumbRect)
    {
        CGImageRef          imageRef = [inImage CGImage];
        CGImageAlphaInfo    alphaInfo = CGImageGetAlphaInfo(imageRef);
    
        // There's a wierdness with kCGImageAlphaNone and CGBitmapContextCreate
        // see Supported Pixel Formats in the Quartz 2D Programming Guide
        // Creating a Bitmap Graphics Context section
        // only RGB 8 bit images with alpha of kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst,
        // and kCGImageAlphaPremultipliedLast, with a few other oddball image kinds are supported
        // The images on input here are likely to be png or jpeg files
        if (alphaInfo == kCGImageAlphaNone)
            alphaInfo = kCGImageAlphaNoneSkipLast;
    
        // Build a bitmap context that's the size of the thumbRect
        CGContextRef bitmap = CGBitmapContextCreate(
                    NULL,
                    thumbRect.size.width,       // width
                    thumbRect.size.height,      // height
                    CGImageGetBitsPerComponent(imageRef),   // really needs to always be 8
                    4 * thumbRect.size.width,   // rowbytes
                    CGImageGetColorSpace(imageRef),
                    alphaInfo
            );
    
        // Draw into the context, this scales the image
        CGContextDrawImage(bitmap, thumbRect, imageRef);
    
        // Get an image from the context and a UIImage
        CGImageRef  ref = CGBitmapContextCreateImage(bitmap);
        UIImage*    result = [UIImage imageWithCGImage:ref];
    
        CGContextRelease(bitmap);   // ok if NULL
        CGImageRelease(ref);
    
        return result;
    }
    

    希望这会有所帮助!

    【讨论】:

    • alphaInfo 问题可能是由于使用了错误的类型。请改用CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    【解决方案2】:

    一句话:没有。

    没有“相似表”是因为你误解了UIImagePickerController 是如何使用UIImagePickerControllerQualityTypeHigh 之类的。

    如果您使用UIImagePickerController 捕获静止图像,您将获得相关设备的默认(即最高)质量——从 iPhone 4s 的 8 MP 到 iPod touch 或 iPad 2 的

    但是,借助 AVFoundation,您可以选择,这要归功于您引用的会话预设。

    但与这些 AVFoundation 会话预设不同,UIImagePickerController UIImagePickerControllerQualityType 选项仅适用于动态视频,而不适用于静态图像捕获。

    因此,您可以选择使用 AVFoundation 来控制捕获大小,或者在保存之前重新调整全尺寸图像的大小;但恐怕UIImagePickerController 不能做你想做的事。

    【讨论】:

      【解决方案3】:

      Thermometer's answer 的问题在于它搞砸了图像方向。

      我发现this solution 解决了方向问题,性能更快:

      - (UIImage *)scaleAndRotateImage:(UIImage *)image {
          int kMaxResolution = 320; // Or whatever
      
          CGImageRef imgRef = image.CGImage;
      
          CGFloat width = CGImageGetWidth(imgRef);
          CGFloat height = CGImageGetHeight(imgRef);
      
          CGAffineTransform transform = CGAffineTransformIdentity;
          CGRect bounds = CGRectMake(0, 0, width, height);
          if (width > kMaxResolution || height > kMaxResolution) {
              CGFloat ratio = width/height;
              if (ratio > 1) {
                  bounds.size.width = kMaxResolution;
                  bounds.size.height = bounds.size.width / ratio;
              }
              else {
                  bounds.size.height = kMaxResolution;
                  bounds.size.width = bounds.size.height * ratio;
              }
          }
      
          CGFloat scaleRatio = bounds.size.width / width;
          CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
          CGFloat boundHeight;
          UIImageOrientation orient = image.imageOrientation;
          switch(orient) {
      
              case UIImageOrientationUp: //EXIF = 1
                  transform = CGAffineTransformIdentity;
                  break;
      
              case UIImageOrientationUpMirrored: //EXIF = 2
                  transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
                  transform = CGAffineTransformScale(transform, -1.0, 1.0);
                  break;
      
              case UIImageOrientationDown: //EXIF = 3
                  transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
                  transform = CGAffineTransformRotate(transform, M_PI);
                  break;
      
              case UIImageOrientationDownMirrored: //EXIF = 4
                  transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
                  transform = CGAffineTransformScale(transform, 1.0, -1.0);
                  break;
      
              case UIImageOrientationLeftMirrored: //EXIF = 5
                  boundHeight = bounds.size.height;
                  bounds.size.height = bounds.size.width;
                  bounds.size.width = boundHeight;
                  transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
                  transform = CGAffineTransformScale(transform, -1.0, 1.0);
                  transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
                  break;
      
              case UIImageOrientationLeft: //EXIF = 6
                  boundHeight = bounds.size.height;
                  bounds.size.height = bounds.size.width;
                  bounds.size.width = boundHeight;
                  transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
                  transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
                  break;
      
              case UIImageOrientationRightMirrored: //EXIF = 7
                  boundHeight = bounds.size.height;
                  bounds.size.height = bounds.size.width;
                  bounds.size.width = boundHeight;
                  transform = CGAffineTransformMakeScale(-1.0, 1.0);
                  transform = CGAffineTransformRotate(transform, M_PI / 2.0);
                  break;
      
              case UIImageOrientationRight: //EXIF = 8
                  boundHeight = bounds.size.height;
                  bounds.size.height = bounds.size.width;
                  bounds.size.width = boundHeight;
                  transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
                  transform = CGAffineTransformRotate(transform, M_PI / 2.0);
                  break;
      
              default:
                  [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
      
          }
      
          UIGraphicsBeginImageContext(bounds.size);
      
          CGContextRef context = UIGraphicsGetCurrentContext();
      
          if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
              CGContextScaleCTM(context, -scaleRatio, scaleRatio);
              CGContextTranslateCTM(context, -height, 0);
          }
          else {
              CGContextScaleCTM(context, scaleRatio, -scaleRatio);
              CGContextTranslateCTM(context, 0, -height);
          }
      
          CGContextConcatCTM(context, transform);
      
          CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
          UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return imageCopy;
      }
      

      【讨论】:

        【解决方案4】:

        对于您的 Swift 2.1 项目,这是@marcelosalloum 代码的翻译:

        func scaleAndRotateImage(image: UIImage, kMaxResolution: CGFloat) -> UIImage {
            var imageCopy: UIImage = image
            if let imgRef: CGImageRef = image.CGImage {
        
                let width = CGFloat(CGImageGetWidth(imgRef))
                let height = CGFloat(CGImageGetHeight(imgRef))
        
                var transform = CGAffineTransformIdentity
                var bounds = CGRectMake(0, 0, width, height)
        
                if width > kMaxResolution || height > kMaxResolution {
                    let ratio = width/height
                    if ratio > 1 {
                        bounds.size.width = kMaxResolution
                        bounds.size.height = bounds.size.width / ratio
                    } else {
                        bounds.size.height = kMaxResolution
                        bounds.size.width = bounds.size.height * ratio
                    }
                }
        
                let scaleRatio = bounds.size.width / width
                let imageSize = CGSizeMake(width, height)
                let boundHeight: CGFloat
                let orient: UIImageOrientation = image.imageOrientation
                switch orient {
                case .Up:
                    transform = CGAffineTransformIdentity
        
                case .UpMirrored:
                    transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0)
                    transform = CGAffineTransformScale(transform, -1.0, 1.0)
        
                case .Down:
                    transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height)
                    transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
        
                case .DownMirrored: //EXIF = 4
                    transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
                    transform = CGAffineTransformScale(transform, 1.0, -1.0);
        
                case .LeftMirrored: //EXIF = 5
                    boundHeight = bounds.size.height;
                    bounds.size.height = bounds.size.width;
                    bounds.size.width = boundHeight;
                    transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
                    transform = CGAffineTransformScale(transform, -1.0, 1.0);
                    transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
        
                case .Left: //EXIF = 6
                    boundHeight = bounds.size.height;
                    bounds.size.height = bounds.size.width;
                    bounds.size.width = boundHeight;
                    transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
                    transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
        
                case .RightMirrored: //EXIF = 7
                    boundHeight = bounds.size.height;
                    bounds.size.height = bounds.size.width;
                    bounds.size.width = boundHeight;
                    transform = CGAffineTransformMakeScale(-1.0, 1.0);
                    transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
        
                case .Right: //EXIF = 8
                    boundHeight = bounds.size.height;
                    bounds.size.height = bounds.size.width;
                    bounds.size.width = boundHeight;
                    transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
                    transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
                }
                UIGraphicsBeginImageContext(bounds.size)
        
                if let context: CGContextRef = UIGraphicsGetCurrentContext() {
                    if orient == .Right || orient == .Left {
                        CGContextScaleCTM(context, -scaleRatio, scaleRatio)
                        CGContextTranslateCTM(context, -height, 0)
                    } else {
                        CGContextScaleCTM(context, scaleRatio, -scaleRatio)
                        CGContextTranslateCTM(context, 0, -height)
                    }
        
                    CGContextConcatCTM(context, transform)
        
                    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0,0,width,height), imgRef)
                    imageCopy = UIGraphicsGetImageFromCurrentImageContext()
                    UIGraphicsEndImageContext()
                }
            }
            return imageCopy
        }
        

        【讨论】:

          【解决方案5】:

          marcelosalloum's answer 的 swift 3 翻译:

          private func scale(image originalImage: UIImage, toLessThan maxResolution: CGFloat) -> UIImage? {
              guard let imageReference = originalImage.cgImage else { return nil }
          
              let rotate90 = CGFloat.pi/2.0 // Radians
              let rotate180 = CGFloat.pi // Radians
              let rotate270 = 3.0*CGFloat.pi/2.0 // Radians
          
              let originalWidth = CGFloat(imageReference.width)
              let originalHeight = CGFloat(imageReference.height)
              let originalOrientation = originalImage.imageOrientation
          
              var newWidth = originalWidth
              var newHeight = originalHeight
          
              if originalWidth > maxResolution || originalHeight > maxResolution {
                  let aspectRatio: CGFloat = originalWidth / originalHeight
                  newWidth = aspectRatio > 1 ? maxResolution : maxResolution * aspectRatio
                  newHeight = aspectRatio > 1 ? maxResolution / aspectRatio : maxResolution
              }
          
              let scaleRatio: CGFloat = newWidth / originalWidth
              var scale: CGAffineTransform = .init(scaleX: scaleRatio, y: -scaleRatio)
              scale = scale.translatedBy(x: 0.0, y: -originalHeight)
          
              var rotateAndMirror: CGAffineTransform
          
              switch originalOrientation {
              case .up:
                  rotateAndMirror = .identity
          
              case .upMirrored:
                  rotateAndMirror = .init(translationX: originalWidth, y: 0.0)
                  rotateAndMirror = rotateAndMirror.scaledBy(x: -1.0, y: 1.0)
          
              case .down:
                  rotateAndMirror = .init(translationX: originalWidth, y: originalHeight)
                  rotateAndMirror = rotateAndMirror.rotated(by: rotate180 )
          
              case .downMirrored:
                  rotateAndMirror = .init(translationX: 0.0, y: originalHeight)
                  rotateAndMirror = rotateAndMirror.scaledBy(x: 1.0, y: -1.0)
          
              case .left:
                  (newWidth, newHeight) = (newHeight, newWidth)
                  rotateAndMirror = .init(translationX: 0.0, y: originalWidth)
                  rotateAndMirror = rotateAndMirror.rotated(by: rotate270)
                  scale = .init(scaleX: -scaleRatio, y: scaleRatio)
                  scale = scale.translatedBy(x: -originalHeight, y: 0.0)
          
              case .leftMirrored:
                  (newWidth, newHeight) = (newHeight, newWidth)
                  rotateAndMirror = .init(translationX: originalHeight, y: originalWidth)
                  rotateAndMirror = rotateAndMirror.scaledBy(x: -1.0, y: 1.0)
                  rotateAndMirror = rotateAndMirror.rotated(by: rotate270)
          
              case .right:
                  (newWidth, newHeight) = (newHeight, newWidth)
                  rotateAndMirror = .init(translationX: originalHeight, y: 0.0)
                  rotateAndMirror = rotateAndMirror.rotated(by: rotate90)
                  scale = .init(scaleX: -scaleRatio, y: scaleRatio)
                  scale = scale.translatedBy(x: -originalHeight, y: 0.0)
          
              case .rightMirrored:
                  (newWidth, newHeight) = (newHeight, newWidth)
                  rotateAndMirror = .init(scaleX: -1.0, y: 1.0)
                  rotateAndMirror = rotateAndMirror.rotated(by: CGFloat.pi/2.0)
              }
          
              UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
              guard let context = UIGraphicsGetCurrentContext() else { return nil }
              context.concatenate(scale)
              context.concatenate(rotateAndMirror)
              context.draw(imageReference, in: CGRect(x: 0, y: 0, width: originalWidth, height: originalHeight))
              let copy = UIGraphicsGetImageFromCurrentImageContext()
              UIGraphicsEndImageContext()
          
              return copy
            }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-14
            • 1970-01-01
            • 2013-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-05
            • 1970-01-01
            相关资源
            最近更新 更多