2012-09-04 4 views
9

Vorrei scattare foto di fogli A4 con la scritta sopra. È importante sottolineare che voglio che il testo sia leggibile, ma non voglio che le immagini con risoluzioni come 2592x1936 pixel o 3264x2448 pixel siano troppo grandi. Inoltre, presumo che il riscalaggio della foto dopo l'acquisizione richieda più tempo, quindi vorrei evitare anche questo.Cattura di foto con risoluzione specifica utilizzando UIImagePickerController

Possiamo scegliere tra le seguenti qualità:

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

Se stavamo usando il AVFoundation, potremmo scegliere risoluzioni da this nice table (sotto titolo "Acquisizione di immagini").

Ma c'è una tabella simile per UIImagePickerController, che ad esempio dice che UIImagePickerControllerQualityTypeHigh equivale a 1920x1080 su iPhone 3gs?

risposta

15

UIImagepickerController quality viene utilizzato per la registrazione video (utilizzato nella proprietà UIImagepickerController "videoQuality").

Immagino che se si desidera specificare quale dovrebbe essere la risoluzione esatta della foto, è necessario utilizzare il framework AV Foundation anziché UIImagepickerController. O come hai detto, converti l'immagine in seguito.

per ridimensionarlo in seguito (trovati 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; 
} 

Spero che questo aiuti!

+0

Il problema 'alphaInfo' è probabilmente dovuto al tipo sbagliato utilizzato. Usa 'CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo (imageRef);' invece. – Berik

4

In una parola: no.

Non c'è "tabella simile" perché non si capisce come i tipi di UIImagePickerControllerQualityTypeHigh siano utilizzati da UIImagePickerController.

Se acquisite immagini fisse con UIImagePickerController, le otterrete alla qualità predefinita (ovvero massima) del dispositivo in questione, ovunque da 8 MP con iPhone 4s a < 1 MP con iPod touch o iPad 2).

Con AVFoundation, tuttavia, è possibile scegliere, grazie ai preset di sessione a cui si fa riferimento.

Ma a differenza di questi preset di sessione AVFoundation, le opzioni UIImagePickerControllerUIImagePickerControllerQualityType si applicano solo al video in movimento, non all'immagine catturata.

Così puoi scegliere di utilizzare AVFoundation per controllare le dimensioni di cattura o ridimensionare le immagini a schermo intero prima di salvarle; ma UIImagePickerController non posso fare quello che vuoi, ho paura.

2

Il problema con Thermometer's answer è che si avvita con l'orientamento dell'immagine.

ho trovato this solution che risolve il problema di orientamento e ha una performance più veloce:

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

Per la vostra Swift 2.1-Project, questa è la traduzione di codici @ di 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 
} 
1

Un rapido 3 traduzione di marcelosalloum's answer:

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 
    }