グラフィックコンテキストを深く理解する

8268 ワード

グラフィックコンテキストを深く理解する
CGContextRef
  • 、Quartz 2 Dエンジンを携帯 .これらの情報は、
  • 絵はどこ?すなわち 、可能であれば (CALayer)、 (OS X)、 PDF および .この部分情報 .
  • 何を描きますか?すなわち UIBezierPath(OC)またはCGPathRef(C)オブジェクトであってもよい.描画操作を行うたびに、この情報は自動的にクリアされる.
  • 何で描いたの?すなわち 、線幅、色、様式、CTM、裁断経路等を含む.描画操作を実行するたびに、新しい情報に上書きされなければ、 .
  • //     
          --->
           --->
            , CTM--->
      /            --->
          。
    
    

    コンテキストの取得/作成
    レイヤーコンテキスト(CALayer)
  • drawRect(UIView)、drawInContext:(CALayer)、drawLayer:inContext:(CALayerDelegate)メソッドを呼び出す場合のみ、UIGraphicsGetCurrentContext関数でコンテキストスタック内の現在のコンテキストを取得できます.
  • レイヤーコンテキストは手動で作成できません.

  • ビットマップコンテキスト(bitmap画像)
  • ビットマップコンテキストを作成できます.
  • UIGraphicsBeginImageContextWithOptionsビットマップコンテキストを手動で作成 .
  • 通過UIGraphicsGetImageFromCurrentImageContextビットマップコンテキストから .
  • 使用済み、呼び出しUIGraphicsEndImageContextビットマップコンテキスト .
  • - (void)modifyImageAndDrawSomewhere
    {
        //       
        UIImage *img = [UIImage imageNamed:@"aim"];
        
        /**
             (  )  ,            。
           ,      ,      。
         */
        CGSize targetSize = CGSizeMake(50, 50);
        //          ,       ,   ,          
        UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);
        
        //               (     ),
        //                  
        [img drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)];
        
        //                     (       )
        img = UIGraphicsGetImageFromCurrentImageContext();
        
        /**
                (   )
                          ,          ,
               UIGraphicsPopContext,    UIGraphicsPushContext    。
         */
        UIGraphicsEndImageContext();
        
        //           image view
        self.imageView.image = img; //               ,    drawRect:     
        
        /**
                      ,    。
           ,  UIImagePNGRepresentation() UIImageJPEGRepresentation()           ,
                png    , jpeg   。
         */
        NSData *data = UIImagePNGRepresentation(img);
        [data writeToFile:filePath atomically:YES];
    }
    

    構築パス
  • 経路のデフォルト輪郭と塗りつぶし色は 、輪郭線のデフォルト幅は1 .
  • OC方式で作成されたパスオブジェクトは、グラフィックコンテキストに明示的に追加することなく、直接描画することができる.C方式で作成されるパスオブジェクトは、CGcontextRefのCGContextAddPath関数で追加する必要があります.

  • UIBezierPath ( OC )
  • 作成経路:
  • bezierPath
  • bezierPathWithCGPath:(CGPathRefより作成)
  • bezierPathByReversingPath(逆方向描画経路)
  • bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:のうち開始角度と終了角度は1つの円の中の位置で表します.
  • 3時:0 PI/2 PI
  • 6時:1/2 PI
  • 9時:PI
  • 12時:3/2 PI
  • //  0 PI  ,   PI
    //        ,       
    //        ,       
    
  • 座標系が異なるためCGContextAddArc()関数 その他は同じ.
  • bezierPathWithRoundedRect:cornerRadius:ではフィレット半径を設定できますconer radius.なお、この値が 2/3以上の場合、矩形は となる.(矩形のみ正方形)
  • サブパス追加:
  • closePath
  • removeAllPoints
  • appendPath:(別のパスの相手をつなぐ)
  • コンテキスト状態の設定:
  • usesEvenOddFillRule(パリティルール使用)
  • 描画経路:
  • fill / stroke(呼び出すと、描画前に現在のコンテキストが自動的に保存され、操作が完了したら前の状態に戻す)
  • クリックテスト:
  • containsPoint:(ある点が経路「内部」にあるかどうか)
  • empty(経路に有効要素が含まれているかどうか)

  • CGPathRef ( C )
  • 作成経路:
  • CGPathCreateMutable
  • CGPathCreateCopy
  • CGPathCreateMutableCopy
  • その他のジオメトリパス.
  • サブパス追加:
  • CGPathAddArcToPoint
  • CGPathAddEllipseInRect
  • その他の関数:
  • CGPathCloseSubpath(サブパスを閉じる)
  • CTM(Current Transformation Matrix)
  • 使用 .( また 表示装置へのマッピングも担当)
  • 現在グラフィックコンテキストが作成された後、1つ 同時に定義され、すべての描画操作が 行われる.
  • の対応関係はCTMが決定する.CTMの値を変更すると、コンテンツ ビュー後に歪みが発生します.
  • ビュー座標系は 変わらない.CTMは、描画座標系の を中心に、回転、スケーリング、パン等の操作を行い、その後、ビューに投射する.
  • CTMが有効になるタイミングに注意し、例えば、使用CGContextAddPathコンテキストにパスを追加する場合、Quartz会 CTM .サンプルコードは、
  • - (void)drawRect:(CGRect)rect
    {
        //           
        CGMutablePathRef path = CGPathCreateMutable();
        
        //       
        CGPathMoveToPoint(path, NULL, 100, 100);
        //      
        CGPathAddLineToPoint(path, NULL, 200, 200);
        
        
        //        
        CGContextRef ctx = UIGraphicsGetCurrentContext();
    
        /**
         1.           ,  ,                      ,
               。
         */
        CGContextRotateCTM(ctx, M_PI_4 * 0.5);
        
        /**
         2.             ,  ,                      ,
               。
         */
        CGContextTranslateCTM(ctx, 30, 30);
        
        //          
        CGContextAddPath(ctx, path);
        
        /**
        3.                ,         。
         */
        CGContextScaleCTM(ctx, 0.5, 4);
    
        
        //          
        CGContextSetLineWidth(ctx, 10);
        CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
        
        //          
        CGContextStrokePath(ctx);
        
        /**
                 ,
         CF      ARC  。
                              
         */
        CFBridgingRelease(path); //  CGPathRelease(path)    CFRelease(path)
        
    }
    

    カットパス
  • グラフィックコンテキスト定義用 .
  • 裁断経路として使用:
  • addClip: (UIBezierPath)
  • CGContextClip (CGContextRef)
  • クリッピングパスとして使用されると、コンテキストの現在のパス属性がクリアされます.
  • コンテキストの状態情報として、クリッピングパスはクリアされないので、この属性を現在のパスで更新するたびに、現在のパスが重畳され、新しいクリッピングパスが生成される.
  • 新たに生成されたパスについては、描画操作はその内部領域のみで行われる.
  • 内部領域に属するか否かを判断する場合は、使用するしかないNone-Zero Winding Number Rule.
  • 文書の使用Even-Odd Fill Rule2つの方法の解釈 :
  • usesEvenOddFillRule (UIBezierPath)
  • CGContextEOClip (CGContextRef)

  • The function uses the even-odd rule to calculate the intersection of the current path with the current clipping path. Quartz then uses the path resulting from the intersection as the new current clipping path for subsequent painting operations.
  • :現在経路のサブ経路間でEven-Odd Fill Ruleに従って裁断する.得られた経路をNone-Zero Winding Number Rule現在Clipping Pathとともに裁断する.得られた .
  • 総合裁断と経路描画の一例:
  • /**
         ,           ,       
     */
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        //        
        CGFloat fullRadius = self.imageView.bounds.size.width * 0.5;
        CGPoint center = CGPointMake(CGRectGetMidX(self.imageView.bounds), CGRectGetMidY(self.imageView.bounds));
        
        //       
        UIImage *img = [UIImage imageNamed:@"bus-ticket"];
        
        //          
        UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, 0);
        
        /**
         1.       
         2.       ,        
         3.     ,           ,            
         */
        //     
        UIBezierPath *outside = [UIBezierPath bezierPathWithArcCenter:center radius:fullRadius - 5 startAngle:0 endAngle:2 * M_PI clockwise:YES];
        outside.lineWidth = 10;
        [outside stroke];
        
        //     
        UIBezierPath *clip = [UIBezierPath bezierPathWithArcCenter:center radius:fullRadius - 10 startAngle:0 endAngle:2 * M_PI clockwise:YES];
        [clip addClip];
        
        //     
        [img drawInRect:CGRectMake(10, 10, self.imageView.bounds.size.width - 20, self.imageView.bounds.size.height - 20)];
        
        //     
        img = UIGraphicsGetImageFromCurrentImageContext();
        
        self.imageView.image = img;
        
        /**
                  
         */
        UIImageWriteToSavedPhotosAlbum(img, NULL, NULL, NULL);
    }