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

时间:2012-09-04 06:59:21

标签: iphone ios ios4 uiimagepickercontroller

我想拍下A4纸的照片。重要的是,我希望文本可读,但我不希望像2592x1936像素或3264x2448像素这样的分辨率的图像太大。此外,我认为捕获后重新缩放照片需要额外的时间,所以我也想避免这种情况。

我们可以选择以下品质:

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

如果我们使用AVFoundation,我们可以选择this nice table的分辨率(标题为“捕捉静止图像”)。

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

5 个答案:

答案 0 :(得分:18)

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;
}

希望这有帮助!

答案 1 :(得分:5)

总之:不。

没有“类似的表格”,因为您误解了UIImagePickerControllerQualityTypeHighUIImagePickerController的使用情况的误解。

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

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

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

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

答案 2 :(得分:2)

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;
}

答案 3 :(得分:2)

对于你的Swift 2.1-Project,这是@ 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
}

答案 4 :(得分:2)

marcelosalloum's answer的快速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
  }