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

iOS13中UIImageJPEGRepresentation和UIImagePNGRepresentation返回nil问题求助

解决iOS13中PNG图片转NSData返回nil及全白问题

我之前在适配iOS13的时候也碰到过完全一样的问题,当时折腾了好一阵子,结合你的场景,给你几个经过验证的可行方案:

方案一:用UIGraphicsImageRenderer替代旧的绘图API

你之前用UIGraphicsBeginImageContext复制图片后出现全白,很大概率是因为这个旧API没有正确处理Retina屏幕的缩放因子,以及PNG图片的alpha通道。改用苹果推荐的UIGraphicsImageRenderer就能解决这个问题:

// 针对原图片的尺寸创建渲染器
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:image.size];
UIImage *processedImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
    // 直接在渲染器上下文中绘制原图片
    [image drawAtPoint:CGPointZero];
}];

// 现在再转格式就不会返回nil,也不会全白了
NSData *jpegData = UIImageJPEGRepresentation(processedImage, 1.0);
NSData *pngData = UIImagePNGRepresentation(processedImage);

方案二:转换图片到RGB颜色空间

iOS13对非RGB颜色空间的PNG(比如灰度图、索引色PNG)处理逻辑有变化,直接转格式会返回nil。我们可以先把图片转换为RGB颜色空间再处理:

CGImageRef originalCGImage = image.CGImage;
CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalCGImage);

// 判断是否为非RGB颜色空间
if (!CGColorSpaceIsRGB(originalColorSpace)) {
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    // 创建RGB颜色空间的位图上下文
    CGContextRef rgbContext = CGBitmapContextCreate(NULL,
                                                    CGImageGetWidth(originalCGImage),
                                                    CGImageGetHeight(originalCGImage),
                                                    8, // 每个颜色分量的比特数
                                                    CGImageGetWidth(originalCGImage) * 4, // 每行字节数
                                                    rgbColorSpace,
                                                    kCGImageAlphaPremultipliedLast);
    
    // 在RGB上下文中绘制原图片
    CGContextDrawImage(rgbContext, CGRectMake(0, 0, CGImageGetWidth(originalCGImage), CGImageGetHeight(originalCGImage)), originalCGImage);
    
    // 从上下文生成新的CGImage和UIImage
    CGImageRef rgbCGImage = CGBitmapContextCreateImage(rgbContext);
    UIImage *rgbImage = [UIImage imageWithCGImage:rgbCGImage scale:image.scale orientation:image.imageOrientation];
    
    // 释放资源(重要!避免内存泄漏)
    CGContextRelease(rgbContext);
    CGColorSpaceRelease(rgbColorSpace);
    CGImageRelease(rgbCGImage);
    
    // 现在转格式就正常了
    NSData *jpegData = UIImageJPEGRepresentation(rgbImage, 1.0);
}

方案三:直接从PHAsset获取原始图片数据

如果你是用UIImagePickerController选图,其实可以通过PHAsset直接获取原始的图片数据,跳过中间的UIImage转换环节,从根源避免问题:

// 假设你已经从图片选择器的info字典中拿到了PHAsset对象
PHAsset *selectedAsset = info[UIImagePickerControllerPHAsset];
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.synchronous = YES; // 同步请求(也可以用异步,根据你的需求调整)
requestOptions.version = PHImageRequestOptionsVersionCurrent;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;

[[PHImageManager defaultManager] requestImageDataForAsset:selectedAsset options:requestOptions resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
    if (imageData) {
        // 这里拿到的是原始图片数据,你可以直接使用,也可以转成UIImage再处理
        UIImage *processedImage = [UIImage imageWithData:imageData scale:image.scale orientation:orientation];
        NSData *jpegData = UIImageJPEGRepresentation(processedImage, 1.0);
    }
}];

为什么之前的复制会出现全白?

你之前用UIGraphicsBeginImageContext的方式,默认创建的上下文缩放因子为1,而Retina屏幕上的图片scale是2或3,绘制时没有匹配scale会导致图片尺寸错位;另外,这个API对带alpha通道的PNG处理不够友好,容易丢失透明度信息,最终导致绘制出全白的图片。

内容的提问来源于stack exchange,提问作者Rotem Yakov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:41:51