
用来提供相册的清理相似、清理截屏、压缩三个功能。
额外需要引入的框架:
Photos 引用了系统的 AssetsLibrary 框架,需要额外导入,否则会报错:
引入方式:
作用是无需创建实例,通过类方法直接调用。
在这个方法中加载的包括相似图、截屏图以及可瘦身的,所以是公共部分。
第一步: 加载照片之前首先要清除旧数据。
第二步: 判断相册授权状态。如果相册授权状态为没决定,则开启权限提示,在 infoplist 中添加上 Privacy - Photo Library Usage Description ,提示语句可为:获取相册权限。
如果相册授权状态为拒绝,则d出提示框,点击前往设置则跳转到设置APP开启权限。
第三步: 如果已经授权则直接获取相册中的数据。
第四步: requestImageWithIndex: 方法通过索引位置来获取 assetArray 中对应的。这个方法在 index+1 后不断递归调用自己,直到遍历完整个 assetArray 。传入缩略图和原图后,即进入了本文章的关键部分,即的处理流程了。
第五步: 的处理方法 dealImageWithIndex: 对传入的缩略图和原图进行三步处理,分别判断其是否为相似、截屏、可以瘦身的,如果是则将其加入到对应数组中保存作为数据源。处理完一张后将 index+1 ,再调用 requestImageWithIndex: 处理下一张,这是个递归过程,直到全部处理完成。
因为资源数组 assetArray 是按照创建时间排序的,所以可以通过和上一个的创建时间相比较来对按照是否为同一天创建的标准来分组显示。如果是同一天创建的,则将其分为一组。是否为同一天的比较方法如下:
第六步: 加载完成,计算相似、截屏、可瘦身的的数量和可节省内存的大小,最后将各类可节省内存的大小加起来得到总的可节省内存的大小。
其中获取数量及可以节省的内存空间大小的 getInfoWithDataArray: 方法的实现如下:
在 ClearPhotoManager 中定义:
当我们在相册新增加了一张的时候,控制台输出如下:
在 ClearPhotoViewController 中使用:页面显示前或者相册发生变动了则更新数据源
在 SimilarPhotoAndScreenShotsViewController 中使用:删除后通知更新相册和数据源
在 ThinPhotoViewController 中使用:压缩后通知更新相册和数据源
删除一张后的内存变化:
注意:这里进行了个小实验,可以看到即使照片相同,但是如果创建日期不同的话,APP也对它进行了单独分组,因为我们是按照日期的标准来划分组的。实际使用过程中,这种情况很少,因为会产生相似的原因大都是复制和连拍,而复制的、连拍的日期都是相同的。
属性的懒加载方法实现如下:
这里用到了相似度算法,其原理包括五步:
1、缩小尺寸
2、简化色彩
3、计算平均值
4、比较像素的灰度
5、计算哈希值
该算法的具体实现我们不用去关心,只需要导入 ImageCompareh 这个文件即可。在该文件内部用到了:
所以还需要导入这个框架: opencv2framework 。这两份文件在我的 demo 里都已经提供了。
如果上一张存在并且是现在的的创建时间是同一天,而且还满足相似度算法,则更新相似数据源,否则说明和上一张并不相似。
其中以创建日期作为字典的 key ,其方法 stringWithDate: 的实现如下:
这是最关键的一步,也是非常绕脑袋的一步,理解的关键是分清楚下面的数组和字典的作用和区别:
similarArray的内容打印结果如下:
similarArray中每一个lastDictionary打印结果如下:
lastDictionary的allValues:
对于大多数APP来说,内存占用主要就是,本文将从实用角度分析,iOS的内存占用、测量、优化等。
在移动 *** 作系统设备中,是不能像PC一样进行内存swap的,而随着用户的使用,打开的应用越来越多,应用使用的内存也越来越多,当占用的内存达到某个临界值时,iOS系统会尝试按照优先级逐个kill掉应用程序,以维护系统的流畅和稳定。
当iOS系统在清理内存过程中,优先级到了前台正在运行的应用程序,那么就会出现前台应用程序闪退的现象,也就是通常所说的OOM。
实际上,对于iOS系统内存,根据划分的方法方式,有很多内存种类,比较常见的有clean memory, dirty memory,有virtual memory, resident memory,等等。那么这么多的内存,重点要关注什么呢?
也就是说,iOS内存优化看“memory footprint”,“memory footprint”优化看“Persistent Bytes for All Heap & Anonymous VM”
先打一个比喻,我们平时为了传输方便,往往会对文件进行压缩,得到一个rar或者zip的压缩包,当我们要阅读文件时,需要先解压压缩包,得到doc或者txt等文档,然后再打开阅读。
类似的,我们平时看到的jpg,png,就是上面所说的压缩包,这个文件是不能直接上屏渲染的,需要先解压缩,然后才能在上屏。而我们平时无感知,直接打开文件就能看,是因为解码渲染很快,在你点击的时候就完成了解码+渲染的 *** 作了,类似zip压缩包也可以不解压直接预览一样。
那么显而易见,我们看到的磁盘上的和最终渲染出来的是不同的,那么实际加载渲染时的内存要怎么算呢。在iOS中可以通过以下公式快速计算。其中4是每个像素占用的byte,在iOS中固定为4(至少目前为止是的),Android中需要根据实际的调整,一般也是4。
如果要进行内存的优化,首先得保证能监测到的内存大小。内存的测量,各家有各家的方案,但是总的来说,都是在某个或多个加载的入口,进行侵入或非侵入AOP,进行相关的计算。
这里推荐一个方法,实用NSHashtable,弱引用持有对象。将的对象放到这个弱引用的hash表中,可以实时查看当前仍存活的所有对象,并据此计算占用的内存。
iOS中UIImage内存占用:
iOS内存-内存优化
iOS内存优化,大的方向就是:
就是在页面中同时加载的数量要少,单张的大小要小,占用的内存要勤释放,用CPU换内存。
一个典型的优化就是,UITableView中,cell的reuse。单个cell的高度推荐小于1屏,cell要能够重用,列表滚动时,cell中的按需加载和释放。能够做到这些,一般的内存问题都能够很好的解决。
目前流行的加载,都会选取CDN,将原图进行初步的压缩,然后加载,但是这个更多的考虑的是服务的的性能,负载均衡等等,客户端的收益基本就只有流量一条。客户端内存的优化微乎其微。
根据上面说的内存解释,我们知道内存暴涨就是在对其解压缩时。如果看过iOS最流行的加载框架SDWebImage,和腾讯开源框架LKImageKit,可以发现LKImageKit有一个很精细的加载优化,就是在解码时,根据加载的view的frame,进行解码。这样就避免了一个很小的view,加载一张很大的,消耗大量内存的情况。
在SDWebImage中,要实现这个feature会有点麻烦。需要将上层调用的frame透传到最下面的解码部分,且需要做一些错误校验。
此外,需要注意的是,压缩率比较高的,在进行这种二次压缩时,压缩后的有可能会有很严重的失真。
项目工程里面用到了压缩,这边做了个笔记整理了一下。
压缩:文件的体积变小,长宽尺寸不变,质量可能下降。
裁剪:文件尺寸变小,长宽尺寸变小,文件体积大小会变小。
在iOS中压缩使用到两个关键方法: UIImageJPEGRepresentation 和 UIImagePNGRepresentation 使用方式如下。
下面我们用测试一下两个方法的差异。就使用的本文上面的那张傍晚iPhone拍摄的,具体参数如图:
使用 UIImagePNGRepresentation(image) 返回的数据量大小为 1,299,138 字节(磁盘上的13 MB) 。
使用 UIImageJPEGRepresentation(image, 10) 返回的数据量大小为 183,531 字节(磁盘上的184 KB 。
可以看到 UIImagePNGRepresentation(UIImage \image) 要比 UIImageJPEGRepresentation(UIImage image, 10) 返回的数据量大很多。
使用 UIImageJPEGRepresentation 可以大幅度降低的数据量,比如刚才拍摄的那张,通过该方法压缩之后,数据大小仅为 184 KB 。 更改压缩系数为05再读取数据时,返回的数据大小只有 111 KB 。大小压缩了,但是清晰度并没有像差多少,质量也没有明显的降低。
所以在读取数据的时候,建议优先使用 UIImageJPEGRepresentation ,根据实际业务需求,设置压缩系数。
只写出关键部分,其它部分自己添加既可
1自动缩放到指定大小
{
UIImage newimage;
if (nil == image) {
newimage = nil;
}
else{
UIGraphicsBeginImageContext(asize);
[image drawInRect:CGRectMake(0, 0, asizewidth, asizeheight)];
newimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return newimage;
}
2保持原来的长宽比,生成一个缩略图
{
UIImage newimage;
if (nil == image) {
newimage = nil;
}
else{
CGSize oldsize = imagesize;
CGRect rect;
if (asizewidth/asizeheight > oldsizewidth/oldsizeheight) {
rectsizewidth = asizeheightoldsizewidth/oldsizeheight;
rectsizeheight = asizeheight;
rectoriginx = (asizewidth - rectsizewidth)/2;
rectoriginy = 0;
}
else{
rectsizewidth = asizewidth;
rectsizeheight = asizewidtholdsizeheight/oldsizewidth;
rectoriginx = 0;
rectoriginy = (asizeheight - rectsizeheight)/2;
}
UIGraphicsBeginImageContext(asize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
UIRectFill(CGRectMake(0, 0, asizewidth, asizeheight));//clear background
[image drawInRect:rect];
newimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return newimage;
}
以上就是关于IOS 解决问题:相似、截屏照片清理和图片压缩全部的内容,包括:IOS 解决问题:相似、截屏照片清理和图片压缩、iOS 内存分析-- 图片加载内存分析、iOS-图片压缩和裁剪等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)