You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:37:12