美文网首页
图片压缩到指定大小,并尽量减少失真

图片压缩到指定大小,并尽量减少失真

作者: yok_ | 来源:发表于2018-04-24 14:36 被阅读130次

在app中,如果上传图片不进行压缩处理,有些高清大图就会上传得很慢,如果用户量大,同一时间内有大量用户上传高清大图,则容易阻塞服务器,而且其他用户查看图片时会出现下载慢费流量的问题,而进行了压缩处理,则可以加快图片上传下载的速度,还可以节省用户流量。

iOS中有两种方式可以对图片进行压缩:压缩图片质量,压缩图片尺寸

压缩图片质量(尺寸不变,质量改变)

NSData *data = UIImageJPEGRepresentation(image, compression);
UIImage *resultImage = [UIImage imageWithData:data];

压缩图片尺寸(尺寸改变,质量不变)

[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

压缩图片到指定大小的设计:

采用压缩图片质量和压缩图片尺寸两种方法结合,先压缩图片质量再压缩图片尺寸,压缩图片质量时,采用二分法来提高压缩效率,同时由于有时候图片压缩到一定程度后,再次压缩并不会减少图片数据,所以每次压缩后都和上一次的图片大小进行对比,如果变化不大,则退出循环,或达到目标大小时退出循环。压缩图片尺寸则采用绘图的方式,这样图片质量不会丢失,同时对目标大小和当前数据大小的系数进行开根,这样当前数据大小离目标数据大小越大,图片尺寸减小得越大,减小循环次数提供绘图效率,当然,压缩质量和压缩尺寸都是在子线程中进行,尽量减少主线程压力

效果

这个是20M大图,被压缩到87kb,从压缩开始到完成用时1秒


image.png
image.png

这个是800多KB的图片,被压缩到65KB,从压缩开始到完成用时0.1秒


image.png image.png

代码:

-(void)compressWithMaxLengthKB:(NSUInteger)maxLengthKB Block :(void (^)(NSData *imageData))block{
    if (maxLengthKB <= 0 || [self isKindOfClass:[NSNull class]] || self == nil) block(nil);
    
    maxLengthKB = maxLengthKB*1024;
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        CGFloat compression = 1;
        NSData *data = UIImageJPEGRepresentation(self, compression);
        NSLog(@"初始 : %ld KB",data.length/1024);
        if (data.length < maxLengthKB){
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"压缩完成: %zd kb", data.length/1024);
                block(data);
            });
            return;
        }
        
        //质量压缩
        CGFloat scale = 1;
        CGFloat lastLength=0;
        for (int i = 0; i < 7; ++i) {
            compression = scale / 2;
            data = UIImageJPEGRepresentation(self, compression);
            NSLog(@"质量压缩中: %ld KB", data.length / 1024);
            if (i>0) {
                if (data.length>0.95*lastLength) break;//当前压缩后大小和上一次进行对比,如果大小变化不大就退出循环
                if (data.length < maxLengthKB) break;//当前压缩后大小和目标大小进行对比,小于则退出循环
            }
            scale = compression;
            lastLength = data.length;

        }
        NSLog(@"压缩图片质量后: %ld KB", data.length / 1024);
        if (data.length < maxLengthKB){
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"压缩完成: %zd kb", data.length/1024);
                block(data);
            });
            return;
        }
        
        //大小压缩
        UIImage *resultImage = [UIImage imageWithData:data];
        NSUInteger lastDataLength = 0;
        while (data.length > maxLengthKB && data.length != lastDataLength) {
            lastDataLength = data.length;
            CGFloat ratio = (CGFloat)maxLengthKB / data.length;
            NSLog(@"Ratio = %.1f", ratio);
            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, compression);
            NSLog(@"绘图压缩中: %ld KB", data.length / 1024);
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"压缩完成: %zd kb", data.length/1024);
            block(data);
        });return;
    });
    
}

相关文章

网友评论

      本文标题:图片压缩到指定大小,并尽量减少失真

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