iOS 图片压缩、滤镜、剪切、渲染等解析

栏目: C · 发布时间: 6年前

内容简介:主要内容:1、图片基础知识的介绍2、图片压缩

主要内容:

1、图片基础知识的介绍

2、图片压缩

  • 简单的回顾一下从相册获取一张图片

  • 直接格式转换压缩:png、jpg、Context 重新绘制

3、图片处理

  • 基于图片像素修改

  • 图片剪切clip

  • 渲染render

  • 截屏

一、图片基础知识的介绍

一张图像是像素点的集合,每一个像素都是一个独立,有自己的颜色。图像一般情况下都存储成数组,可以说是二维数组。当成百上千万个像素集合一起后,就构成了图像。表示图形的方式很多种YUV,RGBA,最简单的:32位RGBA模式。将一个颜色的值存储在32位中(或4个字节) 每个字节存储一个颜色通道(RGBA)。

二、图片压缩

2.1、简单的回顾一下从相册获取一张图片

<1>、说到系统的图片,离不开相册与相机,要能使真机在使用时成功调用相册/拍照功能,那么我们需要在info.plist类里面设置两个key:Privacy - Camera Usage Description与Privacy - Photo Library Usage Description,在测试的时候根据崩溃添加更好 iOS 图片压缩、滤镜、剪切、渲染等解析

相机与相册的key

<2>、挂两个代理:

<3>、定义两个button,相册的tag值 101,相机102,调用UIImagePickerController

#pragma mark 选择相册
-(void)selectImage:(UIButton *)sender{

     NSInteger tag = sender.tag - 100;
     NSUInteger sourceType = 0;
     
     if (tag == 1) {
          // 相册
          // 1.判断能否打开照片库(不支持直接返回)
          if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
                sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
                
      }else if (tag == 2){
          // 拍照
          // 2.判断支不支持相机(不支持直接返回)
          if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) return;
          sourceType = UIImagePickerControllerSourceTypeCamera;
      }
      
      UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
      //设置代理
      imagePickerController.delegate = self;
      // imagePickerController.allowsEditing = YES;
      imagePickerController.sourceType = sourceType;
      
     [self presentViewController:imagePickerController animated:YES completion:nil];
}

<4>、UIImagePickerController代理方法的实现(暂且去掉剪辑图片)

#pragma mark - UIImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary
<nsstring nbsp="" id="">
  *)info{
     
     NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
     // 获取到的图片
     if ([mediaType isEqualToString:@"public.image"]) {
           UIImage * image;
           // 判断,图片是否允许修改
           // if ([picker allowsEditing]){
                 //获取用户编辑之后的图像
                 // image = [info objectForKey:UIImagePickerControllerEditedImage];
           // } else {
                 // 照片的元数据参数
                 image = [info objectForKey:UIImagePickerControllerOriginalImage];
           // }
           
           // 压缩图片(处理) 看下面
     }
     
     [self dismissViewControllerAnimated:YES completion:NULL];
}

// 当用户取消选择的时候,调用该方法
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
      NSLog(@"取消相册使用 --- %s", __func__);
      [self dismissViewControllerAnimated:YES completion:nil];
}
</nsstring>

<4>、 计算  NSData 的大小

#pragma mark 计算  NSData 的大小
- (NSString*)length:(NSInteger)length{

     if (length > 1024 * 1024) {
         int mb = (int)length/(1024*1024);
         int kb = (length%(1024*1024))/1024;
         return [NSString stringWithFormat:@"%dMb%dKB",mb, kb];
     }else{
     
         return [NSString stringWithFormat:@"%ldKB",length/1024];
     }
}

2.2、在上面我们已经拿到图片了,那么下面我们队图片的压缩进行下处理

<1>:png 压缩

// 压缩图片
NSData *dataPNG = UIImagePNGRepresentation(image);
UIImage *compressPNGImage = [UIImage imageWithData:dataPNG];
NSLog(@"%@",[self length:dataPNG.length]);

提示:

  • 这种压缩方式会出现内存飙升

  • 文件属性格式并不会压缩,压缩的是图片内容(像素)

<2>:jpg 压缩

/**
 第一个参数:UIIMage 对象
 第二个参数:图片质量(压缩系数)0~1 之间
 */
NSData *dataJPG = UIImageJPEGRepresentation(image, 0.1);
UIImage *compressJPGImage = [UIImage imageWithData:dataJPG];
NSLog(@"%@",[self length:dataJPG.length]);

提示:

1.如果是通过JPEG来压缩图片, 图片压缩之后是不保真的

2.苹果官方不推荐我们使用JPG图片,因为现实JPG图片的时候解压缩非常消耗性能

3.这种压缩方式虽然可以通过设置图片质量,但是也会出现内存飙升

<3>:自定义 size 压缩通过 上下文 来压缩图片

UIImage *compressImg = [self compressOriginalImage:image withImageSize:CGSizeMake(200, 200)];
NSLog(@"%@",NSStringFromCGSize(compressImg.size));
 
// 压缩图片
- (UIImage *)compressOriginalImage:(UIImage *)originalImage withImageSize:(CGSize)size{
     // 开启图片上下文
     UIGraphicsBeginImageContext(size);
     // 将图片渲染到图片上下文
     [originalImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
     // 获取图片
     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
     // 关闭图片上下文
     UIGraphicsEndImageContext();
     return newImage;
}

提示:这种方式解决了内存的飙升,算是一种好的压缩方式

<4>:注意:一般情况下,只要涉及到从相册中获取图片的功能, 都需要处理内存,一般情况下一个应用程序启动会占用20M左右的内存, 当内存飙升到500M左右的时候系统就会发送内存警告, 此时就需要释放内存 , 否则就会闪退,只要内存释放到100M左右, 那么系统就不会闪退我们的应用程序,也就是说一个应用程序占用的内存20~100时是比较安全的内容范围。

三、图片处理

3.1、基于图片像素修改

<1>、过滤图片:涉及到图片的像素处理,也是根据上下文进行操作的,进行一个绘制;从图片文件把 图片数据的像素拿出来(RGBA), 对像素进行操作, 进行一个转换(Bitmap (GPU))

修改完之后,还原(图片的属性 RGBA,RGBA (宽度,高度,色值空间,拿到宽度和高度,每一个画多少个像素,画多少行))

iOS 图片压缩、滤镜、剪切、渲染等解析

过滤图片

-(void)filterImage{

       CGImageRef imageRef = self.imageView1.image.CGImage;
       // 1 个字节 = 8bit  每行有 17152 每行有17152*8 位
       size_t width   = CGImageGetWidth(imageRef);
       size_t height  = CGImageGetHeight(imageRef);
       size_t bits    = CGImageGetBitsPerComponent(imageRef); // 8
       size_t bitsPerrow = CGImageGetBytesPerRow(imageRef); // width * bits
       
       // 颜色空间
       CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
       // AlphaInfo: RGBA  AGBR  RGB  :AlphaInfo 信息
       CGImageAlphaInfo alpInfo =  CGImageGetAlphaInfo(imageRef);
       
       // bitmap的数据
       CGDataProviderRef providerRef = CGImageGetDataProvider(imageRef);
       CFDataRef bitmapData = CGDataProviderCopyData(providerRef);
       
       NSInteger pixLength = CFDataGetLength(bitmapData);
       // 像素byte数组
       Byte *pixbuf = CFDataGetMutableBytePtr((CFMutableDataRef)bitmapData);
       
       // RGBA 为一个单元
       for (int i = 0; i < pixLength; i+=4) {
       
            [self eocImageFiletPixBuf:pixbuf offset:i];
       }
       
       // 准备绘制图片了
       // bitmap 生成一个上下文  再通过上下文生成图片
       CGContextRef contextR = CGBitmapContextCreate(pixbuf, width, height, bits, bitsPerrow, colorSpace, alpInfo);
       
       CGImageRef filterImageRef = CGBitmapContextCreateImage(contextR);
       
       UIImage *filterImage =  [UIImage imageWithCGImage:filterImageRef];
       
       self.imageView1.image = filterImage;
}

// RGBA 为一个单元  彩色照变黑白照
- (void)eocImageFiletPixBuf:(Byte*)pixBuf offset:(int)offset{

       int offsetR = offset;
       int offsetG = offset + 1;
       int offsetB = offset + 2;
       // int offsetA = offset + 3;
       
       int red = pixBuf[offsetR];
       int gre = pixBuf[offsetG];
       int blu = pixBuf[offsetB];
       // int alp = pixBuf[offsetA];
       
       int gray = (red + gre + blu)/3;
       
       pixBuf[offsetR] = gray;
       pixBuf[offsetG] = gray;
       pixBuf[offsetB] = gray;
}

<2>、还原图片:这个其实没什么讲的,只要把过滤前的图片的UIIMage进行保存,再次赋值就好

3.2、图片剪切clip

iOS 图片压缩、滤镜、剪切、渲染等解析

图片剪切clip

<1>、规则图片剪切(圆形,矩形等)

#pragma mark 剪切图片(规则的剪切图)
-(void)clipImage{

     CGSize size = CGSizeMake(100, 100);
     
     // 开启上下文
     UIGraphicsBeginImageContext(size);
     // 获取当前的上下文
     CGContextRef context = UIGraphicsGetCurrentContext();
     
     // 设置路径剪切(设置一个圆)
     CGRect rect = CGRectMake(0, 0, size.width, size.height);
     CGContextAddEllipseInRect(context, rect);
     
     CGContextClip(context);
     // 把图片绘制上去
     [self.oriImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
     
     UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
     
     UIGraphicsEndImageContext();
     
     // 把剪切过的图片展示出来 
     self.imageView2.image = clipImage;
}

<2>、不规则图片剪切(根据自定义path剪切)

#pragma mark 剪切图片(不规则的剪切图)
-(void)irRegularclipImage{

      UIGraphicsBeginImageContext(CGSizeMake(200, 200));
      CGContextRef context = UIGraphicsGetCurrentContext();
      
      // 非规则的path
      CGMutablePathRef pathRef = CGPathCreateMutable();
      CGPoint lines[] = {
            CGPointMake(50,0),
            CGPointMake(100,0),
            CGPointMake(150,80),
            CGPointMake(0,80),
            CGPointMake(50,0)
      };
      CGPathAddLines(pathRef, NULL, lines, 5);
      CGContextAddPath(context, pathRef);
      CGContextClip(context);
      
      [self.oriImage drawInRect:CGRectMake(0, 0, 200, 200)];
      
      UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
      
      UIGraphicsEndImageContext();
     
      // 把剪切过的图片展示出来 
      self.imageView3.image = clipImage;
}

3.3、图片渲染

#pragma mark 在图片上渲染一层半透明的红色
-(void)blend{

     // 原图的大小
     CGSize size = CGSizeMake(self.imageView1.frame.size.width, self.imageView1.frame.size.height);
     
     UIGraphicsBeginImageContext(size);
     
     CGContextRef context = UIGraphicsGetCurrentContext();
     
     [self.oriImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
     
     // 设置半透明红色的渲染
     UIColor *redColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
     CGContextSetFillColorWithColor(context, redColor.CGColor);
     CGContextSetBlendMode(context, kCGBlendModeNormal);
     CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
     
     // 获取渲染的CGImageRef
     CGImageRef imageRef =  CGBitmapContextCreateImage(context);
     
     self.imageView1.image = [UIImage imageWithCGImage:imageRef];
     
     UIGraphicsEndImageContext();
     
}

3.4、截屏(截取一个对象上的所有视图),我们以截取self.view的视图为例

iOS 图片压缩、滤镜、剪切、渲染等解析

截屏**(截取一个对象上的所有视图),我们以截取self.view的视图为例

<1>、截屏方式一

- (UIImage *)jk_snapshotImage {

     UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0);
     [self.view drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
     UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     
     return result;
}

<2>、截屏方式一

- (UIImage *)imageFromFullView{

    UIGraphicsBeginImageContext(self.view.frame.size);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    [self.view.layer renderInContext:context];
    
    CGImageRef imageRef =  CGBitmapContextCreateImage(context);
    
    UIImage *newImage = [UIImage imageWithCGImage:imageRef];
    
    UIGraphicsEndImageContext();
    
    return newImage;
}

此篇博客的 demo

作者:IIronMan

链接:https://www.jianshu.com/p/6935ad0dca7a


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Open Data Structures

Open Data Structures

Pat Morin / AU Press / 2013-6 / USD 29.66

Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues......一起来看看 《Open Data Structures》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具