iOS 图片压缩

最近在解决Share Extension发送大图导致爆内存的问题,测试用27M的图片,用的是iPhone 7P,系统分配给Share Extension的内存应该有100M,一步步debug发现问题出在压缩的过程。

问题

在缩小图片的时候用了下面的代码:

1
2
3
4
5
6
7
UIGraphicsBeginImageContext(imgSize);
[self drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

运行到drawInRect的时候程序直接退出了,可见drawInRect是比较吃内存的。
于是在网上搜索关键字uiimage drawinrect memory warning,但是貌似都是关于memory not release的帖子,解决方法是添加autoreleasepool,
很显然无法解决爆内存的问题。

解决方法

后来同事推荐使用ImageIO来解决这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CGFloat maxPixelSize = 100;
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
(id) kCGImageSourceCreateThumbnailWithTransform : @YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id) kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize)
};
UIImage *result = nil;
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, options);
if (imageRef) {
result = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
CGImageRelease(imageRef);
}
if (sourceRef) {
CFRelease(sourceRef);
}
return result;

使用改代码对测试用的27M的图片进行压缩,内存在执行CGImageSourceCreateThumbnailAtIndex的时候只上升了20M。

如下是对一个9.2M的图片进行压缩的内存变化图

图中1是将图片读入内存导致的内存增加,在使用ImageIO进行压缩的过程中内存没有出现明显的变化,2是使用drawInRect进行压缩,可见内存飙升到了38.8。

参考:
Resizing High Resolution Images on iOS Without Memory Issues
UIImage vs. CIImage vs. CGImage