iOS学习——图片压缩到指定大小以内

推荐阅读:iOS开发——BAT面试题合集(持续更新中)

一、图片压缩简述

在我们开发过程中,有可能会遇到拍照、或者从相册中选择图片,要么单选或者多选,然后上传图片到服务器,一般情况下一张图片可能3-4M,如果类似微信朋友圈上传9张图片大约是 35M左右,如果我们上传 35M左右的图片到服务器,可想而知后台的压力有多大,最主要的还是特别耗时,如果是在网速比较慢,那么用户上传图片可能需要4-5分钟,那么用户就会受不了,可能会退出应用。

所有 在开发过程中,考虑到手机性能、网络性能等因素的影响,更重要的是后台服务器的内存、网络等性能的限制,我们再通过网络发送图片等信息时不能发送超过一定大小的图片,如果超过了指定大小,我们需要进行压缩后发送。

首先,我们必须明确图片的压缩其实是两个概念:

“ 压 ” 是指文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降。
“ 缩 ” 是指文件的尺寸变小,也就是像素数减少,而长宽尺寸变小,文件体积同样会减小。
二、图片压缩的实现
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方法设置不同压缩比进行压缩后的大小如下:

2019-03-13 13:54:33.546342+0800 CJMobile[52591:15764262] compression = 1.000000 image length = 7076.682617 kB
2019-03-13 13:54:33.658606+0800 CJMobile[52591:15764262] compression = 0.500000 image length = 1490.095703 kB
2019-03-13 13:54:33.748077+0800 CJMobile[52591:15764262] compression = 0.250000 image length = 671.213867 kB
2019-03-13 13:54:33.834126+0800 CJMobile[52591:15764262] compression = 0.125000 image length = 550.979492 kB
2019-03-13 13:54:33.918830+0800 CJMobile[52591:15764262] compression = 0.062500 image length = 532.168945 kB
2019-03-13 13:54:34.004086+0800 CJMobile[52591:15764262] compression = 0.031250 image length = 532.107422 kB
2019-03-13 13:54:34.089819+0800 CJMobile[52591:15764262] compression = 0.015625 image length = 532.107422 kB
通过上面的结果我们可以看到,compressionQuality压缩系数跟最后文件的大小并没有明显的关系,不同的图片呈现不同结果,而且最后压缩比减小但是得到的图片大小没有变化。 本人对图片存储格式不是很了解,所以对出现这样的情况不是很了解,如果有对此比较了解的同学烦请赐教。但是图片颜色细节越单一,图片可压缩的比率会越高。

UIImagePNGRepresentation虽然可以让我们控制压缩质量比例,但是我们看到这个压缩比compressionQuality实际上很难确定一张图片是否能压缩到误差范围内,无法实现精确压缩 。

2.2 “缩”处理
UIImagePNGRepresentation虽然可以让我们控制压缩质量比例,但是我们看到这个压缩比compressionQuality实际上很难确定一张图片是否能压缩到误差范围内,无法实现精确压缩。所以我们对图片只“压”而不缩,有时候是达不到我们的需求的。因此,必要的时候,我们需要适当地对图片“缩”一“缩“尺寸,就可以满足我们的需求。

通过 [sourceImage drawInRect:CGRectMake( 0 , 0 , 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(0,0, targetWidth, targetHeight)];
    //从上下文中获取绘制好的图片
    UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭图片上下文
    UIGraphicsEndImageContext();

    return newImage;
    }
    通过“缩”处理,我们可以将图片压缩到任何我们制定的大小尺寸内,但是这种处理,我们改变了原先图片的尺寸大小,无法保证图片的质量 。

三、图片压缩到指定大小以内实现
当我们需要对图片的大小进行限制时,我们首先应该优先采取“压”处理,如果“压”处理达不到要求,那么我们在“压”处理的结果上继续进行“缩”处理,直到图片的大小达到我们的要求为止。

/*!

  • @brief 使图片压缩后刚好小于指定大小
  • @param image 当前要压缩的图 maxLength 压缩后的大小
  • @return 图片对象
    */
    //图片质量压缩到某一范围内,如果后面用到多,可以抽成分类或者工具类,这里压缩递减比二分的运行时间长,二分可以限制下限。
  • (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength{
    //首先判断原图大小是否在要求内,如果满足要求则不进行压缩,over
    CGFloat compression = 1;
    NSData *data = UIImageJPEGRepresentation(image, compression);
    if (data.length < maxLength) return image;
    //原图大小超过范围,先进行“压处理”,这里 压缩比 采用二分法进行处理,6次二分后的最小压缩比是0.015625,已经够小了
    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;
    }
    }
    //判断“压处理”的结果是否符合要求,符合要求就over
    UIImage *resultImage = [UIImage imageWithData:data];
    if (data.length < maxLength) return resultImage;

    //缩处理,直接用大小的比例作为缩处理的比例进行处理,因为有取整处理,所以一般是需要两次处理
    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)));
    //通过图片上下文进行处理图片
    UIGraphicsBeginImageContext(size);
    [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
    resultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //获取处理后图片的大小
    data = UIImageJPEGRepresentation(resultImage, compression);
    }

    return resultImage;
    }

喜欢的话可以点个赞+1:或关注多多支持哦 小编会经常给小伙伴们更新关于IOS当下热点。

另外小编给大家推荐一个iOS技术交流群:638302184!群内提供数据结构与算法、底层进阶、swift、逆向、整合面试题等免费资料
附上一份收集的各大厂面试题(附答案) ! 群文件直接获取

各大厂面试题

文章来源网络 如有侵权请联系小编删除

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269