iOS開發--解決拍照後照片旋轉90度的問題(附Swift版本),iosswift
當我們使用相機拍照後,調用UIImagePickerController的delegate方法,如下代碼所示:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];}
通過UIImagePickerControllerOriginalImage這個key從info字典中可以擷取到拍照後的UIImage,但如果斷點查看圖片,我們會發現圖片是旋轉了90度的。
不過如果直接使用圖片,比如使用這個UIImage賦值給一個UIImageView的執行個體,顯示出來的圖片是完全沒有問題的。
但如果使用這個UIImage作他用,比如上傳到伺服器,就會出現問題了,上傳到伺服器的圖片也是旋轉了90度的。
原因:通過UIImagePickerControllerOriginalImage這個key從info字典中可以擷取到拍照後的UIImage,其imageOrientation屬性預設是UIImageOrientationRight,也就是說預設就是向左側旋轉了90度的。
解決方案如下:
方法一:建立UIImagePickerController執行個體的時候,設定執行個體的一個屬性allowsEditing為YES,設了這個值,拍完照片後會在照片上出現一個框框,可以對照片的裁剪編輯。在UIImagePickerController的代理方法中取照片的時候也就別用UIImagePickerControllerOriginalImage這個key來取了,而要用UIImagePickerControllerEditedImage,此時取出來的照片,它的imageOrientation是UIImageOrientationUp而不是預設的UIImageOrientationRight了。
方法二:有一個專門針對UIImage旋轉這個問題的很好的Category,代碼如下:
OC版本:
UIImage+fixOrientation.h
#import <UIKit/UIKit.h>@interface UIImage (fixOrientation)- (UIImage *)fixOrientation;@end
UIImage+fixOrientation.m
#import "UIImage+fixOrientation.h"@implementation UIImage (fixOrientation)- (UIImage *)fixOrientation { // No-op if the orientation is already correct if (self.imageOrientation == UIImageOrientationUp) return self; // 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 (self.imageOrientation) { case UIImageOrientationDown: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, 0, self.size.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; } switch (self.imageOrientation) { case UIImageOrientationUpMirrored: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, self.size.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; } // Now we draw the underlying CGImage into a new context, applying the transform // calculated above. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)); CGContextConcatCTM(ctx, transform); switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: // Grr... CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage); break; default: CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.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;}@end
Swift版本:
import UIKitextension UIImage { // 修複圖片旋轉 func fixOrientation() -> UIImage { if self.imageOrientation == .up { return self } var transform = CGAffineTransform.identity switch self.imageOrientation { case .down, .downMirrored: transform = transform.translatedBy(x: self.size.width, y: self.size.height) transform = transform.rotated(by: .pi) break case .left, .leftMirrored: transform = transform.translatedBy(x: self.size.width, y: 0) transform = transform.rotated(by: .pi / 2) break case .right, .rightMirrored: transform = transform.translatedBy(x: 0, y: self.size.height) transform = transform.rotated(by: -.pi / 2) break default: break } switch self.imageOrientation { case .upMirrored, .downMirrored: transform = transform.translatedBy(x: self.size.width, y: 0) transform = transform.scaledBy(x: -1, y: 1) break case .leftMirrored, .rightMirrored: transform = transform.translatedBy(x: self.size.height, y: 0); transform = transform.scaledBy(x: -1, y: 1) break default: break } let ctx = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height), bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0, space: self.cgImage!.colorSpace!, bitmapInfo: self.cgImage!.bitmapInfo.rawValue) ctx?.concatenate(transform) switch self.imageOrientation { case .left, .leftMirrored, .right, .rightMirrored: ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.height), height: CGFloat(size.width))) break default: ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.width), height: CGFloat(size.height))) break } let cgimg: CGImage = (ctx?.makeImage())! let img = UIImage(cgImage: cgimg) return img }}