iOS图片压缩
一般图片压缩的需求
- 压缩到指定宽高(例如:微信图片压缩,宽或者高不超过 1280 )
- 压缩到指定大小(例如:微信小程序分享,图片不超过 32kb)
常规的图片压缩方法
一、质量压缩
UIImageJPEGRepresentation(image, compression);
这是苹果爸爸提供的质量压缩API:第一个参数是 目标image,第二个参数 compression 取值 0.0 ~ 1.0,理论上值越小表示图片质量越低,图片文件自然越小。
但这里有个注意点,并不是 compression 取 0,就是0b大小,取 1 就是原图:
a.首先:图片的大小是根据(图片的宽 * 图片的高 * 每一个色彩的深度)来获取的,
图片只会按照你的手机像素的分辨率 [UIScreen mainScreen].scale 来读取值。
b.其次:对于大图片来说,即使你的 compression 选的很小很小,
比如:0.0000000(n个0)001,无论多小都没有用,因为达到
一定阈值之后,就再也压不下去了,但是得到的结果还是很大,
DEMO中例子:一张13M左右的图片,处理后极限大小为551kb左右。
循环压缩的方法:
+ (UIImage *)compressImageQualityNormal:(UIImage *)image toByte:(NSInteger)maxLength
{
CGFloat compression = 1;
NSUInteger count = 0;
NSData *data = UIImageJPEGRepresentation(image, compression);
while (data.length > maxLength && compression > 0) {
compression -= 0.01;
count++;
// 当压缩到某个阈值的时候,这句代码就没有效果了
data = UIImageJPEGRepresentation(image, compression);
NSLog(@"%@", [NSString stringWithFormat:@"压缩次数:%zd,压缩比例:%f,压缩后的图片大小:%f kb", count, compression, data.length / 1000.0]);
}
UIImage *resultImage = [UIImage imageWithData:data];
return resultImage;
}
以下是压缩数据:
图片的原始大小:13362 kb
| 压缩次数 | 压缩比例 | 压缩后的图片大小 |
|---|---|---|
| 1 | 0.990000 | 5984.280000 kb |
| 2 | 0.980000 | 5818.233000 kb |
| 3 | 0.970000 | 5663.514000 kb |
| … | … | … |
| 37 | 0.630000 | 2726.441000 kb |
| 38 | 0.620000 | 2659.856000 kb |
| 39 | 0.610000 | 2594.750000 kb |
| … | … | … |
| 67 | 0.330000 | 925.446000 kb |
| 68 | 0.320000 | 886.675000 kb |
| 69 | 0.310000 | 867.404000 kb |
| … | … | … |
| 90 | 0.100000 | 562.138000 kb |
| 91 | 0.090000 | 561.355000 kb |
| 92 | 0.080000 | 553.827000 kb |
| 93 | 0.070000 | 553.236000 kb |
| 94 | 0.060000 | 551.402000 kb |
| 95 | 0.050000 | 551.402000 kb |
| 96 | 0.040000 | 551.402000 kb |
| 97 | 0.030000 | 551.402000 kb |
| 98 | 0.020000 | 551.402000 kb |
| 99 | 0.010000 | 551.402000 kb |
| 100 | -0.000000 | 551.402000 kb |
换句话来说,如果要实现压缩到指定大小(比如 32k),如果是小图倒是不会有什么问题,多试几次应该能得到想要的结果,如果大图(比如 13M)只用压缩质量的方式,是办不到的,达到一定阈值之后(压缩比例:小于0.060000),就再也压不下去了。
当然,这个方法是有问题的,总共压缩了 100 次,循环次数过多,效率低,耗时长。
如果你得到的图片压缩的需求,是保证尺寸不变的情况下,尽可能压到最小,自然只需要循环压缩就好,不过有更好的实现方式,那就是 二分法。
+ (UIImage *)compressImageQualityDichotomy:(UIImage *)image toByte:(NSInteger)maxLength
{
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength) return image;
CGFloat max = 1;
CGFloat min = 0;
// 二分最大10次,区间范围精度最大可达0.00097657;第6次,精度可达0.015625,10次,0.000977
for (int i = 0; i < 10; ++i) {
compression = (max + min) / 2;
NSLog(@"%@", [NSString stringWithFormat:@"压缩精度:%f", compression]);
data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength * 0.9) {
min = compression;
} else if (data.length > maxLength) {
max = compression;
} else {
break;
}
}
UIImage *resultImage = [UIImage imageWithData:data];
return resultImage;
}
二分最大10次即可,既可以达到压缩到阈值的效果,又能节约性能,区间范围精度最大可达0.00097657;第6次,精度可达0.015625,10次,0.000977
使用二分法进行处理,比for循环依次递减**“高效”很多,而且也合理**很多,第10次就达到了单纯的for循环的99次的效果。
| 次数 | 压缩比例 |
|---|---|
| 1 | 0.500000 |
| 2 |

本文探讨了iOS中图片压缩的两种方法:质量压缩和尺寸压缩。质量压缩利用苹果API,循环或二分法压缩,但对大图效果有限。尺寸压缩包括使用UIGraphics和ImageIO,后者在处理大图时更节省内存。二分法在压缩性能上优于循环压缩。文章总结了不同场景下选择合适压缩策略的建议。
最低0.47元/天 解锁文章
1222

被折叠的 条评论
为什么被折叠?



