两种图片压缩方法

两种压缩图片的方法:压缩图片质量(Quality),压缩图片尺寸(Size)。

压缩图片质量

NSData *data = UIImageJPEGRepresentation(image, compression);
UIImage *resultImage = [UIImage imageWithData:data];

通过 UIImage 和 NSData 的相互转化,减小 JPEG 图片的质量来压缩图片。UIImageJPEGRepresentation:: 第二个参数 compression 取值 0.0~1.0,值越小表示图片质量越低,图片文件自然越小。

压缩图片尺寸

UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

给定所需的图片尺寸 size,resultImage 即为原图 image 绘制为 size 大小的图片。

压缩图片使图片文件小于指定大小

如果对图片清晰度要求不高,要求图片的上传、下载速度快的话,上传图片前需要压缩图片。压缩到什么程度要看具体情况,但一般会设定一个图片文件最大值,例如 100 KB。可以用上诉两种方法来压缩图片。假设图片转化来的 NSData 对象为 data,通过data.length即可得到图片的字节大小。

压缩图片质量

比较容易想到的方法是,通过循环来逐渐减小图片质量,直到图片稍小于指定大小(maxLength)。

+ (UIImage *)compressImageQuality:(UIImage *)image toByte:(NSInteger)maxLength {CGFloat compression = 1;NSData *data = UIImageJPEGRepresentation(image, compression);while (data.length > maxLength && compression > 0) {compression -= 0.02;data = UIImageJPEGRepresentation(image, compression); // When compression less than a value, this code dose not work}UIImage *resultImage = [UIImage imageWithData:data];return resultImage;
}

这样循环次数多,效率低,耗时长。

可以通过二分法来优化。

+ (UIImage *)compressImageQuality:(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;for (int i = 0; i < 6; ++i) {compression = (max + min) / 2;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;
}
static func compressImageQuality(_ image: UIImage, toByte maxLength: Int) -> UIImage {var compression: CGFloat = 1guard var data = UIImageJPEGRepresentation(image, compression),data.count > maxLength else { return image }var max: CGFloat = 1var min: CGFloat = 0for _ in 0..<6 {compression = (max + min) / 2data = UIImageJPEGRepresentation(image, compression)!if CGFloat(data.count) < CGFloat(maxLength) * 0.9 {min = compression} else if data.count > maxLength {max = compression} else {break}}return UIImage(data: data)!
}

当图片大小小于 maxLength,大于 maxLength * 0.9 时,不再继续压缩。最多压缩 6 次,1/(2^6) = 0.015625 < 0.02,也能达到每次循环 compression 减小 0.02 的效果。这样的压缩次数比循环减小 compression 少,耗时短。需要注意的是,当图片质量低于一定程度时,继续压缩没有效果。也就是说,compression 继续减小,data 也不再继续减小。压缩图片质量的优点在于,尽可能保留图片清晰度,图片不会明显模糊;缺点在于,不能保证图片压缩后小于指定大小。

压缩图片尺寸

与之前类似,比较容易想到的方法是,通过循环逐渐减小图片尺寸,直到图片稍小于指定大小(maxLength)。具体代码省略。同样的问题是循环次数多,效率低,耗时长。可以用二分法来提高效率,具体代码省略。这里介绍另外一种方法,比二分法更好,压缩次数少,而且可以使图片压缩后刚好小于指定大小(不只是 < maxLength, > maxLength * 0.9)。

+ (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength {UIImage *resultImage = image;NSData *data = UIImageJPEGRepresentation(resultImage, 1);NSUInteger lastDataLength = 0;while (data.length > maxLength && data.length != lastDataLength) {lastDataLength = data.length;CGFloat ratio = (CGFloat)maxLength / data.length;CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),(NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blankUIGraphicsBeginImageContext(size);// Use image to draw (drawInRect:), image is larger but more compression time// Use result image to draw, image is smaller but less compression time[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];resultImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();data = UIImageJPEGRepresentation(resultImage, 1);}return resultImage;
}
static func compressImageSize(_ image: UIImage, toByte maxLength: Int) -> UIImage {guard var data = UIImageJPEGRepresentation(image, 1) else { return image }var resultImage: UIImage = imagevar lastDataLength: Int = 0while data.count > maxLength, data.count != lastDataLength {lastDataLength = data.countlet ratio: CGFloat = CGFloat(maxLength) / CGFloat(data.count)let size: CGSize = CGSize(width: Int(resultImage.size.width * sqrt(ratio)),height: Int(resultImage.size.height * sqrt(ratio)))UIGraphicsBeginImageContext(size)resultImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))resultImage = UIGraphicsGetImageFromCurrentImageContext()!UIGraphicsEndImageContext()data = UIImageJPEGRepresentation(resultImage, 1)!}return resultImage
}

[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];是用新图 resultImage 绘制,也可以用原图 image 来绘制。用原图绘制,压缩后图片更接近指定大小,但是压缩次数较多,耗时较长。一张大小为 6064 KB 的图片,压缩图片尺寸,原图绘制与新图绘制结果如下

指定大小(KB) 原图绘制压缩后大小(KB) 原图绘制压缩次数 新图绘制压缩后大小(KB) 新图绘制压缩次数
500 498 6 498 3
300 299 4 296 3
100 99 5 98 3
50 49 6 48 3

两种绘制方法压缩后大小很接近,与指定大小也很接近,但原图绘制压缩次数可达到新图绘制压缩次数的两倍。建议使用新图绘制,减少压缩次数。压缩后图片明显比压缩质量模糊。

需要注意的是绘制尺寸的代码CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)), (NSUInteger)(resultImage.size.height * sqrtf(ratio)));每次绘制的尺寸 size,要把宽 width 和 高 height 转换为整数,防止绘制出的图片有白边

压缩图片尺寸可以使图片小于指定大小,但会使图片明显模糊(比压缩图片质量模糊)。

两种图片压缩方法结合

如果要保证图片清晰度,建议选择压缩图片质量。如果要使图片一定小于指定大小,压缩图片尺寸可以满足。对于后一种需求,还可以先压缩图片质量,如果已经小于指定大小,就可得到清晰的图片,否则再压缩图片尺寸。

+ (UIImage *)compressImage:(UIImage *)image toByte:(NSUInteger)maxLength {// Compress by qualityCGFloat compression = 1;NSData *data = UIImageJPEGRepresentation(image, compression);if (data.length < maxLength) return image;CGFloat max = 1;CGFloat min = 0;for (int i = 0; i < 6; ++i) {compression = (max + min) / 2;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];if (data.length < maxLength) return resultImage;// Compress by sizeNSUInteger lastDataLength = 0;while (data.length > maxLength && data.length != lastDataLength) {lastDataLength = data.length;CGFloat ratio = (CGFloat)maxLength / data.length;CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),(NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blankUIGraphicsBeginImageContext(size);[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];resultImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();data = UIImageJPEGRepresentation(resultImage, compression);}return resultImage;
}
static func compressImage(_ image: UIImage, toByte maxLength: Int) -> UIImage {var compression: CGFloat = 1guard var data = UIImageJPEGRepresentation(image, compression),data.count > maxLength else { return image }// Compress by sizevar max: CGFloat = 1var min: CGFloat = 0for _ in 0..<6 {compression = (max + min) / 2data = UIImageJPEGRepresentation(image, compression)!if CGFloat(data.count) < CGFloat(maxLength) * 0.9 {min = compression} else if data.count > maxLength {max = compression} else {break}}var resultImage: UIImage = UIImage(data: data)!if data.count < maxLength { return resultImage }// Compress by sizevar lastDataLength: Int = 0while data.count > maxLength, data.count != lastDataLength {lastDataLength = data.countlet ratio: CGFloat = CGFloat(maxLength) / CGFloat(data.count)let size: CGSize = CGSize(width: Int(resultImage.size.width * sqrt(ratio)),height: Int(resultImage.size.height * sqrt(ratio)))UIGraphicsBeginImageContext(size)resultImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))resultImage = UIGraphicsGetImageFromCurrentImageContext()!UIGraphicsEndImageContext()data = UIImageJPEGRepresentation(resultImage, compression)!}return resultImage
}

转载于:https://my.oschina.net/d0ou/blog/1068628

iOS 图片压缩方法相关推荐

  1. Android应用开发中三种常见的图片压缩方法

    Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 一.质量压缩法private Bitmap comp ...

  2. 怎么压缩图片大小,图片压缩方法

    怎么压缩图片大小?工作中如果遇到一些体积较大的图片,尤其一些清晰度很高的图片,可能一张小尺寸的图片就有2-3M的大小,这个我们的使用打开造成很多的麻烦,例如因为超过限制大小而不能上传,打开的时候很大, ...

  3. 图片压缩怎么做?这几种图片压缩方法很方便

    怎么把图片给压缩一下呢?图片的内存如果太大,那我们不管是在发送还是保存都会不方便.发送时会非常缓慢,保存时也占据很多内存,对本来空间就不太够的电脑或手机来说是一个致命问题.缓解这方面问题我们可以将图片 ...

  4. Android图片压缩方法总结

    本文总结Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 第一:质量压缩方法: ? 1 2 3 4 5 ...

  5. Excel 表格图片压缩方法

    我们在工作,学习当中少不了用Excel 来制作各式各样的表格,其中有很多使用技巧,来提高我们的工作效率.下面介绍在EXCEL中压缩图片的方法: 一.如果你在EXCEL工作表中插入比较大的图片,保存为文 ...

  6. 图片太大怎么改小kb?简单的图片压缩方法分享

    平时当我们在朋友圈分享一些有趣的照片或者使用图片素材进行上传的时候,经常遇到图片大小kb超出平台限制的情况,这时就无法正常上传了,遇到这种情况我们就需要想办法降低图片大小kb,那么有什么办法能够压缩图 ...

  7. 图片怎么压缩到200K以内,这3个图片压缩方法,简单有效

    你没有遇到过上传图片到网站的时候,图片太大不能上传的情况?还有,许多报名照片要求小于200K,可是照片超过这个大小,应该如何压缩呢?下面我给大家带来3个图片压缩的方法,既能快速压缩图片大小,又保存画质 ...

  8. 怎样改变照片大小?免费在线图片压缩方法

    平时我们经常会遇到一些线上申请资料需要上传证件照,一般我们会通过一些手机软件制作并下载适合规格的照片,但除了尺寸要求外,还会限制图片大小.如何才能既不改变图片原来的尺寸仅仅将照片压缩到100KB以下呢 ...

  9. Android不错的图片压缩方法,圆我大厂梦

    /** 质量压缩方法 @param image @return */ public static Bitmap compressImage(Bitmap image) { ByteArrayOutpu ...

最新文章

  1. 第二十章:异步和文件I/O.(十三)
  2. 数组--将两个有序数组a,b合并成新的有序数组c
  3. leetcode每日一题系列——787. K 站中转内最便宜的航班
  4. Spring Cloud Config Server迁移节点或容器化带来的问题
  5. 【MM模块】Procurement for Stock Material 库存型物料采购相关
  6. markdown语法中的空格_Markdown语法简明教程
  7. JAVA socket编程 Datagram套接字 UDP协议(转)
  8. arm9 安装java_QT5.7 AM1808 ARM9的交叉编译
  9. 载体构建实例解析——构建 SETD3-pEGFP-N1(Snapgene 设计引物)
  10. 苹果手机长截屏_iPhone终于自带长截屏了?苹果手机这些截图方式,你用过几种?...
  11. 事业单位计算机技术岗工资,事业单位待遇,是管理岗好还是技术岗好?
  12. ABAQUS内核及GUI方法的代理接口
  13. autocad.net 画多段线_AutoCAD2016快速入门:绘制多段线
  14. CAD组合成块,CAD合并成块,CAD炸开后再合并,CAD中炸开的图块合并在一起
  15. CNN之Xception Keras实现模型训练
  16. 用户活跃、留存、流失,终于讲清楚了!
  17. matlab(1):画图像修改曲线形状
  18. ubuntu 下载 wps 及 字体缺失问题
  19. MATLAB-修改图片的背景颜色
  20. Kibana 的用途是什么?

热门文章

  1. AcWing 2005. 马蹄铁
  2. 数据库面试题:对称加密和非对称加密的区别
  3. PyQt5安装及Pycharm配置详细教程(win10)
  4. App换量攻略|实操技巧+换量神器,app换量推广
  5. 无限制端口服务器,怎样限制服务器的端口
  6. 价目表报价单微信小程序
  7. PyQt5系列-网红辞职小程序-[1]
  8. python培训班 达内
  9. php文本首行缩进,html设置页面文本首行缩进
  10. Python3 实现大众点评网酒店信息和酒店评论的网页爬取