2012-09-04 7 views
9

Ich möchte Fotos von A4-Papier mit dem Schreiben auf Fotos machen. Wichtig ist, dass der Text lesbar sein soll, aber ich möchte keine Bilder mit Auflösungen wie 2592x1936 Pixel oder 3264x2448 Pixel, da dies zu groß wäre. Außerdem gehe ich davon aus, dass die Neuskalierung des Fotos nach der Aufnahme zusätzliche Zeit in Anspruch nimmt, daher möchte ich dies auch vermeiden.Aufnahme von Fotos mit einer bestimmten Auflösung mit dem UIImagePickerController

Wir können zwischen den folgenden Qualitäten wählen:

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

Wenn wir die AVFoundation verwendet haben, wir Auflösungen von this nice table wählen könnte (unter Überschrift „Aufnahme von Standbildern“).

Aber gibt es eine ähnliche Tabelle für UIImagePickerController, die zum Beispiel sagt, dass UIImagePickerControllerQualityTypeHigh entspricht 1920x1080 auf iPhone 3gs?

Antwort

15

UIImagepickerController quality wird für die Videoaufnahme verwendet (wird in der UIImagepickerController-Eigenschaft "videoQuality" verwendet).

Ich denke, wenn Sie angeben möchten, was die genaue Fotoauflösung sein sollte, sollten Sie das AV Foundation Framework anstelle von UIImagepickerController verwenden. Oder wie du gesagt hast, konvertiere das Bild danach.

es um die Größe danach (gefunden 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; 
} 

hoffe, das hilft!

+0

Das 'alphaInfo' Problem ist wahrscheinlich auf die falsche Art verwendet. Verwenden Sie stattdessen 'CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo (imageRef);'. – Berik

4

In einem Wort: nein.

Es gibt keine "ähnliche Tabelle", weil Sie missverstehen, wie die UIImagePickerControllerQualityTypeHigh von UIImagePickerController verwendet werden.

Wenn Sie Standbilder mit UIImagePickerController erfassen, erhalten Sie diese in der Standardqualität (d. H. Maximal) des jeweiligen Geräts - von 8 MP mit iPhone 4s bis < 1 MP mit iPod touch oder iPad 2).

Mit AVFoundation haben Sie jedoch dank der Sitzungsvoreinstellungen, auf die Sie sich beziehen, eine Auswahl.

Im Gegensatz zu diesen AVFoundation-Sitzungsvoreinstellungen gelten die Optionen UIImagePickerControllerUIImagePickerControllerQualityType jedoch nur für Bewegtbilder und nicht für Standbildaufnahmen.

So haben Sie die Wahl, AVFoundation zu verwenden, um die Aufnahmegröße zu steuern oder die Bilder in voller Größe zu ändern, bevor Sie sie speichern; aber UIImagePickerController kann nicht tun, was Sie wollen, fürchte ich.

2

Das Problem mit Thermometer's answer ist, dass es mit der Bildausrichtung verschraubt.

Ich habe this solution gefunden, der die Ausrichtung Problem löst und hat eine schnellere Leistung:

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

Für Ihre Swift 2.1-Projekt, das ist die Übersetzung von @ marcelosalloum Code:

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

Eine schnelle 3 Übersetzung von 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 
    }