繪圖詳解(轉摘)

來源:互聯網
上載者:User

標籤:blog   http   io   ar   color   os   使用   sp   for   

 

Quartz是Mac OS X的Darwin核心之上的繪圖層,有時候也認為是CoreGraphics。共有兩種部分組成Quartz:

Quartz Compositor,合成視窗系統,管理和合成幕後視窗影像來建立Mac OS X使用者介面。

Quartz 2D,是iOS和Mac OS X環境下的二維繪圖引擎。

涉及內容包括:基於路徑的繪圖,透明度繪圖,遮蓋,陰影,透明層,顏色管理,防鋸齒渲染,產生PDF,以及PDF中繼資料相關處理。

14.2 繪製基本幾何圖形

視圖繪製

    在iOS上,所有的繪製,無論是否採用OpenGL、Quartz、UIKit、或者 Core Animation—都發生在UIView對象的地區內。

視圖定義繪製發生的螢幕地區。如果您使用系統提供的視圖,繪製工作會自動得到處理。然而,如果您定義自己的定製視圖,則必須自行提供繪製代碼。

對於使用OpenGL進行繪製的應用程式,一旦建立了渲染表面,就必須使用OpenGL指定的繪製模型。

視圖繪製周期

    描繪系統會調用UIView對象的drawRect:方法,並向它傳入一個包含需要重畫的視圖地區的矩形。觸發視圖更新的動作有如下幾種:

對遮擋您的視圖的其它視圖進行移動或刪除操作。 

將視圖的hidden屬性聲明設定為NO,使其從隱藏狀態變為可見。

將視圖滾出螢幕,然後再重新回到螢幕上。

顯式調用視圖的setNeedsDisplay或者setNeedsDisplayInRect:方法。

setNeedsDisplay是更新整個視圖,

setNeedsDisplayInRect是更新視圖的部分地區。

視圖繪製執行個體FirstQuartz2D

自訂視圖的h檔案

@interface MyView : UIView {    }@end

自訂視圖的m檔案 

@implementation MyView- (void)drawRect:(CGRect)rect {        CGContextRef context = UIGraphicsGetCurrentContext();        CGContextMoveToPoint (context, 75, 10);     CGContextAddLineToPoint (context, 10, 150);     CGContextAddLineToPoint (context, 160, 150);         // Closing the path connects the current point to the start of the current path.    CGContextClosePath(context);    // And stroke the path    [[UIColor blackColor] setStroke];     //CGContextStrokePath(context);    [[UIColor redColor] setFill];     CGContextDrawPath(context, kCGPathFillStroke);    //kCGPathFillStroke,kCGPathFill,kCGPathStroke    }@end

CGContextRef context = UIGraphicsGetCurrentContext();可以獲得圖形上下文。

CGContextMoveToPoint、CGContextAddLineToPoint兩個函數是構建描繪路徑。

CGContextClosePath(context);函數是閉合描繪路徑。

CGContextStrokePath函數是為閉合路徑描邊。

[[UIColor blackColor] setStroke]設定描邊的顏色。

[[UIColor redColor] setFill]設定要填充顏色。

CGContextDrawPath(context, kCGPathFillStroke);設定描繪路徑方式。常用的還有:

kCGPathFill和kCGPathStroke

圖形上下文

  在調用您提供的drawRect:方法之前,視圖對象會自動設定其繪製環境,使您的代碼可以立即進行繪製。作為這些

配置的一部分,UIView對象會為當前繪製環境建立一個圖形上下文(對應於CGContextRef封裝類型)。

  該圖形上下文包含繪製系統執行後續繪製命令所需要的資訊,定義了各種基本的繪製屬性,比如繪製使用的顏色、

裁剪地區、線的寬度及風格資訊、字型資訊、合成選項、以及幾個其它資訊。

繪製路徑

  路徑用於描述由一序列線和Bézier曲線構成的2D幾何形狀。Core Graphics中也有一些用於建立簡單路徑(比如矩形和橢圓形)的便利函數。對於更為複雜的路徑,必須用Core Graphics架構提供的函數自行建立。

  Bézier曲線是法國數學家“貝塞爾”在工作中發現,任何一條曲線都可以通過與它相切的控制線兩端的點的位置來定義。

Bézier曲線

Bézier曲線執行個體BezierCurve

- (void)drawRect:(CGRect)rect {        CGContextRef cgContext = UIGraphicsGetCurrentContext();        //CGContextBeginPath(cgContext);    CGContextMoveToPoint(cgContext, 333, 0);    CGContextAddCurveToPoint(cgContext, 333, 0, 332, 26, 330, 26);    CGContextAddCurveToPoint(cgContext, 330, 26, 299, 20, 299, 17);    CGContextAddLineToPoint(cgContext, 296, 17);    CGContextAddCurveToPoint(cgContext, 296, 17, 296, 19, 291, 19);    CGContextAddLineToPoint(cgContext, 250, 19);    CGContextAddCurveToPoint(cgContext, 250, 19, 241, 24, 238, 19);    CGContextAddCurveToPoint(cgContext, 236, 20, 234, 24, 227, 24);    CGContextAddCurveToPoint(cgContext, 220, 24, 217, 19, 216, 19);    CGContextAddCurveToPoint(cgContext, 214, 20, 211, 22, 207, 20);    CGContextAddCurveToPoint(cgContext, 207, 20, 187, 20, 182, 21);    CGContextAddLineToPoint(cgContext, 100, 45);    CGContextAddLineToPoint(cgContext, 97, 46);    CGContextAddCurveToPoint(cgContext, 97, 46, 86, 71, 64, 72);    CGContextAddCurveToPoint(cgContext, 42, 74, 26, 56, 23, 48);    CGContextAddLineToPoint(cgContext, 9, 47);    CGContextAddCurveToPoint(cgContext, 9, 47, 0, 31, 0, 0);        CGContextStrokePath(cgContext);}
14.3 繪製映像和文本

UIImages的-drawRect:方法繪製映像:

- [UIImage drawAtPoint:(CGPoint)point] 

- [UIImage drawInRect:(CGRect)rect]

- [UIImage drawAsPatternInRect:(CGRect)rect]

NSString的-drawRect:方法繪製文本:  

- [NSString drawAtPoint:(CGPoint)point withFont:(UIFont *)font]

執行個體DrawImage

#import "MyView.h"@implementation MyView- (void)drawRect:(CGRect)rect {        NSString* imagePath = [[NSBundle mainBundle] pathForResource:@"dog" ofType:@"png"];    UIImage* myImageObj = [[UIImage alloc] initWithContentsOfFile:imagePath];    //[myImageObj drawAtPoint:CGPointMake(0, 0)];    [myImageObj drawInRect:CGRectMake(0, 0, 320, 480)];        NSString *s = @"我的小狗";        [s drawAtPoint:CGPointMake(100, 0) withFont:[UIFont systemFontOfSize:34.0]];}@end

寫字執行個體Draw

Dot對象

//--h@interface Dot : NSObject {  CGFloat x;  CGFloat y;}@property(assign) CGFloat x;@property(assign) CGFloat y;@end//--m#import "Dot.h"@implementation Dot@synthesize x;@synthesize y;@end

DrawView.h 

#import <UIKit/UIKit.h>@interface DrawView : UIView {  NSMutableArray *dots;}@property(nonatomic, retain) NSMutableArray *dots;@end

DrawView.m

 

#import "DrawView.h"#import "Dot.h"@implementation DrawView@synthesize dots;- (NSMutableArray *)dots {    if(nil == dots) {        self.dots = [NSMutableArray array];    }    return dots;}//START:code.DrawView.drawRect- (void)drawRect:(CGRect)rect {    CGContextRef ctx = UIGraphicsGetCurrentContext();    CGContextSetFillColorWithColor(ctx, [[UIColor blueColor] CGColor]);    for(Dot *dot in self.dots) {        CGContextAddArc(ctx, dot.x, dot.y, 5.0f, 0.0f, 2.0f * M_PI, YES);        CGContextFillPath(ctx);    }    }//END:code.DrawView.drawRect- (void)dealloc {    self.dots = nil;    [super dealloc];}

drawRect方法中將dots集合中的Dot對象取出,一個一個在螢幕上面畫出來。

CGContextAddArc(ctx, dot.x, dot.y, 5.0f, 0.0f, 2.0f * M_PI, YES);函數是繪製弧形。

CGContextFillPath(ctx);填充路徑。

//START:code.DrawView.touchesBegan- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    UITouch *touch = [touches anyObject];    CGPoint location = [touch locationInView:self];    Dot *dot = [[[Dot alloc] init] autorelease];    dot.x = location.x;    dot.y = location.y;    //[self.dots removeAllObjects];    [self.dots addObject:dot];    [self setNeedsDisplay];}//END:code.DrawView.touchesBegan//START:code.DrawView.touchesMoved- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {    UITouch *touch = [touches anyObject];    CGPoint location = [touch locationInView:self];    Dot *dot = [[[Dot alloc] init] autorelease];    dot.x = location.x;    dot.y = location.y;    [self.dots addObject:dot];    [self setNeedsDisplay];}//END:code.DrawView.touchesMoved

 

14.4 座標

Quartz座標

Quartz技術最開始為Mac OS X系統設計的圖形技術,它的座標原點位於左下角。

UIKit座標

UIKit座標與Quartz不同,原點位於右上方。在iOS中的UIView等控制項都是基於此座標,由於在UIView使用了Quartz座標有時候需要轉換。

座標變換執行個體

MyView.m檔案

#import "MyView.h"@implementation MyView- (void)drawRect:(CGRect)rect {    NSString *path = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];    UIImage *img = [UIImage imageWithContentsOfFile:path];    CGImageRef image = img.CGImage;    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSaveGState(context);        CGRect touchRect = CGRectMake(0, 0, img.size.width, img.size.height);    CGContextDrawImage(context, touchRect, image);      CGContextRestoreGState(context);}@end

 

CGContextSaveGState是將當前圖形狀態要入到圖形堆棧。

CGContextDrawImage(context, touchRect, image)在上下文中繪製圖形。 CGContextRestoreGState回複當前圖形狀態。

14.5 變換

運用變換 

變換(transformation)修改了圖形上下文中繪製圖形的方式。可以通過移動、旋轉或縮放實現變換。

Quartz提供了多種形式的變換,其中主要:CTM(當前變換矩陣)變換和仿射(affine)變換。

CTM(current transformation matrix)變換,這種變換比較簡單,函數有:

CGContextRotateCTM,旋轉座標

CGContextScaleCTM,縮放座標

CGContextTranslateCTM,移動原點

移動變換

CGContextTranslateCTM (myContext, 100, 50)

從對象角度沿著x軸正向移動100單位,沿著y軸正向移動50單位。

旋轉變換

static inline double radians (double degrees) {return degrees * M_PI/180;}

CGContextRotateCTM (myContext, radians(–45.));

從對象角度:

在Quartz座標下正數為逆時針旋轉,負數為順時針旋轉。

在UIKit座標下正數為順時針旋轉,負數為逆時針旋轉。

縮放變換

CGContextScaleCTM (myContext, .5, .75);

從對象角度:所有x座標縮小0.5,所有y座標縮小0.75。

修改MyView.m檔案

#import "MyView.h"@implementation MyView- (void)drawRect:(CGRect)rect {    NSString *path = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];    UIImage *img = [UIImage imageWithContentsOfFile:path];    CGImageRef image = img.CGImage;    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSaveGState(context);        CGContextRotateCTM(context, M_PI);    CGContextTranslateCTM(context, -img.size.width, -img.size.height);        CGRect touchRect = CGRectMake(0, 0, img.size.width, img.size.height);    CGContextDrawImage(context, touchRect, image);      CGContextRestoreGState(context);}@end

 

仿射(affine)變換

仿射(affine)變換也是一種直角座標變換,重

用變換,經過多次變換(多次的矩陣相乘),

每一種變換都可以用矩陣表示,通過多次矩陣

相乘得到最後結果。仿射變換函數:

    CGAffineMakeRotation,建立旋轉矩陣仿射對象

    CGAffineMakeScale,建立縮放矩陣仿射對象

    CGAffineMakeTranslation,建立移動矩陣仿射對象

    CGAffineTransformRotate,旋轉矩陣仿射對象

    CGAffineTransformScale,縮放矩陣仿射對象

    CGAffineTransformTranslate,移動矩陣仿射對象

    CGContextConcatCTM,串連到CTM變換

使用仿射變換MyView.m

#import "MyView.h"@implementation MyView- (void)drawRect:(CGRect)rect {    NSString *path = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];    UIImage *img = [UIImage imageWithContentsOfFile:path];    CGImageRef image = img.CGImage;    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSaveGState(context);        CGAffineTransform myAffine = CGAffineTransformMakeRotation(M_PI);     myAffine = CGAffineTransformTranslate(myAffine, -img.size.width, -img.size.height);     CGContextConcatCTM(context, myAffine);        CGContextRotateCTM(context, M_PI);    CGContextTranslateCTM(context, -img.size.width, -img.size.height);        CGRect touchRect = CGRectMake(0, 0, img.size.width, img.size.height);    CGContextDrawImage(context, touchRect, image);      CGContextRestoreGState(context);}@end

 

14.6 映像拾取器

映像拾取器(Image Picker)是可以協助你從圖片庫中選取圖片,也可以捕獲照相機圖片。

PhotoViewViewController.h

//START:code.PhotoViewController.h@interface PhotoViewViewController : UIViewController<UIImagePickerControllerDelegate> {    UIImageView *imageView;    UIImagePickerController *imagePicker;}@property(nonatomic, retain) IBOutlet UIImageView *imageView;@property(nonatomic, retain) IBOutlet UIImagePickerController *imagePicker;@end//END:code.PhotoViewController.h

 

需要實現UIImagePickerControllerDelegate協議。

需要定義UIImagePickerController控制器成員變數。

PhotoViewViewController.m

#import "PhotoViewViewController.h"@implementation PhotoViewViewController@synthesize imageView;@synthesize imagePicker;//START:code.PhotoViewController.touchesEnded:withEvent:- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {    if([[touches anyObject] tapCount] > 1) {        // bring up image grabber        if([UIImagePickerController isSourceTypeAvailable:            UIImagePickerControllerSourceTypeCamera]) {            self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;        } else {            self.imagePicker.sourceType =            UIImagePickerControllerSourceTypePhotoLibrary;        }        //self.imagePicker.allowsImageEditing = YES; //iOS 3之前        self.imagePicker.allowsEditing = YES;                 [self presentModalViewController:self.imagePicker animated:YES];     }}//END:code.PhotoViewController.touchesEnded:withEvent:

 

映像選取器的sourceType屬性有:

UIImagePickerControllerSourceTypePhotoLibrary,圖片來源於“相簿”

UIImagePickerControllerSourceTypeCamera,來源於相機

UIImagePickerControllerSourceTypeSavedPhotosAlbum,來源於“相機菲林”。

PhotoViewViewController.m

//START:code.PhotoViewController.didFinish- (void)imagePickerController:(UIImagePickerController *)pickerdidFinishPickingMediaWithInfo:(NSDictionary *)info {    imageView.image = [info objectForKey:UIImagePickerControllerEditedImage];     [self dismissModalViewControllerAnimated:YES]; }//END:code.PhotoViewController.didFinish//START:code.PhotoViewController.didCancel- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {    [self.imagePicker dismissModalViewControllerAnimated:YES];}//END:code.PhotoViewController.didCancel- (void)dealloc {    self.imageView = nil;    self.imagePicker = nil;    [super dealloc];}

 

imagePickerController:didFinishPickingMediaWithInfo:委託實現方法,當選擇完成時候調用。

imageView.image = [info objectForKey:UIImagePickerControllerEditedImage];語句可以從圖片拾取器中獲得一個Image對象。

imagePickerControllerDidCancel:是委託實現方法當點擊取消時候調用。

繪圖詳解(轉摘)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.