使用UIImagePickerController捕获具有特定分辨率的照片

13

我希望拍摄有文字的A4纸张照片,重要的是我想保证文本清晰可读,但不想使用2592x1936像素或3264x2448像素这样分辨率太高的图像。此外,我认为在捕捉后重新调整照片大小会花费额外的时间,所以我也想避免这种情况。

以下是我们可以选择的质量:

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

如果我们使用AVFoundation,我们可以从这个很好的表格(标题为“捕获静态图像”)中选择分辨率。

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

5个回答

19

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);”。 - Berik

5
简而言之:不行。
这是因为您误解了像UIImagePickerControllerQualityTypeHigh这样的选项在UIImagePickerController中的使用方式。
如果您使用UIImagePickerController捕获静态图像,则会以设备的默认(即最大)质量获取它们 - 从 iPhone 4s 的8 MP到 iPod touch或iPad 2的小于1 MP。
然而,通过AVFoundation,您有选择的余地,感谢您参考的会话预设。
但是,与这些AVFoundation会话预设不同,UIImagePickerController中的UIImagePickerControllerQualityType选项仅适用于动态视频,而不是静态图像捕获。
因此,您可以选择使用AVFoundation来控制捕获大小,或在保存它们之前重新调整完整大小图像;但是,很遗憾,UIImagePickerController不能做到您想要的。

2
温度计的答案的问题在于它会影响图像的方向。”
“我找到了这个解决方案,可以解决方向问题,而且速度更快。”
- (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;
}

2

对于您的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
}

2
一份快速的 Swift 3 翻译:marcelosalloum 的回答
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
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接