开发中经常会碰到从手机相册中选择图片的需求,选择图片这个过程是一个消耗性能的过程,取决于手机图片的大小,如果手机像素非常高,图片的尺寸非常大,这个时候就会变得很消耗性能,比如一张图片5M,这个时候选择后加载的时候就会有些卡顿,内存开始大幅升高,仔细想想也没有这种必要去加载这么大的图片,所以总结了两种处理方法,提供参考
1:对图片进行压缩,iOS的API中提供了函数进行压缩,代码如下:
NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
//实际开发中的例子
+(NSData *)imageData:(UIImage *)myimage
{
NSData *data = UIImageJPEGRepresentation(myimage, 1.0);
if (data.length>100*1024) {
if (data.length>1024*1024) {
//1M以及以上
data=UIImageJPEGRepresentation(myimage, 0.1);
}else if (data.length>512*1024) {
//0.5M-1M
data=UIImageJPEGRepresentation(myimage, 0.5);
}else if (data.length>200*1024) {
//0.25M-0.5M
data=UIImageJPEGRepresentation(myimage, 0.9);
}
}
return data;
}
优点:在基本没有降低图片的质量的前提下,压缩图片,不改变图片的分辨率
缺点:压缩图片有一定限度,因为这是不改变分辨率的压缩。比如你想压缩图片到原来的十分之一大小,但是他最大可能只会压缩到三分之一。经测试图片最大能压到的大小和图片本身有关,每个图片各不相同
这个返回的是二进制的data值,可以通过打印知道大小确实减少了好多,通过此方法确实能优化性能,需要注意的是这个0.5,并不是说压缩到之前图片的二分之一 ,应该是个系数之类的数值(0-1),这样的话图片压缩之后性能会好很多,但是不建议这个,因为解压缩的时候很耗费性能建议使用第二种方法
2:根据image从新绘制一张新的图片出来,第一种的方法多多少少会有些失真,第二种方法是根据图片从新绘制一张出来,不会失真,只是改变图片的大小,比如之前是5000 * 5000的分辨率,这个时候你压缩后可能就只有500 * 500 ,不会失真,只会改变大小,建议使用,方法如下:
//压缩图片
+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
// Create a graphics image context
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
// Return the new image.
return newImage;
}
怎么计算图片占用内存的大小呢?
我们平时看到的png、jpg、webp这些图片格式,其实都是图片压缩格式。通过对应的算法来优化了大小以节省网络传输与本地保存所需的资源。但是当我们加载图片到内存中将要显示出来的时候是不能使用压缩格式,这样就不能显示图片了。计算机依赖每一个像素点中的数据来显示图片。例如iOS中的UIImange的每个像素点是由red+green+blue 三原色在加上alpha透明度组成的。三原色每一个的范围在0 ~ 255所以需要int8来存储一个值的大小。那么一个像素点的颜色就需要3*int8 在加上需要alpha的大小。alpha的范围是0 ~ 100 也是以int8来存储的。所以一个像素点就需要4个int8来存储,也就是一个int32的大小。
我们平时取颜色也可以看到这一点。一张图片由很多像素点组成每个像素点由rgb组成的。但是这里是取颜色可能获取不到alpha。那我们现在知道了每一个像素点的大小,得出一整张图片在内存中的大小就很容易了。width * height * int32 = 图片的内存大小。
//解释一下这里bytesPerRow这个属性的意思,苹果官方文档上是这样描述的
//bytesPerRow
//The number of bytes per row of pixels in the input image data.
if let imagea = UIImage.init(named: "ccc.png"){
let size = imagea.cgImage.height * imagea.cgImage.bytesPerRow
}
所以bytesPerRow 返回的是一张图片一行所占用的内存大小。单位是bytes。
所以我们这里只需要在乘以图片的高度就OK了。如果要转换为kb直接在除以1024就OK了。基本就是一张图片在内存中占用的大小。以一张400 * 400的图片为例。
400 * (400 * 4) / 1024 = 625KB
其中400*4 = bytesPerRow的值
网友评论