iOS小技能:解决图片压缩之后模糊的问题

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

前言

压缩原理:找出那些重复出现的字符串,然后用更短的符号代替,达到缩短字符串的目的。

比如,一篇文章大量使用"#公众号::iOS逆向"这个词语,我们用"iOS"代替,就缩短了6个字符,如果用"i"代替,就缩短了8个字符。

事实上,只要保证对应关系,可以用任意字符代替那些重复出现的字符串。

本质上,所谓"压缩"就是找出文件内容的概率分布,将那些出现概率高的部分代替成更短的形式。

所以,内容越是重复的文件,就可以压缩地越小。

比如,"ABABABABABABAB"可以压缩成"7AB"。 在这里插入图片描述

I 图片压缩的两种方式

  1. 质量压缩:即损失图片的质量为代价,大小(长宽尺寸)不变;

          UIImageJPEGRepresentation(image, 0.0);//JPEG
     NSData * imageData = UIImagePNGRepresentation(image);
`
//推荐使用png 因为`PNG:0x89 image/png ,压缩比没有 JPG 高,但是无损压缩,解压缩性能高,苹果推荐的图像格式!
复制代码
  1. 像素压缩(比例压缩):通过减少长宽方向的像素数量;

          [sourceImage drawInRect:CGRectMake(0,0,targetWidth, targetHeight)] ;
          

复制代码

本文的压缩方案:质量压缩(0.5) 结合比例压缩(1028):

1、质量压缩的比例(质量压缩使用系统APIUIImageJPEGRepresentation) 2、比例压缩使用:drawInRect

II、 解决压缩之后图片模糊的问题

模糊的问题的大部分原因:使用第三方框架,(比如QMUIKit),在选择相册预览的时候,就把图片压缩了很模糊了。

应用场景:针对协议类型这种大图

2.1、如果是拍照,可以压缩一下分辨率,否则上传很慢

不用使用预览图进行上传

//    [self imgUpLoad:imageAsset.previewImage Max:1 Index:1];
    
    [self imgUpLoad:imageAsset.originImage Max:1 Index:1];

复制代码

如果是拍照,可以压缩一下分辨率,否则上传很慢

    return  [self imageCompressForSize:image targetSize:size];

复制代码

拍照压缩分辨率的例子

- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
    //当选择的类型是图片
    if ([type isEqualToString:@"public.image"])
    {
        UIImage *image1 = [info objectForKey:UIImagePickerControllerOriginalImage];
        image1 = [ControlManager image:image1 scaleToSize:CGSizeMake(1000, 1200)];// 压缩分辨率 便于上传
        
        [picker dismissViewControllerAnimated:YES completion:nil];
        
        [SVProgressHUD showWithStatus:@"上传中.." maskType:SVProgressHUDMaskTypeGradient];
        [self imgUpLoad:image1 Max:1 Index:1];
    }
}

复制代码

2.2、 质量压缩(0.5) 结合比例压缩(1028)

用法

        NSData * imageData = UIImageJPEGRepresentation( [image compressWithTargetPixel:1028], k_UIImageJPEGRepresentationcompressionQuality);

复制代码

质量压缩的比例

(质量压缩使用系统APIUIImageJPEGRepresentation

#define k_UIImageJPEGRepresentationcompressionQuality 0.5

复制代码

比例压缩的代码



- (UIImage *)compressWithTargetPixel:(NSUInteger)targetPx {
    
    UIImage *newImage = nil;
    
    CGSize imageSize = self.size;
    CGFloat width = imageSize.width * self.scale;
    CGFloat height = imageSize.height * self.scale;
    
    // 是否重绘
    BOOL drawImge = NO;
    
    // 压缩后的尺寸
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetPx;
    CGFloat scaledHeight = targetPx;
    
    // 1. 图片宽高均 ≤ 参照像素,图片尺寸保持不变
    if (width <= targetPx && height <= targetPx) {
        newImage = self;
    }
    
    // 2. 宽或高均 > 参照像素
    else if (width > targetPx && height > targetPx) {
        
        drawImge = YES;
        CGFloat factor = width / height;
        
        if (factor <= 2) {
            // 2.1 图片宽高比 ≤ 2,则将图片宽或者高取大的等比压缩至1280px
            if (width > height) {
                scaleFactor  = targetPx / width;
            } else {
                scaleFactor = targetPx / height;
            }
        } else {
            // 2.2 图片宽高比 > 2时,则宽或者高取小的等比压缩至1280px
            if (width > height) {
                scaleFactor  = targetPx / height;
            } else {
                scaleFactor = targetPx / width;
            }
        }
    }
    
    // 3. 宽高一个 >= 1280px,另一个 < 1280px; 宽 >= 1280
    else if (width >= targetPx && height < targetPx ) {
        if (width / height > 2) {
            newImage = self;
        } else {
            drawImge = YES;
            scaleFactor = targetPx / width;
        }
    }
    // 4. 宽高一个 >= 1280px,另一个 < 1280px 高 >= 1280
    else if (width < targetPx &&  height >= targetPx) {
        if (height / width > 2) {
            newImage = self;
        } else {
            drawImge = YES;
            scaleFactor = targetPx / height;
        }
    }
    
    if (drawImge == YES) {
        scaledWidth = width * scaleFactor;
        scaledHeight = height * scaleFactor;
        
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(scaledWidth/self.scale, scaledHeight/self.scale), YES, [UIScreen mainScreen].scale);
        [self drawInRect:CGRectMake(0, 0, scaledWidth/self.scale, scaledHeight/self.scale)];
        newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
    
    if (newImage == nil) {
        newImage = self;
    }
    
    newImage = [UIImage imageWithData:UIImageJPEGRepresentation(newImage, 0.7) scale:newImage.scale];
    
    return newImage;
}

复制代码

III 针对业务场景选择图片格式

3.1 如何区分不同格式的图像的

  • 根据图像数据第一个字节来判断的!
	// NSData+ImageContentType.m    + (NSString *)sd_contentTypeForImageData:

	PNG:0x89 image/png ,压缩比没有 JPG 高,但是无损压缩,解压缩性能高,苹果推荐的图像格式!
	JPG:0xFF image/jpeg,压缩比最高的一种图片格式,有损压缩!最多使用的场景,照相机!解压缩的性能不好!
	GIF:0x47 image/gif ,序列桢动图,特点:只支持 256 种颜色!最流行的时候在 19981999,有专利的!

复制代码

3.2 使用场景分析

3.2.1 JPEG/JPG

  • 特点:有损压缩、体积小、不支持透明
  • 使用场景:颜色丰富的照片,JPG是通用的选择,如大的背景图、轮播图或Banner图。

3.2.2 PNG

  • 特点:无损压缩、质量高、体积大、支持透明。
  • 使用场景:透明图片的业务场景,如小的Logo、颜色简单且对比强烈的图片或背景。

3.2.3 SVG

  • 特点:文本文件、体积小、不失真、兼容性好、无需多端、多分辨率适配、较强的交互特性、渲染成本比较高。
  • 使用场景:图片色彩相对简单的业务场景。

3.2.4 Base64

  • 特点:文本文件、依赖编码,Base64编码后,图片大小会膨胀为原文件的4/3。
  • 使用场景:小图标(<8KB)解决方案。

3.2.5 WebP

  • 特点:WebP图片是一种新的图像格式,由Google开发。与png、jpg相比,相同的视觉体验下,WebP图像的尺寸缩小了大约30%。另外,WebP图像格式还支持有损压缩、无损压缩、透明和动画,但有兼容性问题。
  • 使用场景:图片占较大的商场类网站,目前Google、Facebook、ebay、淘宝、腾讯、美团等已经在用。

“打开淘宝网,假如你是chrome浏览器,你会发现,所有图片都是webp结尾的,淘宝网图片运用了webp。假如你是safari浏览器,看到图片就是jpg或者png了,淘宝网自动判断浏览器支持不支持webp,假如支持,则输出相应的图片格式!

img.alicdn.com/imgextra/i4…

IV see also

更多内容请查看原文或者关注公众号:iOS逆向

ZipArchive

带密码解压缩

4.1: NSData与UIImage之间的转换


//NSData转换为UIImage
NSData *imageData = [NSData dataWithContentsOfFile: imagePath];
UIImage *image = [UIImage imageWithData: imageData];

//UIImage转换为NSData
NSData *imageData = UIImagePNGRepresentation(aimae);
复制代码

4.2 其他压缩参考

猜你喜欢

转载自juejin.im/post/7091103373046317093