2012-09-04 15 views
9

Me gustaría tomar fotos de hojas de papel A4 con la escritura activada. Es importante destacar que quiero que el texto sea legible, pero no quiero imágenes con resoluciones como 2592x1936 píxeles o 3264x2448 píxeles, ya que sería demasiado grande. Además, supongo que volver a escalar la foto después de la captura lleva más tiempo, así que me gustaría evitar esto también.Capturar fotos con resolución específica usando el UIImagePickerController

Podemos elegir entre las siguientes cualidades:

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

Si estábamos usando el AVFoundation, podríamos elegir resoluciones de this nice table (bajo título "Captura de imágenes fijas").

¿Pero hay una tabla similar para UIImagePickerController, que por ejemplo dice que UIImagePickerControllerQualityTypeHigh es igual a 1920x1080 en iPhone 3gs?

Respuesta

15

UIImagepickerController quality se utiliza para la grabación de video (utilizado en la propiedad UIImagepickerController "videoQuality").

Supongo que si desea especificar cuál debe ser la resolución de foto exacta, debe utilizar el marco de AV Foundation en lugar del UIImagepickerController. O como dijiste, convierte la imagen después.

para cambiar su tamaño después (encontrado 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; 
} 

Espero que esto ayude!

+0

El tema 'alphaInfo' es probablemente debido al tipo equivocado utilizado. Utilice 'CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo (imageRef);' en su lugar. – Berik

4

En una palabra: no.

No hay una "tabla similar" porque no está entendiendo cómo UIImagePickerControllerQualityTypeHigh son usados ​​por UIImagePickerController.

Si está capturando imágenes estáticas con UIImagePickerController, las obtendrá con la calidad predeterminada (es decir, máxima) del dispositivo en cuestión, desde 8 MP con iPhone 4s a < 1 MP con iPod touch o iPad 2).

Con AVFoundation, sin embargo, tiene opciones, gracias a los preajustes de sesión a los que se refiere.

Pero a diferencia de estos preajustes de sesión de AVFoundation, las opciones UIImagePickerControllerUIImagePickerControllerQualityType solo se aplican al video en movimiento, no a la captura de imágenes fijas.

Así que tiene la opción de utilizar AVFoundation para controlar el tamaño de captura, o cambiar el tamaño de las imágenes de tamaño completo antes de guardarlas; pero me temo que UIImagePickerController no puede hacer lo que usted quiere.

2

El problema con Thermometer's answer es que se atornilla con la orientación de la imagen.

que he encontrado this solution que resuelve el problema de la orientación y tiene un rendimiento más rápido:

- (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

Para su Swift 2.1-Proyecto, esta es la traducción del código de @ 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

Una traducción rápida de 3 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 
    } 
Cuestiones relacionadas