iOS17中CGImageSourceCreateThumbnailAtIndex旋转功能失效求助
iOS 17 下 CGImageSourceCreateThumbnailAtIndex 旋转失效的解决办法
问题背景
通过 CGImageSourceCreateThumbnailAtIndex 生成缩略图时,在 options 中指定 kCGImagePropertyOrientation 控制旋转的逻辑,在 iOS 17 上完全失效——无论设置 kCGImagePropertyOrientationUp、Left、Down 还是 Right,返回的图片方向均无变化。但该逻辑在 iOS 16 及以下系统、iPadOS 17 中均可正常运行。
问题根源
iOS 17 对 CGImageSourceCreateThumbnailAtIndex 的参数处理逻辑做了变更:kCGImagePropertyOrientation 现在仅用于读取图片元数据中的原始方向,不再支持通过该参数强制指定旋转角度。这个调整是苹果统一图片方向处理逻辑的一部分,目前仅在 iOS 17 生效,iPadOS 17 暂未跟进该变更。
修复方案
方案1:生成缩略图后手动旋转
先生成基础缩略图,再通过 UIImage 的 orientation 属性应用旋转:
CGImageSourceRef imageSource = CGImageSourceCreateWithData(capturedImage, nil); CFDictionaryRef options = (__bridge CFDictionaryRef) @{ (id)kCGImageSourceCreateThumbnailWithTransform: @YES, (id)kCGImageSourceCreateThumbnailFromImageAlways : @YES, (id)kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize) }; CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options); CFRelease(imageSource); // 手动应用旋转 UIImage *rotatedImage = [[UIImage alloc] initWithCGImage:thumbnail scale:1.0 orientation:rotationAngle]; CGImageRef finalThumbnail = rotatedImage.CGImage; CFRetain(finalThumbnail); // 按需管理内存,避免泄漏 CFRelease(thumbnail); return finalThumbnail;
方案2:用 CIImage 统一处理缩放与旋转
通过 CIImage 管道同时完成缩放和旋转,兼容性更强:
CIImage *ciImage = [CIImage imageWithData:capturedImage]; CGFloat scaleFactor = MIN(maxPixelSize / ciImage.extent.size.width, maxPixelSize / ciImage.extent.size.height); // 根据目标方向构建变换矩阵 CGAffineTransform transform = CGAffineTransformIdentity; switch (rotationAngle) { case kCGImagePropertyOrientationLeft: transform = CGAffineTransformRotate(transform, M_PI_2); transform = CGAffineTransformTranslate(transform, 0, -ciImage.extent.size.width); break; case kCGImagePropertyOrientationDown: transform = CGAffineTransformRotate(transform, M_PI); transform = CGAffineTransformTranslate(transform, -ciImage.extent.size.width, -ciImage.extent.size.height); break; case kCGImagePropertyOrientationRight: transform = CGAffineTransformRotate(transform, -M_PI_2); transform = CGAffineTransformTranslate(transform, -ciImage.extent.size.height, 0); break; default: break; } // 应用旋转和缩放 CIImage *transformedImage = [ciImage imageByApplyingTransform:transform]; transformedImage = [transformedImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleFactor, scaleFactor)]; // 转换为 CGImage CIContext *context = [CIContext contextWithOptions:nil]; // 建议全局复用 CIContext 提升性能 CGImageRef finalThumbnail = [context createCGImage:transformedImage fromRect:transformedImage.extent]; return finalThumbnail;
兼容建议
如果需要同时兼容新旧系统,可以通过系统版本判断分支处理:
if (@available(iOS 17.0, *)) { // 使用上述修复方案 } else { // 保留原有逻辑 CGImageSourceRef imageSource = CGImageSourceCreateWithData(capturedImage, nil); CFDictionaryRef options = (__bridge CFDictionaryRef) @{ (id)kCGImageSourceCreateThumbnailWithTransform: @YES, (id)kCGImageSourceCreateThumbnailFromImageAlways : @YES, (id)kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize), (id)kCGImagePropertyOrientation: @(rotationAngle) }; CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options); CFRelease(imageSource); return thumbnail; }
内容的提问来源于stack exchange,提问作者Tedxxxx
相关产品推荐
相关产品推荐

