iOS开发之——图片压缩

前言:最近做的一个项目需要上传图片到服务器,根据需求来设计压缩图片

一: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 博主的参考

你可能感兴趣的:(iOS开发之——图片压缩)