美文网首页
CoreGraphics框架

CoreGraphics框架

作者: 宙斯YY | 来源:发表于2017-12-12 16:27 被阅读35次

    1.介绍

    Quartz2D是二维绘图引擎,支持iOS,macOS
    在iOS中,体现为CoreGraphics框架

    2.作用

    绘制图形
    绘制文字
    绘制/生成图片
    读取/生成pdf
    截图/裁剪图片
    自定义UI控件(手势解锁,统计图)
    CGContextRef图形上下文的作用,保存绘制信息,决定输出目标(PDF,Bitmap,显示器窗口)

    Quartz2D提供了几种类型的Context
    Bitmap Graphics Context
    PDF Graphics Context
    Window Graphics Context
    Layer Graphics Context
    Printer Graphics Context

    3.iOS中通过继承UIView重写drawRect可以直接获取到Context

    -(void)drawRect:(CGRect)rect
    {
    //rect->bounds,rect指的是该view的bounds
    }
    

    4.实现基本图形,文本以及UIImage的绘制

    @interface ZSView()
    
    @property(nonatomic,strong) UIImageView * bgImg;
    
    @end
    
    @implementation ZSView
    
    -(instancetype)initWithFrame:(CGRect)frame
    {
        if(self = [super initWithFrame:frame])
        {
            self.bgImg=[[UIImageView alloc]initWithFrame:CGRectZero];
            
            [self addSubview:self.bgImg];
        }
        return self;;
    }
    
    
    //UI绘制的优化
    -(void)draw
    {
        //异步计算UI控件的颜色文字图片大小尺寸数据,然后在主线程上全部渲染到图片上
        CGRect rect = self.bounds;
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
            CGPoint point = CGPointMake(150, 150);
            UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
            CGContextRef ctx = UIGraphicsGetCurrentContext();
            CGContextSetRGBFillColor(ctx, 0.5, 0.5, 0.5, 1);
            CGContextFillRect(ctx, CGRectMake(0, 0, 200, 200));
            NSMutableDictionary * dict =[NSMutableDictionary dictionary];
            [dict setObject:[UIFont systemFontOfSize:15] forKey:NSFontAttributeName];
            [dict setObject:[UIColor redColor] forKey:NSForegroundColorAttributeName];
            [@"内容区域" drawInRect:CGRectMake(0, 0, 200, 200) withAttributes:dict];
            
            [[UIImage imageNamed:@"release_driver"] drawAtPoint:point];
            UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            //CGContextRelease(ctx);
            
            dispatch_async(dispatch_get_main_queue(), ^{
               
                self.bgImg.frame=rect;
                self.bgImg.image=temp;
            });
    
        });
        
    }
    
    //对于绘制出的图片进行点击区域设置
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        CGPoint location = [[touches anyObject] locationInView:self];
        
        CGRect frame = CGRectMake(0, 0, 200, 200);
        
        if (CGRectContainsPoint(frame, location)) {
            
            NSLog(@"点击");
        }
        
    }
    
    -(void)drawRect:(CGRect)rect
    {
        
        /*绘制图形*/
        //1.绘制直线
        //[self drawLine];
        
        //2.绘制曲线
        //[self drawCurve];
        
        //3,绘制圆形
        //[self drawCircle];
        
        //4.绘制不规则路径
        //[self drawPath];
        
        /*绘制控件*/
        //1.绘制文字
        //[self drawText];
        
        //2.绘制图片
        //[self drawImage];
        
        //3.绘制Rect空间
        //[self drawRect];
        
    }
    
    #pragma mark - 绘制Rect空间
    -(void)drawRect
    {
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        
        CGRect rect = CGRectMake(0, 0, 300, 100);
        
        CGContextSetRGBFillColor(ctx, 0, 1.0, 0, 1);//设置填充色
        
        CGContextFillRect(ctx, rect);
        
        CGContextRelease(ctx);
    }
    
    #pragma mark - 绘制图片
    -(void)drawImage
    {
        
        //第一种方式
        CGPoint point = CGPointMake(100, 100);
        [[UIImage imageNamed:@"release_driver"] drawAtPoint:point];
     
        //第二种方式
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        UIImage * img = [UIImage imageNamed:@"release_driver"];
        //CGContextTranslateCTM(ctx,0.0f,self.frame.size.height);
        //CGContextScaleCTM(ctx,1.0,-1.0);
        CGContextDrawImage(ctx,CGRectMake(50,50, img.size.width, img.size.height), [img CGImage]);
        
        CGContextRelease(ctx);
        
    }
    
    #pragma mark - 绘制文字
    -(void)drawText
    {
        NSDictionary * dict=@{NSFontAttributeName:[UIFont systemFontOfSize:18],NSForegroundColorAttributeName:[UIColor orangeColor],NSStrokeColorAttributeName:[UIColor blueColor],NSStrokeWidthAttributeName:@2};
        [@"绘制文字" drawInRect:CGRectMake(10, 10, 50, 50) withAttributes:dict];
    /*也可以通过Lable实现
        UILabel * label=[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 100, 50)];
        NSString * text=@"绘制文字";
        [self.testview addSubview:label];
        NSDictionary * dict=@{NSFontAttributeName:[UIFont   systemFontOfSize:18],NSForegroundColorAttributeName:[UIColor orangeColor],NSStrokeColorAttributeName:[UIColor blueColor],NSStrokeWidthAttributeName:@2};
        NSAttributedString * str=[[NSAttributedString alloc]initWithString:text attributes:dict];
        label.attributedText=str;
    */
    }
    
    #pragma mark - 绘制路径
    -(void)drawPath
    {
        //1.获取上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        //2.创建路径
        CGMutablePathRef path = CGPathCreateMutable();//创建路径
        CGPathMoveToPoint(path, nil, 100, 100);//移动到指定位置(设置路径起点)
        CGPathAddLineToPoint(path, nil, 200, 300);//绘制直线(从起始位置开始)
        CGPathAddLineToPoint(path, nil,50, 100);//绘制直线(从起始位置开始)
        CGContextAddPath(context, path);//把路径添加到上下文(画布)中
        
        //3.设置图形上下文状态属性
        CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//设置笔触颜色
        CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//设置填充色
        CGContextSetLineWidth(context, 5.0);//设置线条宽度
        //4.绘制路径
        CGContextDrawPath(context, kCGPathStroke);//最后一个参数是填充类型
        
        //5.释放路径和上下文资源
        CGPathRelease(path);
        CGContextRelease(context);
    }
    
    #pragma mark - 绘制曲线
    -(void)drawCurve
    {
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        CGContextMoveToPoint(context, 100, 100);
        CGContextAddCurveToPoint(context, 200, 0, 300, 100, 100, 100);
        
        CGContextSetRGBStrokeColor(context, 0.5, 0.4, 0.3, 1);
        CGContextSetRGBFillColor(context, 0.3, 0.4, 0.5, 1);
        CGContextSetLineWidth(context, 1.0);
        
        CGContextDrawPath(context, kCGPathStroke);
    
        CGContextRelease(context);
    }
    
    #pragma mark - 绘制圆形
    -(void)drawCircle
    {
        //1.获取上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        //2.创建圆形路径
        CGContextAddArc(context, 100, 100, 50, 0, 2*M_PI, 0);
        //3.设置上下文属性
        CGContextSetRGBStrokeColor(context, 0.5, 0.4, 0.3, 1);//设置笔触颜色
        CGContextSetRGBFillColor(context, 0.3, 0.4, 0.5, 1);//设置填充色
        CGContextSetLineWidth(context, 1.0);//设置线条宽度
        //4.绘制路径
        CGContextDrawPath(context, kCGPathFill);
        //5.释放资源
        CGContextRelease(context);
    }
    
    #pragma mark - 绘制直线
    -(void)drawLine
    {
        //1.获取上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        //2.创建路径
        CGContextMoveToPoint(context, 100, 100);
        CGContextAddLineToPoint(context, 200, 200);
        
        //3.设置图形上下文状态属性
        CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//设置笔触颜色
        CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//设置填充色
        CGContextSetLineWidth(context, 5.0);//设置线条宽度
        CGContextSetLineCap(context, kCGLineCapButt);//设置顶点样式
        CGContextSetLineJoin(context, kCGLineJoinMiter);//设置连接点样式
        CGFloat lengths[5] = {18,9,6,3,1};
        CGContextSetLineDash(context, 0, lengths, 5);
        CGContextSetShadowWithColor(context, CGSizeMake(2, 2), 0, [UIColor blueColor].CGColor);
        
        //4.绘制路径
        CGContextDrawPath(context, kCGPathFillStroke);//最后一个参数是填充类型
        
        //5.释放上下文资源
        CGContextRelease(context);
    }
    
    #pragma mark - 绘制直线(第二种方式),使用UIBezierPath替代CGPathRef
    -(void)drawLine2
    {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetLineWidth(context, 3);
        [[UIColor blackColor]setStroke];
        
        //UIBezierPath是对CGPathRef的面向对象封装
        UIBezierPath * path=[UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(50,50)];
        CGContextAddPath(context, path.CGPath);
       
        CGContextStrokePath(context);
    }
    
    #pragma mark - 绘制直线(第三种方式),直接使用UIBezierPath
    -(void)drawLine3
    {
        UIBezierPath * path=[UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 30, 30)];
        //内部帮我们实现获取CGContextRef和设置Path的功能
        [path stroke];
    }
    

    4.Context上下文状态栈

    Context的状态(颜色,笔宽等属性)可以保存在栈中,可以保存多个状态到状态栈,但是只能取栈顶状态到上下文中使用。
    绘制两条不同颜色的线条

    CGContextRef context = UIGraphicsGetCurrentContext();
        //设置上下文状态
        CGContextSetLineWidth(context, 3);
        [[UIColor blackColor]setStroke];
        //把该上下文状态存储到栈中(栈中1元素,这次状态位于栈顶)
        CGContextSaveGState(context);
        
        //再次设置上下文状态(覆盖当前上下文状态)
        CGContextSetLineWidth(context, 3);
        [[UIColor redColor]setStroke];
        //把该上下文状态存储到栈中(栈中2元素,这次状态位于栈顶)
        CGContextSaveGState(context);
        
        //使用当前上下文状态描绘路径(Red)
        UIBezierPath * path=[UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(50,50)];
        CGContextAddPath(context, path.CGPath);
        CGContextStrokePath(context);
        
        
        UIBezierPath * path2=[UIBezierPath bezierPath];
        [path2 moveToPoint:CGPointMake(80, 80)];
        [path2 addLineToPoint:CGPointMake(80,20)];
        CGContextAddPath(context, path2.CGPath);
        //把(Black)状态从栈取出到栈顶并设置上下文状态
        CGContextRestoreGState(context);
        CGContextRestoreGState(context);
        CGContextStrokePath(context);
    

    5.应用

    a.合成图片(给图片加水印)

        //使用BitmapContext上下文
        UIImage * bgimage=[UIImage imageNamed:@"bgimg"];
        UIImage * logo=[UIImage imageNamed:@"logo"];
        //开始上下文
        UIGraphicsBeginImageContext(bgimage.size);
        //把两张图片渲染到上下文中
        [bgimage drawAtPoint:CGPointZero];
        [logo drawAtPoint:CGPointMake(50, 50)];
        //合成图像
        UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
        //结束上下文绘制
        UIGraphicsEndImageContext();
        UIImageView * imgV=[[UIImageView alloc]initWithFrame:self.bounds];
        [self addSubview:imgV];
        imgV.image=newImage;
        
        /*更好的方式是进行异步绘制
        UIImageView * imgV=[[UIImageView alloc]initWithFrame:self.bounds];
        [self addSubview:imgV];
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            UIImage * bgimage=[UIImage imageNamed:@"bgimg"];
            UIImage * logo=[UIImage imageNamed:@"logo"];
            UIGraphicsBeginImageContext(bgimage.size);
            [bgimage drawAtPoint:CGPointZero];
            [logo drawAtPoint:CGPointMake(50, 50)];
            UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            dispatch_async(dispatch_get_main_queue(), ^{
                imgV.image=newImage;
            });
        });
        */
    

    b.裁剪圆形图片

    UIImage * bgimage=[UIImage imageNamed:@"bgimg"];
        UIGraphicsBeginImageContext(bgimage.size);
        //设置裁剪区域
        UIBezierPath * path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, bgimage.size.width, bgimage.size.height)];
        [path addClip];
       //把图片渲染到上下文中
        [bgimage drawAtPoint:CGPointZero];
        UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        UIImageView * imgV=[[UIImageView alloc]initWithFrame:self.bounds];
        [self addSubview:imgV];
        imgV.image=newImage;
    

    c.裁剪带边框的圆形图片

    UIImage * bgimage=[UIImage imageNamed:@"bgimg"];
        CGSize contextSize=CGSizeMake(bgimage.size.width+20, bgimage.size.height+20);
        //设置上下文大小比图片宽度大10
        UIGraphicsBeginImageContext(contextSize);
        //填充一个橙色的圆形
        UIBezierPath * path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, contextSize.width, contextSize.height)];
        [[UIColor orangeColor]set];
        [path fill];
        //设置裁剪区域
        UIBezierPath * path2=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(10, 10, bgimage.size.width, bgimage.size.height)];
        [path2 addClip];
        //把图片渲染到上下文中
        [bgimage drawAtPoint:CGPointMake(10, 10)];
        UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        UIImageView * imgV=[[UIImageView alloc]initWithFrame:self.bounds];
        [self addSubview:imgV];
        imgV.image=newImage;
    

    d.截屏

        /*
          第二个参数表示图像上下文是不是要透明-YES不透明。
          [UIScreen mainScreen].scale是像素和点的一个桥接,在iOS-UIKit中使用点作为单位,其实内部就是像素*scale的结果
          [UIScreen mainScreen].scale-iphone8-2
          [UIScreen mainScreen].scale-iphone8p-3
          值得注意的是CoreGraphics框架使用的是像素作为单位
        */
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, [UIScreen mainScreen].scale);
        //UIGraphicsBeginImageContext(self.bounds.size);
        CGContextRef ctx=UIGraphicsGetCurrentContext();
        //把Layer被渲染到CGContext上
        [self.layer renderInContext:ctx];
        UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
        NSData * data=UIImagePNGRepresentation(newImage);
        [data writeToFile:@"/Users/zhousiyang/Downloads/1.png" atomically:YES];
        UIGraphicsEndImageContext();
    

    e.拖拽截图

    @interface TestViewController ()
    {
        UIView * maskView;
        CGPoint startP;
    }
    @property (weak, nonatomic) IBOutlet UIImageView *bgImgV;
    
    @end
    
    @implementation TestViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIPanGestureRecognizer * pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [self.bgImgV addGestureRecognizer:pan];
    }
    
    -(void)pan:(UIPanGestureRecognizer*)pan
    {
        
        if(pan.state==UIGestureRecognizerStateBegan)
        {
            startP=[pan locationInView:self.bgImgV];
        }
        if(pan.state==UIGestureRecognizerStateChanged)
        {
            CGPoint panP=[pan translationInView:self.bgImgV];
            CGFloat x=startP.x;
            CGFloat y=startP.y;
            CGFloat w=panP.x;
            CGFloat h=panP.y;
            if(maskView==nil)
            {
                maskView=[[UIView alloc]initWithFrame:CGRectMake(x, y, w, h)];
                maskView.backgroundColor=[UIColor colorWithWhite:0.5 alpha:0.5];
                [self.bgImgV addSubview:maskView];
            }else
            {
                maskView.frame=CGRectMake(x, y, w, h);
            }
        }
        if(pan.state==UIGestureRecognizerStateEnded)
        {
            [self screencapture];
            [maskView removeFromSuperview];
            maskView=nil;
            
        }
    }
    
    
    -(void)screencapture
    {
        //1.开启图片上下文(大小就是被截图View大小)
        UIGraphicsBeginImageContextWithOptions(self.bgImgV.bounds.size, YES, 0.0);
        NSLog(@"1%@",NSStringFromCGSize(self.bgImgV.bounds.size));
        //2.设置Clip区域
        UIBezierPath * path=[UIBezierPath bezierPathWithRect:CGRectMake(maskView.frame.origin.x, maskView.frame.origin.y, maskView.frame.size.width, maskView.frame.size.height)];
        [path addClip];
        //或者UIRectClip(maskView.frame);
        CGContextRef ctx=UIGraphicsGetCurrentContext();
        //3.把图片渲染到上下文中
        [self.bgImgV.layer renderInContext:ctx];
        //4.获取上下文中的图片(大小图片上下文大小-被截图View大小)
        UIImage * newImage=UIGraphicsGetImageFromCurrentImageContext();
        NSLog(@"2%@",NSStringFromCGSize(newImage.size));
        UIGraphicsEndImageContext();
        self.bgImgV.image=newImage;
    }
    
    

    f.手势解锁
    思路:
    布局一个有9个按钮固定大小View的解锁界面,界面外边不响应滑动事件;(事件响应
    滑动到按钮范围内,按钮变为选中状态,把滑到过的按钮添加到数组中;(touches...
    把数组中的按钮按照中心点连接绘制起来,末端加一个最后绘制的点;(drawRect,UIBezierPath
    绘制完毕保存按钮的tag;(touchesEnd

    @interface LockView()
    {
        BOOL isEnd;
        CGPoint curP;
        NSMutableArray * btnArr;
    }
    @end
    
    @implementation LockView
    
    -(void)awakeFromNib
    {
        [super awakeFromNib];
        
        btnArr=[NSMutableArray array];
        
        for (int i=0; i<9; i++) {
            UIButton * btn=[[UIButton alloc]init];
            [btn setUserInteractionEnabled:NO];
            btn.tag=i;
            btn.backgroundColor=[UIColor colorWithWhite:0.5 alpha:0.5];
            btn.titleLabel.font=[UIFont systemFontOfSize:13];
            [btn setTitle:[NSString stringWithFormat:@"%d未选中",i] forState:UIControlStateNormal];
            [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            [btn setTitle:[NSString stringWithFormat:@"%d选中",i] forState:UIControlStateSelected];
            [btn setTitleColor:[UIColor blueColor] forState:UIControlStateSelected];
            [self addSubview:btn];
        }
    }
    
    -(void)layoutSubviews
    {
        float border=(self.frame.size.width-150)/4;
        for (int i=0; i<9; i++) {
            float x=border+(border+50)*(i%3);
            float y=border+(border+50)*(i/3);
            float w=50;
            float h=50;
            UIButton * btn=self.subviews[i];
            btn.frame=CGRectMake(x, y, w, h);
        }
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        //点击在按钮范围,按钮被选中
        UITouch * touch=[touches anyObject];
        CGPoint startP=[touch locationInView:self];
        for (UIButton * btn in self.subviews) {
            if(CGRectContainsPoint(btn.frame, startP))
            {
                [btnArr addObject:btn];
                btn.selected=YES;
                break;
            }
        }
    }
    
    -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        //滑动在按钮范围,按钮被选中
        UITouch * touch=[touches anyObject];
        curP=[touch locationInView:self];
        for (UIButton * btn in self.subviews) {
            if(CGRectContainsPoint(btn.frame,curP)&&btn.selected==NO)
            {
                [btnArr addObject:btn];
                btn.selected=YES;
                break;
            }
        }
        //调用drawRect绘制线条
        [self setNeedsDisplay];
    }
    
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        isEnd=YES;
        [self setNeedsDisplay];
    }
    
    -(void)drawRect:(CGRect)rect
    {
        if(btnArr.count>0)
        {
            CGContextRef ctx=UIGraphicsGetCurrentContext();
            [[UIColor redColor]set];
            CGContextSetLineJoin(ctx, kCGLineJoinRound);
            CGContextSetLineWidth(ctx, 10);
            UIBezierPath * path=[UIBezierPath bezierPath];
            for (int i=0; i<btnArr.count; i++) {
                UIButton * btn=btnArr[i];
                if(i==0)
                {
                    [path moveToPoint:btn.center];
                }else
                {
                    [path addLineToPoint:btn.center];
                }
            }
            if(!isEnd)
            {
                [path addLineToPoint:curP];
            }
            
            CGContextAddPath(ctx, path.CGPath);
            CGContextStrokePath(ctx);
    
           /*
              直接使用UIBezierPath
            [[UIColor redColor]set];
            UIBezierPath * path=[UIBezierPath bezierPath];
            path.lineWidth=10;
            path.lineJoinStyle=kCGLineJoinRound;
            for (int i=0; i<btnArr.count; i++) {
                UIButton * btn=btnArr[i];
                if(i==0)
                {
                    [path moveToPoint:btn.center];
                }else
                {
                    [path addLineToPoint:btn.center];
                }
            }
            if(!isEnd)
            {
                [path addLineToPoint:curP];
            }
            [path stroke];
            */
        }
    }
    

    g.画板
    思路:
    手滑过的路径可以通过手势或者touch...方法监听。
    绘制:每条路径通过UIBezierPath,所有路径保存在数组中,进行drawRect重绘
    颜色和线宽:通过UIBezierPath属性修改,颜色通过上下文修改
    撤销:删除数组末位元素,重绘
    清屏:删除数组全部元素,重绘
    橡皮擦:使用画板底色画笔绘制
    优化:通过 [self.drawview setNeedsDisplay]以及drawRect重绘(CPU),如果绘制很多很多线条会导致内存和CPU暴增,思路是把绘制的Path变成一张图片,在手势移动的时候绘制上去。

        CAShapeLayer * shaperLayer=[[CAShapeLayer alloc]init];
        shaperLayer.path=path.CGPath;
        [self.view.layer addSublayer:shaperLayer];
    

    h.抽奖转盘
    关键点:
    布局UI,键盘上每个小格子如果使用UIButton,要设置anchorPoint=(0.5,1),position=背景View.center。
    旋转动画的交互,使用UIView动画,不能使用CA核心动画。
    从大切图截取部分图片的问题,使用CoreGrapyics框架问题。

        UIImage * img=[UIImage imageNamed:@""];
        float w=img.size.width;
        float h=img.size.height;
        //CoreGraphyics框架是像素点为单位,截取时必须乘以[UIScreen mainScreen].scale
        CGImageCreateWithImageInRect(img.CGImage, CGRectMake(0, 0, w*[UIScreen mainScreen].scale, h*[UIScreen mainScreen].scale));
    

    相关文章

      网友评论

          本文标题:CoreGraphics框架

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