项目中常会遇到,上传图片的操作,由于iPhone手机直接拍照的图片往往比较大,一般3-4M,如果直接上传不做处理会浪费用户很多流量,再者有很多场景并不需要高清图片,所以在上传图片前对图片进行压缩,是很有必要的。
1.OC中的UIKit中提供了现成的压缩函数 UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality) ,但压缩比率只能是0.1到0.9,如果图片过大,还是无法达到我们想要的效果。
2.对于大图片(10M以上),我们可以先对图片进行裁剪,然后再压缩。这个方法能大大压缩图片的大小。以我的项目中需求为例,需求是:不管多大图片,都要压缩至50kb左右才可以上传到服务器,而且像素不能过度失真。
1 + (NSData *)compressWithOrgImg:(UIImage *)img 2 { 3 4 NSData *imageData = UIImageJPEGRepresentation(img, 1); 5 float length = imageData.length; 6 length = length/1024; 7 NSLog(@"压缩前的大小:%fKB",length); 8 // 裁剪比例 9 CGFloat cout = 0.5; 10 11 // 压缩比例 12 CGFloat imgCout = 0.1; 13 if(length > 25000){ // 25M以上的图片 14 cout = 0.1; 15 imgCout = 0; 16 }else if(length > 10000){ // 10M以上的图片 17 cout = 0.2; 18 imgCout = 0; 19 }else if (length > 5000) { // 5M以上的图片 20 cout = 0.3; 21 imgCout = 0; 22 }else if (length > 1500) { // 如果原图大于1.5M就换一个压缩级别 23 cout = 0.7; 24 imgCout = 0.1; 25 }else if (length > 1000) { 26 cout = 0.8; 27 imgCout = 0.2; 28 }else if (length > 500) { 29 cout = 0.8; 30 imgCout = 0.3; 31 }else if (length >100){ // 小于500k的不用裁剪 32 33 imageData = UIImageJPEGRepresentation(img, 50 / imageData.length); 34 float length = imageData.length; 35 length = length/1024; 36 NSLog(@"压缩后的大小:%fKB",length); 37 return imageData; 38 }else{ 39 40 imageData = UIImageJPEGRepresentation(img, 0.5); 41 float length = imageData.length; 42 length = length/1024; 43 NSLog(@"压缩后的大小:%fKB",length); 44 return imageData; 45 } 46 47 48 // 按裁剪比例裁剪 49 UIImage *compressImage = [img imageByScalingAndCroppingForSize:CGSizeMake(img.size.width * cout, img.size.height *cout)]; 50 51 52 // 那压缩比例压缩 53 imageData = UIImageJPEGRepresentation(compressImage, imgCout); 54 55 length= imageData.length / 1024; 56 NSLog(@"裁剪比例:%f,压缩比例:%f,压缩后的大小:%fKB",cout,imgCout,length); 57 return imageData; 58 }
1 // 裁剪 2 - (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize 3 { 4 UIImage *sourceImage = self; 5 UIImage *newImage = nil; 6 CGSize imageSize = sourceImage.size; 7 CGFloat width = imageSize.width; 8 CGFloat height = imageSize.height; 9 CGFloat targetWidth = targetSize.width; 10 CGFloat targetHeight = targetSize.height; 11 CGFloat scaleFactor = 0.0; 12 CGFloat scaledWidth = targetWidth; 13 CGFloat scaledHeight = targetHeight; 14 CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 15 16 if (CGSizeEqualToSize(imageSize, targetSize) == NO) 17 { 18 CGFloat widthFactor = targetWidth / width; 19 CGFloat heightFactor = targetHeight / height; 20 21 if (widthFactor > heightFactor) 22 scaleFactor = widthFactor; // scale to fit height 23 else 24 scaleFactor = heightFactor; // scale to fit width 25 scaledWidth= width * scaleFactor; 26 scaledHeight = height * scaleFactor; 27 28 // center the image 29 if (widthFactor > heightFactor) 30 { 31 thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 32 } 33 else if (widthFactor < heightFactor) 34 { 35 thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 36 } 37 } 38 39 UIGraphicsBeginImageContext(targetSize); // this will crop 40 41 CGRect thumbnailRect = CGRectZero; 42 thumbnailRect.origin = thumbnailPoint; 43 thumbnailRect.size.width= scaledWidth; 44 thumbnailRect.size.height = scaledHeight; 45 46 [sourceImage drawInRect:thumbnailRect]; 47 48 newImage = UIGraphicsGetImageFromCurrentImageContext(); 49 if(newImage == nil) 50 NSLog(@"could not scale image"); 51 52 //pop the context to get back to the default 53 UIGraphicsEndImageContext(); 54 return newImage; 55 }
代码中针对不同大小图片,给出了不同的压缩比率,以保证压缩后的图片大小都在50k左右。此处的“裁剪”是将图片的宽高等比例缩小到指定的比率