天天看點

iOS - 圖形上下文使用

實作圓形圖檔的裁切有多種方法,可以直接設定

layer.cornerRadius

,但這樣會造成離屏渲染,耗費記憶體。在此不詳述離屏渲染,想看的戳進去吧:iOS離屏渲染研究

先來個簡單例子:實作圓形圖檔的裁切

- (UIImage *)circleImage:(UIImage *)image {

    if (!image) return nil;

    // 開始上下文,下面不使用時一定要關閉,從上下文棧中移除
    UIGraphicsBeginImageContextWithOptions(image.size, NO
                                           ,[UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // 添加鑲邊
    CGContextSetLineWidth(context, );
    CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);

    //裁切
    CGRect rect = CGRectMake(, , image.size.width, image.size.height);
    CGContextAddEllipseInRect(context, rect);
    CGContextClip(context);

    // 在圓區内畫出image原圖
    [image drawInRect:rect];

    // 圍繞目前路徑畫一條線,鑲邊線,注意在調用strokePath之前必須先添加線,fillPath也一樣要先添加線才可操作
    CGContextAddEllipseInRect(context, rect);
    CGContextStrokePath(context); 

    //從上下文環境中擷取切好的圖檔
    UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();

    // 使用了beginImgacontext需要關閉上下文 并從上下文棧中移除
    UIGraphicsEndImageContext();

    return newImg;

}
           

調用方式如:

UIImage *image = [UIImage imageNamed:@"welcome.png"];

    UIImageView *imagView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
    imagView.image = [self circleImage:image];
    [self.view addSubview:imagView];
           

一直對上下文操作視圖感到好奇,這下便檢視部分文檔資料,簡單翻譯了下,如有不合理歡迎指正:

傳回:
    目前的圖形上下文   

描述: 
    預設情況下目前的圖形上下文為nil,首先調用到它的是drawRect:方法,
    視圖控件将一個有效的上下文壓到一個棧中,使其成為目前上下文, 如果你不使用一個控件對象來進行繪畫, 
    那麼你便需要手動将一個有效的上下文壓到棧中通過使用UIGraphicsPushContext函數   

 這個方法可能從你app的任何線程中調用。
           
使一個特殊的上下文成為目前的上下文    

描述: 你可以使用這個功能去儲存之前的圖形上下文狀态,并且使一個上下文成為目前的上下文,
使用這個方法需要配對使用UIGraphicsPopContext方法 這個方法可能從你的app的任何線程中調用
           
從上下文棧中移除目前的上下文,恢複使用之前的上下文
           
UIGraphicsBeginImageContext(size)
           
建立一個基于位圖的圖形上下文,并使之成為目前的上下文

parameters:  
     size: 新位圖上下文的尺寸,這個代表了通過        UIGraphicsGetImageFromCurrentImageContext方法傳回的圖檔的尺寸    

 描述: 
     這個方法相當于調用了UIGraphicsBeginImageContextWithOptions方法, 
     并且opaque參數設定為NO,并且一個scale參數為1.0 這個方法可能從你的app的任何線程中調用
           
UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)
           
建立一個基于位圖的圖形上下文同時附帶有相應的選擇

parameters:
    size: 新的位圖上下文的尺寸(以點來作為量算機關)。 
    這展現在在UIGraphicsGetImageFromCurrentImageContext函數傳回的圖檔的尺寸。 
    為了得到位圖的的像素尺寸,你必須以寬度和高度乘以scale參數。

    opaque: 一個BOOL值的标志标志着位圖是否為半透明。如果你知道位圖是完全的不透明, 
    指派YES去忽略掉alpha通道并且優化位圖的存儲空間。 
    指派為NO意味着位圖必須要包含alpha通道去掌握着部分的透明像素。

    scale: 這個scale元素去應用到位圖中,如果你将其設定為0.0f, 
    那麼就會以系統裝置螢幕尺寸的的scale作為标準。

讨論:
    你可以使用這個方法去配置繪畫環境送出到位圖中。 
    這個位圖是ARGB32-bit整型像素格式使用主byte次序。如果opaque參數設定為YES, 
    這個alpha通道被忽略并且被認為是完全不透明(kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrer32Host)。 
    不然每一個像素使用premultipledARGB格式(kCGImageAlphaPremultipledFirst | kCGBitmapByteOrder32Host).

這個環境同時使用了預設的UIKit視圖的坐标系統,它的原點是在左上角, 
正軸是原點向下及向右。這個提供到的scale因為同樣應用到坐标系統及得到的結果圖檔。 
這個繪畫環境會被立刻push到圖形上下文。

當 目前上下文是通過這個方法生成的,你便可以調用UIGraphicsGetImageFromCurrentImageContext 
函數去取回基于目前上下文的圖檔對象。當你不再改正上下文你必須去調用UIGraphicsEndImageContext方法去清理位圖繪畫環境并且從上下文棧中移除。 
你不應該使用UIGraphicsPopContext函數去從棧上移除上下文。

在大多數其他情況,這個圖形上下文建立與其他一樣,你可以改變上下文通過 
push或pop其他圖形上下文,你一樣可以通過UIGraphicsGetCurrentContext函數。

這個函數可以被任何線程的app調用
           
UIGraphicsGetImageFromCurrentImageContext
           
傳回一個基于目前位圖上下文中的内容

Return Value:
    一個圖檔對象包含目前圖檔上下文中的内容

讨論:
    你隻能在一個位圖上下文為目前上下文時才能調用這個方法。 
    如果目前上下文為nil或者不是通過調用UIGraphicsBeginImageContext來調用的,那麼這個函數便傳回nil.

這個函數可以被app的任何線程調用。
           
UIGraphicsEndImageContext
           
從上下文棧頂部移除目前的位圖上下文


注: 你可以使用這個方法來清理通過UIGraphicsBeginImageContext函數建立的上下文并且可以移除在棧頂部并基于位圖的上下文。 
如果目前上下文不是通過UIGraphicsBeginImageContext函數建立,那麼這個方法什麼都不會去做。