iOS开发之——图片压缩

作者: 天空像天空一样蓝 | 来源:发表于2018-10-26 15:57 被阅读0次

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

    一: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开发之——图片压缩

        本文链接:https://www.haomeiwen.com/subject/quoktqtx.html