最近在接入一個拍照翻譯的api時,發現用自帶相機拍攝的照片傳上去時返回的文字的rect對不上,而去相冊里把照片截屏再上傳之又是正常的,在排查了一段時間之后終于在輸出照片的大小時發現了端倪
CGFloat imageW = CGImageGetWidth(photo.CGImage);
CGFloat imageH = CGImageGetHeight(photo.CGImage);
在用上面的方法輸出圖片的高度和寬度時,發現用相機拍攝的照片輸出的寬度居然大于高度,可UIimageView里顯示的照片明顯是高度比寬度大一些的,于是上網搜索有關資料,果不其然:
相機拍照后直接取出來的UIimage(用UIImagePickerControllerOriginalImage取出),它本身的imageOrientation屬性是3,即UIImageOrientationRight。如果這個圖片直接使用則沒事,但是如果對它進行裁剪、縮放等操作后,它的這個imageOrientation屬性會變成0。此時這張圖片用在別的地方就會發生旋轉。imageOrientation是只讀的,不能直接修改其值。
最坑的地方在于,UIimageView在使用照片的時候會自動旋轉回來,這給人的誤導就是如果不通過CGImageGetHeight
的方式輸出照片的寬高,根本無法發現這個問題!因為你看到屏幕上顯示的圖片確實是正常的
知道了原因,解決起來就簡單了,給UIImage寫一個分類解決這個問題:
- (UIImage *)fixOrientation{
// No-op if the orientation is already correct
UIImage *image = self;
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;
default:
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;
default:
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 *resultImg = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return resultImg;
}
使用時,直接調用- (UIImage *)fixOrientation
方法即可