2013-04-11 2 views
10

Что-то действительно странное происходит, я пытаюсь захватить изображение с помощью AVFoundation, изображение ролика камеры кажется просто прекрасным, но просмотр изображения имеет поворот изображения на 90 градусов.AVFoundation Ориентация изображения на 90 градусов в предварительном просмотре, но отлично в рулоне камеры

Это код, я использую для захвата изображения

AVCaptureConnection *videoConnection = nil; 
for (AVCaptureConnection *connection in stillImageOutput.connections) 
{ 
    for (AVCaptureInputPort *port in [connection inputPorts]) 
    { 
     if ([[port mediaType] isEqual:AVMediaTypeVideo]) 
     { 
      videoConnection = connection; 
      break; 
     } 
    } 
    if (videoConnection) 
    { 
     break; 
    } 
} 

//NSLog(@"about to request a capture from: %@", stillImageOutput); 
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) 
{ 
    CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 
    if (exifAttachments) 
    { 
     // Do something with the attachments. 
     //NSLog(@"attachements: %@", exifAttachments); 
    } else { 
     NSLog(@"no attachments"); 
    } 

    NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 

    UIImage *image = [[UIImage alloc] initWithData:imageData]; 

    self.vImage.image = image; 

    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 
}]; 
+7

Почему получить голос вниз по дороге? является ли решение тривиальным? если это пожалуйста, просветите меня! Это место, где можно научиться не избегать. Я стараюсь учиться так же, как и в какой-то момент! – Jonathan

+0

У меня эта работа предварительного просмотра работает правильно, если да, то PLS поделится этим с нами –

ответ

43

да, это происходит, когда вы захват изображения в портретной ориентации устройства и использовать это изображение в приложении, поскольку ориентация по умолчанию изображения является ландшафтом на любом устройстве IOS, поэтому вам нужно изменить ориентацию изображения после выбора из галереи, чтобы использовать его в своем приложении.

Я поставил код для достижения этой цели

код Objective-C

- (UIImage *)fixOrientationOfImage:(UIImage *)image { 

    // No-op if the orientation is already correct 
    if (image.imageOrientation == UIImageOrientationUp) return image; 

    // We need to calculate the proper transformation to make the image upright. 
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 
    CGAffineTransform transform = CGAffineTransformIdentity; 

    switch (image.imageOrientation) { 
     case UIImageOrientationDown: 
     case UIImageOrientationDownMirrored: 
      transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 

     case UIImageOrientationLeft: 
     case UIImageOrientationLeftMirrored: 
      transform = CGAffineTransformTranslate(transform, image.size.width, 0); 
      transform = CGAffineTransformRotate(transform, M_PI_2); 
      break; 

     case UIImageOrientationRight: 
     case UIImageOrientationRightMirrored: 
      transform = CGAffineTransformTranslate(transform, 0, image.size.height); 
      transform = CGAffineTransformRotate(transform, -M_PI_2); 
      break; 
     case UIImageOrientationUp: 
     case UIImageOrientationUpMirrored: 
      break; 
    } 

    switch (image.imageOrientation) { 
     case UIImageOrientationUpMirrored: 
     case UIImageOrientationDownMirrored: 
      transform = CGAffineTransformTranslate(transform, image.size.width, 0); 
      transform = CGAffineTransformScale(transform, -1, 1); 
      break; 

     case UIImageOrientationLeftMirrored: 
     case UIImageOrientationRightMirrored: 
      transform = CGAffineTransformTranslate(transform, image.size.height, 0); 
      transform = CGAffineTransformScale(transform, -1, 1); 
      break; 
     case UIImageOrientationUp: 
     case UIImageOrientationDown: 
     case UIImageOrientationLeft: 
     case UIImageOrientationRight: 
      break; 
    } 

    // Now we draw the underlying CGImage into a new context, applying the transform 
    // calculated above. 
    CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height, 
              CGImageGetBitsPerComponent(image.CGImage), 0, 
              CGImageGetColorSpace(image.CGImage), 
              CGImageGetBitmapInfo(image.CGImage)); 
    CGContextConcatCTM(ctx, transform); 
    switch (image.imageOrientation) { 
     case UIImageOrientationLeft: 
     case UIImageOrientationLeftMirrored: 
     case UIImageOrientationRight: 
     case UIImageOrientationRightMirrored: 
      // Grr... 
      CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage); 
      break; 

     default: 
      CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage); 
      break; 
    } 

    // And now we just create a new UIImage from the drawing context 
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx); 
    UIImage *img = [UIImage imageWithCGImage:cgimg]; 
    CGContextRelease(ctx); 
    CGImageRelease(cgimg); 
    return img; 
} 

Swift код

func fixOrientationOfImage(image: UIImage) -> UIImage? { 
    if image.imageOrientation == .Up { 
     return image 
    } 

    // We need to calculate the proper transformation to make the image upright. 
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 
    var transform = CGAffineTransformIdentity 

    switch image.imageOrientation { 
    case .Down, .DownMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height) 
     transform = CGAffineTransformRotate(transform, CGFloat(M_PI)) 
    case .Left, .LeftMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, 0) 
     transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2)) 
    case .Right, .RightMirrored: 
     transform = CGAffineTransformTranslate(transform, 0, image.size.height) 
     transform = CGAffineTransformRotate(transform, -CGFloat(M_PI_2)) 
    default: 
     break 
    } 

    switch image.imageOrientation { 
    case .UpMirrored, .DownMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, 0) 
     transform = CGAffineTransformScale(transform, -1, 1) 
    case .LeftMirrored, .RightMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.height, 0) 
     transform = CGAffineTransformScale(transform, -1, 1) 
    default: 
     break 
    } 

    // Now we draw the underlying CGImage into a new context, applying the transform 
    // calculated above. 
    guard let context = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage).rawValue) else { 
     return nil 
    } 

    CGContextConcatCTM(context, transform) 

    switch image.imageOrientation { 
    case .Left, .LeftMirrored, .Right, .RightMirrored: 
     CGContextDrawImage(context, CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width), image.CGImage) 
    default: 
     CGContextDrawImage(context, CGRect(origin: .zero, size: image.size), image.CGImage) 
    } 

    // And now we just create a new UIImage from the drawing context 
    guard let CGImage = CGBitmapContextCreateImage(context) else { 
     return nil 
    } 

    return UIImage(CGImage: CGImage) 
} 

Swift 3.0

func fixOrientationOfImage(image: UIImage) -> UIImage? { 
    if image.imageOrientation == .up { 
     return image 
    } 

    // We need to calculate the proper transformation to make the image upright. 
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 
    var transform = CGAffineTransform.identity 

    switch image.imageOrientation { 
     case .down, .downMirrored: 
     transform = transform.translatedBy(x: image.size.width, y: image.size.height) 
     transform = transform.rotated(by: CGFloat(Double.pi)) 
    case .left, .leftMirrored: 
     transform = transform.translatedBy(x: image.size.width, y: 0) 
     transform = transform.rotated(by: CGFloat(Double.pi/2)) 
    case .right, .rightMirrored: 
     transform = transform.translatedBy(x: 0, y: image.size.height) 
     transform = transform.rotated(by: -CGFloat(Double.pi/2)) 
    default: 
     break 
    } 

    switch image.imageOrientation { 
    case .upMirrored, .downMirrored: 
     transform = transform.translatedBy(x: image.size.width, y: 0) 
     transform = transform.scaledBy(x: -1, y: 1) 
    case .leftMirrored, .rightMirrored: 
     transform = transform.translatedBy(x: image.size.height, y: 0) 
     transform = transform.scaledBy(x: -1, y: 1) 
    default: 
     break 
    } 

    // Now we draw the underlying CGImage into a new context, applying the transform 
    // calculated above. 
    guard let context = CGContext(data: nil, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: image.cgImage!.bitsPerComponent, bytesPerRow: 0, space: image.cgImage!.colorSpace!, bitmapInfo: image.cgImage!.bitmapInfo.rawValue) else { 
     return nil 
    } 

    context.concatenate(transform) 

    switch image.imageOrientation { 
     case .left, .leftMirrored, .right, .rightMirrored: 
     context.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width)) 
     default: 
      context.draw(image.cgImage!, in: CGRect(origin: .zero, size: image.size)) 
    } 

    // And now we just create a new UIImage from the drawing context 
    guard let CGImage = context.makeImage() else { 
     return nil 
    } 

    return UIImage(cgImage: CGImage) 
} 
+0

Dipen, да, я закончил тем, что использовал что-то подобное. но я столкнулся с другой проблемой, я хочу, чтобы мое сохраненное изображение было обрезано для содержимого, которое я показываю в своем квадратном контейнере видео. но это не так, его даже сохранение части изображения, которое не видно в поле. – Jonathan

+0

, для этого вам нужно использовать некоторые методы обрезки для обрезки изображения, которые доступны в рамках QuartzCore. –

+0

ОТЛИЧНО! Большое спасибо!!!! Потребовалось 3 часа с этой проблемой. – horseshoe7

1

Принятый ответ работает, но гораздо сложнее, чем нужно. Для поворота изображения вы можете использовать следующее.

- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect { 
    CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) { 
     return deg/180.0f * (CGFloat) M_PI; 
    }; 

    // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position 
    CGAffineTransform rectTransform; 
    switch (image.imageOrientation) { 
     case UIImageOrientationLeft: 
      rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height); 
      break; 
     case UIImageOrientationRight: 
      rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0); 
      break; 
     case UIImageOrientationDown: 
      rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height); 
      break; 
     default: 
      rectTransform = CGAffineTransformIdentity; 
    }; 

    // adjust the transformation scale based on the image scale 
    rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale); 

    // apply the transformation to the rect to create a new, shifted rect 
    CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform); 
    // use the rect to crop the image 
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare); 
    // create a new UIImage and set the scale and orientation appropriately 
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation]; 
    // memory cleanup 
    CGImageRelease(imageRef); 

    return result; 
} 

Чтобы просто повернуть изображение, а не урожай, вы можете просто назвать это так:

UIImage *image; 
[self cropImage:image toRect:rect.bounds]; 
+0

Не работает во всех ориентациях устройств – decades

+0

@decades, для которых ориентация и устройство не работают? Кроме того, имейте в виду, что это смотрит на ориентацию изображения, поэтому, если оно не записано в изображение (которое, я считаю, вам нужно установить вручную, если вы создадите свой собственный вокруг структур AV), это не сработает. – mikeho

+0

Я пытался использовать ваш код в сочетании с результатами captureStillImageAsynchronouslyFromConnection. Возможно, я ошибся здесь – decades

Смежные вопросы