前言:最近做的一个项目需要上传图片到服务器,根据需求来设计压缩图片
一:iOS读取图片数据的方法
UIImagePNGRepresentation(<#UIImage * _Nonnull image#>)
UIImageJPEGRepresentation(<#UIImage * _Nonnull image#>, <#CGFloat compressionQuality#>)
比较两种方式不同点:
- UIImagePNGRepresentation(image)只需要图片一个参数,耗时比较大。
- UIImageJPEGRepresentation(image,1.0)需要图片和压缩系数两个参数,耗时比较小。
二:具体使用
分别使用两个函数进行测试,发现同一张照片返回的数据大小是不一样的。
例如:在网上下载的图片117K,使用UIImageJPEGRepresentation(image, 1.0)方法后得到的大小是348K,但是使用UIImagePNGRepresentation后却有583K。
因为UIImageJPEGRepresentation(image, 1.0)这个方法里面的参数,其实使用会发现并不是和自己想想的一样,不是线性变化的,使用1.0拿到的数据也不是真实的数据大小,同理0.5也不是数据大小的一半。
UIImagePNGRepresentation这个函数返回的大小,我们没有办法做处理,只能看结果,所以,也就直接抛弃了研究方向。
三:压缩尺寸
- 使用压缩比例
主要是通过 drawInRect方法重新绘制图片
/**
等比压缩
@param image 原图片
@param scaleSize 压缩比例
@return 压缩后的图片
*/
- (UIImage *)scaleImage:(UIImage *)image toScale:(float)scaleSize {
CGFloat imageW = image.size.width * scaleSize;
CGFloat imageH = image.size.height * scaleSize;
UIGraphicsBeginImageContext(CGSizeMake(imageW, imageH));
[image drawInRect:CGRectMake(0, 0, imageW, imageH)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
这里需要传入两个参数:需要压缩的image、压缩比
可以看到下图,传入的参数是0.5,压缩后图片大小、宽、高确实是原图的一半。
等比率压缩
- 给定尺寸的压缩
这种适合,需求就是要固定的尺寸,这种做法可以做到一步到位,小图拉伸,大图缩小。
/**
自定义长宽
@param image 原图片
@param reSize 定义的图片大小
@return 压缩后的图片
*/
- (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize {
UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height));
[image drawInRect:CGRectMake(0, 0, reSize.width, reSize.height)];
UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return reSizeImage;
}
下图传的参数为CGSizeMake(1000, 680)
固定尺寸压缩
- 给定图片质量大小进行压缩
- (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)));
UIGraphicsBeginImageContext(size);
[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
data = UIImageJPEGRepresentation(resultImage, 1);
}
return resultImage;
}
下图传的参数是1024*1024的大小,看下压缩后的效果,可以和上面的那个给定尺寸做下比较。
给定内存大小压缩尺寸
四:压缩质量
- 指定大小压缩
- (NSData *)compressOriginalImage:(UIImage *)image toMaxDataSizeKBytes:(CGFloat)size{
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(image, compression);
if (data.length <= size) {
return data;
}
CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
compression = (max + min) / 2;
data = UIImageJPEGRepresentation(image, compression);
if (data.length < size) {
min = compression;
} else if (data.length > size * 0.9) {
max = compression;
} else {
break;
}
}
return data;
}
下图传的参数是1024*1024,压缩质量,尺寸不变
指定内存大小压缩质量
五:压缩图片和压缩尺寸结合
- (NSData *)compressWithOriginalImage:(UIImage *)image maxLength:(NSUInteger)maxLength{
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(image, compression);
if (data.length <= maxLength) {
return data;
}
CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
UIImage *resultImage = [UIImage imageWithData:data];
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, 1);
compression = (max + min) / 2;
if (data.length <= maxLength) {
return data;
}
if (data.length < maxLength) {
min = compression;
} else if (data.length > maxLength * 0.9) {
max = compression;
} else {
break;
}
data = UIImageJPEGRepresentation(resultImage, compression);
if (data.length <= maxLength) {
return data;
}
}
return data;
}
下图同样的传参为1024*1024
质量和尺寸同时压缩
六:总结
- 在使用压缩尺寸的方法时,图片的质量肯定是减少的,但是压缩尺寸要是处理不好可能会显示白边,同时也可能是图片模糊,要想保证图片清晰度就使用质量压缩。
- 质量压缩只要使用二分法,避免使用循环造成耗性能。
- 使用两种结合的模式
1.先进行图片的尺寸压缩,判断是否是趋近于指定大小,是->返回, 否->进行质量压缩
2.质量压缩后再次判断是否趋近于指定大小,是->返回, 否->进行图片压缩
感谢 http://www.cnblogs.com/silence-cnblogs/p/6346729.html 博主的参考
网友评论