1. 程式人生 > >iOS中(相簿)攝像頭獲取的圖片上傳至伺服器被自動旋轉了

iOS中(相簿)攝像頭獲取的圖片上傳至伺服器被自動旋轉了

今天寫專案的時候發現, 通過相機(相簿)獲取到的圖片顯示是正的,但是上傳至伺服器後下次從伺服器讀取就被莫名其妙的旋轉了,開始時候以為是伺服器的原因,最後原來是我的原因:如果把通過相機獲取到的圖片,直接進行操作, 比如裁剪, 縮放, 則會把原圖片向右旋轉90度。

上網查後也有人說是這個原因:如果該圖片大於2M,會自動旋轉90度;否則不旋轉

  1. //get original photo from iOS photos 
  2. //如果該圖片大於2M,會自動旋轉90度;否則不旋轉
  3. UIImage* originalImg=[dict objectForKey:UIImagePickerControllerOriginalImage];  
不知道是否是上邊的原因,至於是否正確, 還沒確定。 先Mark,哈哈。

下邊說下解決方案:用相機拍攝出來的照片含有EXIF資訊,UIImage的imageOrientation屬性指的就是EXIF中的orientation資訊。
如果我們忽略orientation資訊,而直接對照片進行畫素處理或者drawInRect等操作,得到的結果是翻轉或者旋轉90之後的樣子。這是因為我們執行畫素處理或者drawInRect等操作之後,imageOrientaion資訊被刪除了,imageOrientaion被重設為0,造成照片內容和imageOrientaion不匹配。
所以,在對照片進行處理之前,先將照片旋轉到正確的方向,並且返回的imageOrientaion為0。
下面這個方法就是一個UIImage category中的方法,用它可以達到以上目的。

上程式碼:

  1. - (UIImage *)fixOrientation:(UIImage *)aImage {  
  2.     // No-op if the orientation is already correct
  3.     if (aImage.imageOrientation == UIImageOrientationUp)   
  4.         return aImage;  
  5.     // We need to calculate the proper transformation to make the image upright.
  6.     // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
  7.     CGAffineTransform transform = CGAffineTransformIdentity;  
  8.     switch (aImage.imageOrientation) {  
  9.         case UIImageOrientationDown:  
  10.         case UIImageOrientationDownMirrored:  
  11.             transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);  
  12.             transform = CGAffineTransformRotate(transform, M_PI);  
  13.             break;  
  14.         case UIImageOrientationLeft:  
  15.         case UIImageOrientationLeftMirrored:  
  16.             transform = CGAffineTransformTranslate(transform, aImage.size.width0);  
  17.             transform = CGAffineTransformRotate(transform, M_PI_2);  
  18.             break;  
  19.         case UIImageOrientationRight:  
  20.         case UIImageOrientationRightMirrored:  
  21.             transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);  
  22.             transform = CGAffineTransformRotate(transform, -M_PI_2);  
  23.             break;  
  24.         default:  
  25.             break;  
  26.     }  
  27.     switch (aImage.imageOrientation) {  
  28.         case UIImageOrientationUpMirrored:  
  29.         case UIImageOrientationDownMirrored:  
  30.             transform = CGAffineTransformTranslate(transform, aImage.size.width0);  
  31.             transform = CGAffineTransformScale(transform, -11);  
  32.             break;  
  33.         case UIImageOrientationLeftMirrored:  
  34.         case UIImageOrientationRightMirrored:  
  35.             transform = CGAffineTransformTranslate(transform, aImage.size.height0);  
  36.             transform = CGAffineTransformScale(transform, -11);  
  37.             break;  
  38.         default:  
  39.             break;  
  40.     }  
  41.     // Now we draw the underlying CGImage into a new context, applying the transform
  42.     // calculated above.
  43.     CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,  
  44.                                              CGImageGetBitsPerComponent(aImage.CGImage), 0,  
  45.                                              CGImageGetColorSpace(aImage.CGImage),  
  46.                                              CGImageGetBitmapInfo(aImage.CGImage));  
  47.     CGContextConcatCTM(ctx, transform);  
  48.     switch (aImage.imageOrientation) {  
  49.         case UIImageOrientationLeft:  
  50.         case UIImageOrientationLeftMirrored:  
  51.         case UIImageOrientationRight:  
  52.         case UIImageOrientationRightMirrored:  
  53.             // Grr...
  54.             CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);  
  55.             break;  
  56.         default:  
  57.             CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);  
  58.             break;  
  59.     }  
  60.     // And now we just create a new UIImage from the drawing context
  61.     CGImageRef cgimg = CGBitmapContextCreateImage(ctx);  
  62.     UIImage *img = [UIImage imageWithCGImage:cgimg];  
  63.     CGContextRelease(ctx);  
  64.     CGImageRelease(cgimg);  
  65.     return img;  
  66. }  

上邊方法親自測試用過絕對靠譜。下面擷取專案中用此方法的片段:
  1. UIImageView *aImageView=[[[UIImageView alloc]init]autorelease];  
  2. [aImageView setFrame:CGRectMake(INSETS-855, PIC_WIDTH, PIC_HEIGHT)];  
  3. aImageView = [addedPicArray objectAtIndex:0];  
  4. NSData *imageData = UIImageJPEGRepresentation([self fixOrientation:aImageView.image], 0.1);  
  5. // 上傳資訊至伺服器
  6. [self setPlayerImageRequest:imageData];//先上傳玩發表的圖片,然後在發表文字

經過轉後的image上傳至伺服器就是正常方向了。