iOS 13保存UIImage方向错误:相机胶卷旋转,ImageView显示正常
关于竖屏照片保存到相机胶卷后显示旋转的问题
我之前也遇到过一模一样的问题,身边不少iOS开发者也反馈过类似情况,给你梳理下问题根源和解决方案:
问题核心原因
问题出在UIImage的orientation元数据上:
- 从
UIImagePickerController获取的原始图片,会携带拍摄时的方向信息(比如竖屏拍摄时orientation为Right或Left); UIImageView会自动识别并应用这个orientation元数据,所以显示出来是正常的;- 但直接用
UIImageWriteToSavedPhotosAlbum或PHAssetChangeRequest保存时,这些方法没有正确将orientation信息写入照片的EXIF数据,系统相册读取时会默认按Up方向显示,导致照片看起来是旋转状态。
解决方案:先修正图片方向再保存
最可靠的解决方法是先把图片转换成不带orientation偏移的位图,确保保存到相册的图片本身就是正确方向。你可以添加一个工具方法来修正图片方向:
- (UIImage *)fixImageOrientation:(UIImage *)image { // 如果图片方向已经是Up,直接返回 if (image.imageOrientation == UIImageOrientationUp) return image; 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; } // 创建绘图上下文并应用变换 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: 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; } // 生成修正后的UIImage CGImageRef cgimg = CGBitmapContextCreateImage(ctx); UIImage *fixedImage = [UIImage imageWithCGImage:cgimg]; CGContextRelease(ctx); CGImageRelease(cgimg); return fixedImage; }
然后修改你的保存代码,先处理图片再保存:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage]; // 修正图片方向 UIImage *fixedImage = [self fixImageOrientation:originalImage]; UIImageWriteToSavedPhotosAlbum(fixedImage, nil, nil, nil); // 保存后显示正常 imageView.image = originalImage; // 依然用原图显示,避免重复处理 [self dismissModalViewControllerAnimated:YES]; // PHPhotoLibrary保存同样用fixedImage [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:fixedImage]; PHObjectPlaceholder *assetPlaceholder = changeRequest.placeholderForCreatedAsset; // 后续逻辑... } completionHandler:^(BOOL success, NSError * _Nullable error) { // 处理完成回调 }]; }
Feedback Assistant中的Bug情况
确实有不少开发者在Feedback Assistant中提交过类似Bug报告,主要集中在iOS 13到iOS 15的部分版本,问题描述多为PHAssetChangeRequest/UIImageWriteToSavedPhotosAlbum未正确处理UIImage的orientation元数据。你可以搜索关键词UIImage orientation save photos album或PHAssetChangeRequest rotation issue,能找到不少已提交的报告,其中部分被标记为「待修复」或「已在新版本iOS中解决」。如果你的App需要适配旧版本iOS,上面的手动修正方法依然是最稳妥的方案。
内容的提问来源于stack exchange,提问作者sebastian
相关产品推荐
相关产品推荐

