iOS学习——图片压缩到指定大小以内
一、图片压缩简述
首先,我们必须明确图片的压缩其实是两个概念:
- “压” 是指文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降。
- “缩” 是指文件的尺寸变小,也就是像素数减少,而长宽尺寸变小,文件体积同样会减小。
二、图片压缩的实现
2.1 “压”处理
对于“压”的功能,我们一般是使用系统提供的UIImageJPEGRepresentation或UIImagePNGRepresentation方法实现,如:
// return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format
UIKIT_EXTERN NSData *UIImagePNGRepresentation(UIImage *image); // return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)
UIKIT_EXTERN NSData *UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality); //UIImageJPEGRepresentation需要传两个参数,
//第一个参数是图片对象
//第二个参数是压的系数,其值范围为0~1
NSData *imgData=UIImageJPEGRepresentation(image, 0.5); //UIImagePNGRepresentation只需要传一个参数,就是图片对象
NSData *imgData = UIImagePNGRepresentation(image);
UIImagePNGRepresentation要比UIImageJPEGRepresentation(UIImage* image, 1.0)返回的图片数据量大很多。同样的一张照片, 使用UIImagePNGRepresentation(image)返回的数据量大小为199K,而UIImageJPEGRepresentation(image, 1.0)返回的数据量大小只为140K,比前者少了59K。
如果对图片的清晰度要求不是极高,建议使用UIImageJPEGRepresentation,可以大幅度降低图片数据量.其中UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality)提供了一个压缩比率的参数compressionQuality,但是实际体验确实compressionQuality并不能够按照设定好的数值,比例压缩。比如一张2.9M的图片(jpg格式),通过UIImageJPEGRepresentation方法设置不同压缩比进行压缩后的大小如下:
-- ::33.546342+ CJMobile[:] compression = 1.000000 image length = 7076.682617 kB
-- ::33.658606+ CJMobile[:] compression = 0.500000 image length = 1490.095703 kB
-- ::33.748077+ CJMobile[:] compression = 0.250000 image length = 671.213867 kB
-- ::33.834126+ CJMobile[:] compression = 0.125000 image length = 550.979492 kB
-- ::33.918830+ CJMobile[:] compression = 0.062500 image length = 532.168945 kB
-- ::34.004086+ CJMobile[:] compression = 0.031250 image length = 532.107422 kB
-- ::34.089819+ CJMobile[:] compression = 0.015625 image length = 532.107422 kB
通过上面的结果我们可以看到,compressionQuality压缩系数跟最后文件的大小并没有明显的关系,不同的图片呈现不同结果,而且最后压缩比减小但是得到的图片大小没有变化。本人对图片存储格式不是很了解,所以对出现这样的情况不是很了解,如果有对此比较了解的同学烦请赐教。但是图片颜色细节越单一,图片可压缩的比率会越高。
UIImagePNGRepresentation虽然可以让我们控制压缩质量比例,但是我们看到这个压缩比compressionQuality实际上很难确定一张图片是否能压缩到误差范围内,无法实现精确压缩。
2.2 “缩”处理
UIImagePNGRepresentation虽然可以让我们控制压缩质量比例,但是我们看到这个压缩比compressionQuality实际上很难确定一张图片是否能压缩到误差范围内,无法实现精确压缩。所以我们对图片只“压”而不缩,有时候是达不到我们的需求的。因此,必要的时候,我们需要适当地对图片“缩”一“缩“尺寸,就可以满足我们的需求。
通过 [sourceImage drawInRect:CGRectMake(, , targetWidth, targetHeight)] 可以进行图片“缩”的功能。示例如下:
- (UIImage*)compressImage:(UIImage*)sourceImage toTargetWidth:(CGFloat)targetWidth {
//获取原图片的大小尺寸
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
//根据目标图片的宽度计算目标图片的高度
CGFloat targetHeight = (targetWidth / width) * height;
//开启图片上下文
UIGraphicsBeginImageContext(CGSizeMake(targetWidth, targetHeight));
//绘制图片
[sourceImage drawInRect:CGRectMake(,, targetWidth, targetHeight)];
//从上下文中获取绘制好的图片
UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
//关闭图片上下文
UIGraphicsEndImageContext();
return newImage;
}
通过“缩”处理,我们可以将图片压缩到任何我们制定的大小尺寸内,但是这种处理,我们改变了原先图片的尺寸大小,无法保证图片的质量。
三、图片压缩到指定大小以内实现
当我们需要对图片的大小进行限制时,我们首先应该优先采取“压”处理,如果“压”处理达不到要求,那么我们在“压”处理的结果上继续进行“缩”处理,直到图片的大小达到我们的要求为止。
/*!
* @brief 使图片压缩后刚好小于指定大小
*
* @param image 当前要压缩的图 maxLength 压缩后的大小
*
* @return 图片对象
*/
//图片质量压缩到某一范围内,如果后面用到多,可以抽成分类或者工具类,这里压缩递减比二分的运行时间长,二分可以限制下限。
- (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength{
//首先判断原图大小是否在要求内,如果满足要求则不进行压缩,over
CGFloat compression = ;
NSData *data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength) return image;
//原图大小超过范围,先进行“压处理”,这里 压缩比 采用二分法进行处理,6次二分后的最小压缩比是0.015625,已经够小了
CGFloat max = ;
CGFloat min = ;
for (int i = ; i < ; ++i) {
compression = (max + min) / ;
data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength * 0.9) {
min = compression;
} else if (data.length > maxLength) {
max = compression;
} else {
break;
}
}
//判断“压处理”的结果是否符合要求,符合要求就over
UIImage *resultImage = [UIImage imageWithData:data];
if (data.length < maxLength) return resultImage; //缩处理,直接用大小的比例作为缩处理的比例进行处理,因为有取整处理,所以一般是需要两次处理
NSUInteger lastDataLength = ;
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)));
//通过图片上下文进行处理图片
UIGraphicsBeginImageContext(size);
[resultImage drawInRect:CGRectMake(, , size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//获取处理后图片的大小
data = UIImageJPEGRepresentation(resultImage, compression);
} return resultImage;
}
iOS学习——图片压缩到指定大小以内的更多相关文章
- iOS 图片按比例压缩,指定大小压缩
使用系统方法UIImageJPEGRepresentation(UIimage *image,CGFloat quality)进行图片质量压缩,暂且叫参数quality为压缩比吧,取值范围为0-1. ...
- [Android算法] bitmap 将图片压缩到指定的大小
Bitmap压缩到指定大小: private void imageZoom() {//图片允许最大空间 单位:KBdouble maxSize =400.00;//将bitmap放至数组中,意在bit ...
- 使用 opencv 将图片压缩到指定文件尺寸
前言 图片压缩应用很广泛,如生成缩略图等.前期我在进行图片处理的过程中碰到了一个问题,就是如何将图片压缩到指定尺寸,此处尺寸指的是生成图片文件的大小. 我使用 opencv 进行图片处理,于是想着直接 ...
- 微信小程序 上传图片并等比列压缩到指定大小
微信小程序官方API中 wx.chooseImage() 是可以进行图片压缩的,可惜的是不能压缩到指定大小. 实际开发中需求可能是压缩到指定大小: 原生js可以使用canvas来压缩,但由于微信小程 ...
- C# 图片超过指定大小将压缩到指定大小不失真
using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Drawing2D;us ...
- GIF图片裁剪出指定大小的GIF图片
前言 最近在博客后台上传图片的时候,突然发现上传gif图片的时候裁剪图片有问题.既没法裁剪gif指定区域的图片,又没法裁剪指定区域生成一个新的指定大小的gif图.本来想直接去找个裁剪的库直接放上去的, ...
- vue+element-ui upload图片上传前大小超过4m,自动压缩到指定大小,长宽
最近项目需要实现一个需求,用户上传图片时,图片大小超过4M,长宽超过2000,需要压缩到400k,2000宽高.在git上找到一个不错的方法,把实现方法总结一下: 安装image-conversion ...
- ios 视频/图片压缩
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- Delphi将图片缩放成指定大小
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
随机推荐
- mysql 服务器负载过高的解决分析之路
最近我们有台 mysql 服务器一直报负载过高,不停的收到阿里云的报警短信,让我很抓狂,登陆上服务器,看下一下,慢查询日志 发现有60多万的慢查询日志,一看这个就知道是搜索带来的,一直想把搜索的服务给 ...
- James Munkres Topology: Theorem 20.3 and metric equivalence
Proof of Theorem 20.3 Theorem 20.3 The topologies on \(\mathbb{R}^n\) induced by the euclidean metri ...
- SpringBoot简单入门
一.创建SpringBoot项目 1.创建maven项目,pom引入springboot父级启动器(starter)依赖: <?xml version="1.0" encod ...
- 10分钟了解JSON Web令牌(JWT)
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.虫虫今天给大家介绍JWT的原理和用法. 1.跨域身份验证 Internet服务无法与用户身份验证分开.一般过程如下. 1.用户 ...
- TortoiseSVN--clearup清理失败解决办法
工作中经常遇到update.commit 失败导致冲突问题,需要用clear up来清除问题,个别异常情况导致clear up失败,进入死循环!可以使用sqlite3.exe清理一下wc.db文件的队 ...
- [pyMongo]insert_many的Bulkwrite实现机制
在SQL中,insert many的操作可能会出现插入数据量过大的问题. 印象中MySQL Driver对insert语句的buffer有一个大小限制.超过这个限制的数据可能会被丢弃? -- > ...
- 如何删除github上的某个文件夹
在github上只能删除仓库,却无法删除文件夹或文件, 所以只能通过命令来解决 首先进入你的master文件夹下, Git Bash Here ,打开命令窗口 $ git –help 帮助命令 $ g ...
- Python操作Excel, 开发和调用接口,发送邮件
笔记: 上周回顾: 模块: 导入模块的顺序 lyl.py # def hhh(): pass name = 'lyl' a.py import lyl import sys from lyl impo ...
- vijos搭建踩坑
nodejs我用的8.x版本,可以工作. 和制作组交谈之后他们说最好榨汁机和主机不要在同一系统下. vj4/vj4/handler/base.py的第343行 从 super(Connection, ...
- python学习:输入设置
输入设置 输入用户名和密码 代码: _user = "alex"_password = "abc123" username = input("User ...