• (五十)Quartz2D生成图片的一些应用


    应用一:给图片打水印,不应该是画到View的Layer上,而应该画到Bitmap上,产生一张新的图片。

    1.首先读入背景图,然后开启一个位图上下文,并将它画在位图上下文上:

        UIImage *bgImage = [UIImage imageNamed:@"scene"];
        /**
         *  创建基于位图的上下文
         *
         *  @param size#>   图片的尺寸 description#>
         *  @param opaque#> 是否不透明 YES为不透明、NO透明 description#>
         *  @param scale#>  伸缩尺寸,写0.0是按默认尺寸 description#>
         *
         *  @return void
         *
         *  执行完毕后就相当于创建了一个新的UIImage,尺寸就是传入的size
         */
        UIGraphicsBeginImageContextWithOptions(bgImage.size, NO, 0.0);
        // 画背景
        [bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];

    2.接下来计算要打的水印的位置,并且进行尺寸的缩放:

        // 画右下角的水印
        UIImage *waterImage = [UIImage imageNamed:@"logo"];
        CGFloat scale = 0.2;
        CGFloat margin = 5;
        CGFloat waterW = waterImage.size.width * scale;
        CGFloat waterH = waterImage.size.height * scale;
        CGFloat waterX = bgImage.size.width - waterW - margin;
        CGFloat waterY = bgImage.size.height - waterH - margin;
        [waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
    3.从上下文中取出画好的图片,然后结束上下文:

        // 从上下文中取得制作完毕的UIImage对象
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        
        // 结束上下文
        UIGraphicsEndImageContext();

    4.保存图片:转为二进制数据(压缩为JPEG或者PNG图片数据,JPEG可以选择压缩质量0-1,PNG默认最好的质量)。

    JPEG:第二个参数为质量

    UIImageJPEGRepresentation(<#UIImage *image#>, <#CGFloat compressionQuality#>)

    PNG:只有一个参数

    NSData *data = UIImagePNGRepresentation(newImage);

    通过搜索的方式查找Documents文件夹的方法:注意找到的路径是个数组,iOS系统只有一个路径,因此使用lastObject就可以取到。

    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"文件名.拓展名"];


    应用二:生成圆形头像图片。

    先开启位图上下文,然后取得这个上下文(同以前一样)画一个圆,并且开启裁剪(先开启裁剪后面的才会收到裁剪的影响)。

    为了产生一个白框,应该先画一个大圆,然后在期内画一个小圆,这时候执行裁剪,因为只有这后面的部分才会执行裁剪,因此就会出现一个大圆和小圆之间的环,一般取为白色。

        // 1.加载原图
        UIImage *oldImage = [UIImage imageNamed:@"me"];
        
        // 2.开启上下文
        CGFloat borderW = 2; // 圆环的宽度
        CGFloat imageW = oldImage.size.width + 2 * borderW;
        CGFloat imageH = oldImage.size.height + 2 * borderW;
        CGSize imageSize = CGSizeMake(imageW, imageH);
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
        
        // 3.取得当前的上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        
        // 4.画边框(大圆)
        [[UIColor whiteColor] set];
        CGFloat bigRadius = imageW * 0.5; // 大圆半径
        CGFloat centerX = bigRadius; // 圆心
        CGFloat centerY = bigRadius;
        CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);
        CGContextFillPath(ctx); // 画圆
        
        // 5.小圆
        CGFloat smallRadius = bigRadius - borderW;
        CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);
        // 裁剪(后面画的东西才会受裁剪的影响)
        CGContextClip(ctx);
        
        // 6.画图
        [oldImage drawInRect:CGRectMake(borderW, borderW, oldImage.size.width, oldImage.size.height)];
        
        // 7.取图
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        
        // 8.结束上下文
        UIGraphicsEndImageContext();
        
        // 9.显示图片
        self.iconView.image = newImage;
        
        // 10.写出文件
        NSData *data = UIImagePNGRepresentation(newImage);
        NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"new.png"];
        [data writeToFile:path atomically:YES];
    

    应用三:屏幕截图

    截图的原理:将View的layer渲染到上下文,然后取出图片保存。

    一个细节:应该延迟截图,让按钮恢复非点击状态。

    作为ImageView的一个功能,将屏幕截图作为分类扩充方法:注意从layer捕捉的方法

    #import "UIImage+MJ.h"
    
    @implementation UIImage (MJ)
    + (instancetype)captureWithView:(UIView *)view
    {
        // 1.开启上下文
        UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
        
        // 2.将控制器view的layer渲染到上下文
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
        
        // 3.取出图片
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        
        // 4.结束上下文
        UIGraphicsEndImageContext();
        
        return newImage;
    }
    @end

    如果要存入系统相册,应该调用UIImageWriteToSavedPhotoAlbum方法,注意回调函数应该用官方建议的方法:

    UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    回调函数的写法:
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
    {
        if (error) { // 保存失败
            [MBProgressHUD showError:@"保存失败"];
        } else { // 保存成功
            [MBProgressHUD showSuccess:@"保存成功"];
        }
    }

    应用四:背景平铺。

    使用Quartz2D可以将一个小图片完全平铺到背景:注意到colorWithPatternImage可以设置背景图。

        UIImage *oldImage = [UIImage imageNamed:@"me"];
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
        [oldImage drawInRect:self.view.bounds];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        self.view.backgroundColor = [UIColor colorWithPatternImage:newImage];



    总结:

    1.因为只有drawRect:方法中才能取出上下文,因此应该在这里绘图。

    2.View内部有一个layer层,drawRect:方法获取的是view的layer,view显示全靠layer,view还有一个响应事件的作用。

    3.产生图片的方法:

    先开启图形上下文

    UIGraphicsBeginImageContextWithOptions...

    然后可以在需要绘图时按原来的方法获取上下文

    然后取图:UIImage *newImage =UIGraphicsGetImageFromCurrentImageContext();

    最后不要忘了结束上下文:UIGraphicsEndImageContext();







  • 相关阅读:
    python基础之列表解析
    初学者学习python2还是python3?
    给曾经是phper的程序员推荐个学习网站
    详解python2 和 python3的区别
    Python如何进行中文注释
    import方法引入模块详解
    详解python 局部变量与全局变量
    131-19. 删除链表的倒数第N个节点
    65.django中关于跨域访问设置
    130-283. 移动零
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154201.html
Copyright © 2020-2023  润新知