iOS圖像處理之UI,CG和CI

UIImage,CGImage和CGImageRef釋疑

UIImage雖然可以加載糯累、顯示各種格式的位圖沙咏,甚至可以同時(shí)加載圖片肮疗,接下來依次播放多張圖片形成動(dòng)畫。但UIImage不能對(duì)圖片進(jìn)行縮放童番、旋轉(zhuǎn)精钮,不能"挖取"源圖片的指定區(qū)域等,這些功能可借助Quartz 2D的CGImageRef來實(shí)現(xiàn)剃斧。UIImage與CGImageRef之間可以相互轉(zhuǎn)換轨香,CGImageRef并不是面向?qū)ο蟮腁PI,也不是類悯衬,只是一個(gè)指針類型弹沽,Quartz 2D對(duì)CGImageRef的定義為:

typedef struct CGImage *CGImageRef;

CGImage和CGImageRef是用來重繪圖形的類,它們?cè)趹?yīng)用時(shí)是按照?qǐng)D像的像素矩陣來繪制圖片的筋粗,它們可以用來處理bitmap策橘。

//CGImageRef轉(zhuǎn)換成UIImage
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef ic = CGBitmapContextCreateImage(context);
UIImage* image = [UIImage imageWithCGImage: ic];

//UIImage轉(zhuǎn)換成CGImageRef
UIImage *loadImage=[UIImage imageNamed:@"c.png"];
CGImageRef cgimage=loadImage.CGImage;

系統(tǒng)會(huì)維護(hù)一個(gè)CGContextRef的棧,而UIGraphicsGetCurrentContext()會(huì)取棧頂?shù)腃GContextRef娜亿,正確的做法是只在drawRect里調(diào)用UIGraphicsGetCurrentContext()丽已,因?yàn)樵赿rawRect之前,系統(tǒng)會(huì)往棧里面壓入一個(gè)valid的CGContextRef买决,除非自己去維護(hù)一個(gè)CGContextRef沛婴,否則不應(yīng)該在其他地方取CGContextRef。

UIColor督赤,CGColor嘁灯,CIColor區(qū)別和聯(lián)系

UIColor是UIKit中存儲(chǔ)顏色信息的一個(gè)重要的類,一個(gè)UIColor對(duì)象包含了顏色和透明度的值躲舌,它的顏色空間已經(jīng)針對(duì)iOS進(jìn)行了優(yōu)化丑婿。UIColor包含了一些類方法用于創(chuàng)建一些最常見的顏色,如白色没卸,黑色羹奉,紅色,透明色等约计,這些顏色的色彩空間也不盡相同(白色和黑色是kCGColorSpaceDeviceGray诀拭,紅色的色彩空間是kCGColorSpaceDeviceRGB)。UIColor有兩個(gè)重要的屬性:一個(gè)是CGColor煤蚌,一個(gè)是CIColor(5.0之后添加)耕挨。

CGColor主要用于CoreGaphics框架之中,CGColor其實(shí)是個(gè)結(jié)構(gòu)體铺然,而我們通常在使用的CGColor的時(shí)候使用的是它的引用類型CGColorRef俗孝。CGColor主要由CGColorSapce和Color Components兩個(gè)部分組成,同樣的顏色組成魄健,如果顏色空間不同的話赋铝,解析出來的結(jié)果可能會(huì)有所不同。這就像我們?cè)谔幚韴D片數(shù)據(jù)的時(shí)候沽瘦,如果把RGBA格式當(dāng)成BGRA格式處理的結(jié)果可想而知革骨。在Quartz 2D中CGColor常用來設(shè)置context的填充顏色农尖,設(shè)置透明度等。

CIColor主要用于和Core Image框架中其他類交互良哲,比如CIFilter盛卡,CIContext以及CIImage。CIColor中顏色值的范圍是0.0-1.0之間筑凫,0.0代表該顏色分量為最小值滑沧,1.0代表改顏色分量為最大值。其中alpha值的范圍也是0.0到1.0之間巍实,0.0代表全透明滓技,1.0代表完全不透明,CIColor的顏色分量通常都是沒有乘以alpha值棚潦×钇可以使用initWithCGColor:函數(shù),通過CGColor創(chuàng)建一個(gè)CIColor丸边。其中傳入的CGColorRef對(duì)象可以使任何任何顏色空間叠必,但是Core Image框架會(huì)在傳入filter kernel之前把所有的顏色空間轉(zhuǎn)換到Core Image工作顏色空間。Core Image工作顏色空間使用三個(gè)顏色分量加上一個(gè)alpha分量組成(其實(shí)就是kCGColorSpaceDeviceRGB)妹窖。

UIColor的CGColor總是有效的纬朝,不管它是通過CGColor,CIColor骄呼,還是其他方法創(chuàng)建的玄组,CGColor屬性都總是有效的;但是CIColor屬性就不總是有效的谒麦,只有當(dāng)UIColor是通過CIColor創(chuàng)建的時(shí)候,它才是有效的哆致,否則訪問該屬性將會(huì)拋出異常绕德。

// test init uicolor with CGColor
UIColor *color = [UIColor colorWithCGColor:[UIColor whiteColor].CGColor];

// CGColor property is always valid
NSLog(@"CGColor from UIColor %@", color.CGColor);

// don't use CIColor property 
// This property throws an exception if the color object was not initialized with a Core Image color. 
NSLog(@"CIColor from UIColor %@", color.CIColor);   // crush

當(dāng)UIColor使用CGColor初始化的時(shí)候,所有CGColorRef包含的信息摊阀,都會(huì)被原封不動(dòng)的保留耻蛇,其中就包括Color space,而且通過下面的小例子我們還可以看到如果使用CGColor初始化UIColor的時(shí)候胞此,UIColor其實(shí)是直接保留了一份這個(gè)CGColorRef對(duì)象臣咖。

// test kCGColorSpaceDeviceCMYK
CGColorSpaceRef cmykSpace = CGColorSpaceCreateDeviceCMYK();
CGFloat cmykValue[] = {1, 1, 0, 0, 1};      // blue
CGColorRef colorCMYK = CGColorCreate(cmykSpace, cmykValue);
CGColorSpaceRelease(cmykSpace);
NSLog(@"colorCMYK: %@", colorCMYK);

// color with CGColor, uicolor will just retain it
UIColor *color = [UIColor colorWithCGColor:colorCMYK];
NSLog(@"CGColor from UIColor: %@", color.CGColor);

當(dāng)使用CIColor來初始化一個(gè)UIColor的時(shí)候,再去訪問UIColor的CGColor屬性的時(shí)候漱牵,我們會(huì)發(fā)現(xiàn)CGColor的color Space和設(shè)置CIColor的color space的是不完全一樣的夺蛇,在這個(gè)過程中CIColor會(huì)為我們做一個(gè)轉(zhuǎn)換。使用kCGColorSpaceDeviceGray酣胀,kCGColorSpaceDeviceRGB刁赦,kCGColorSpaceDeviceCMYK三種顏色空間來初始化一個(gè)CIColor的時(shí)候娶聘,再去使用該CIColor去初始化一個(gè)UIColor,然后在去訪問其CIColor屬甚脉,CGColor屬性丸升,查看顏色空間并打印顏色信息。

  1. 使用kCGColorSpaceDeviceGray初始化CIColor

     // test kCGColorSpaceDeviceGray
     NSLog(@"CGColor white color:%@", [UIColor whiteColor].CGColor);
    
     CIColor *ciColor = [CIColor colorWithCGColor:[UIColor whiteColor].CGColor];
     NSLog(@"cicolor: %@", ciColor);
     NSLog(@"cicolor colorspace: %@", ciColor.colorSpace);
    
     color = [UIColor colorWithCIColor:ciColor];
     NSLog(@"color %@", color);
    
     // Core Image converts all color spaces to the Core Image working color 
     // space before it passes the color space to the filter kernel.
     // kCGColorSpaceDeviceGray ---> kCGColorSpaceDeviceRGB
     NSLog(@"cicolor from UIColor: %@", color.CIColor);
     NSLog(@"cicolor's colorspace: %@", color.CIColor.colorSpace);
     NSLog(@"color's CGColor: %@", color.CGColor);
    

通過運(yùn)行程序牺氨,我們看出來狡耻,如果使用一個(gè)kCGColorSpaceDeviceGray的顏色空間的CGColor來初始化CIColor的時(shí)候,我們可以看到CIColor的色彩空間一直是kCGColorSpaceDeviceGray猴凹,通過訪問UIColor的CIColor屬性夷狰,我們可以看到其顏色空間仍然是kCGColorSpaceDeviceGray,但是當(dāng)訪問UIColor的CGColor屬性的時(shí)候精堕,通過打印可以發(fā)現(xiàn)其色彩空間已經(jīng)轉(zhuǎn)變成了kCGColorSpaceDeviceRGB空間了孵淘,而顏色值也正確的從原來的顏色空間轉(zhuǎn)換到了新的顏色空間。

  1. 使用kCGColorSpaceDeviceRGB初始化CIColor

     //test kCGColorSpaceDeviceRGB
     NSLog(@"CGColor red color:%@", [UIColor redColor].CGColor);
    
     CIColor *ciColor = [CIColor colorWithCGColor:[UIColor redColor].CGColor];
     NSLog(@"cicolor: %@", ciColor);
     NSLog(@"cicolor colorspace: %@", ciColor.colorSpace);
    
     UIColor *color = [UIColor colorWithCIColor:ciColor];
     NSLog(@"color %@", color);
    
     NSLog(@"cicolor from UIColor: %@", color.CIColor);
     NSLog(@"cicolor's colorspace: %@", color.CIColor.colorSpace);
     NSLog(@"color's CGColor: %@", color.CGColor);
    

整個(gè)過程中CIColor歹篓,以及通過UIColor的CGColor和CIColor屬性訪問到的值瘫证,打印出來我們可以發(fā)現(xiàn)它們都是kCGColorSpaceDeviceRGB空間的。

  1. 使用kCGColorSpaceDeviceCMYK初始化CIColor

     // test kCGColorSpaceDeviceCMYK
     CGColorSpaceRef cmykSpace = CGColorSpaceCreateDeviceCMYK();
     NSLog(@"Components number: %zu", CGColorSpaceGetNumberOfComponents(cmykSpace));
     CGFloat cmykValue[] = {1, 1, 0, 0, 1};      // blue
     CGColorRef colorCMYK = CGColorCreate(cmykSpace, cmykValue);
     CGColorSpaceRelease(cmykSpace);
     NSLog(@"colorCMYK: %@", colorCMYK);
    
     ciColor = [CIColor colorWithCGColor:colorCMYK];
     NSLog(@"cicolor: %@", ciColor);     // in fact庄撮,the color value of CIColor has converted to RGB Colorspace
     NSLog(@"cicolor colorspace: %@", ciColor.colorSpace);
    
     color = [UIColor colorWithCIColor:ciColor];
     NSLog(@"UIColor with CIColor: %@", color);
    
     NSLog(@"cicolor from UIColor: %@", color.CIColor);
     NSLog(@"cicolor's colorspace: %@", color.CIColor.colorSpace);
    
     // when UIColor init with CIColor, UIColor's CGColor will convert other colorspace to   kCGColorSpaceDeviceRGB
     NSLog(@"cgcolor from UIColor: %@", color.CGColor);
    

當(dāng)我們用一個(gè)CMYK顏色空間的CGColor來初始化CIColor的時(shí)候背捌,CIColor的顏色空間依然是CMYK,但是顏色值已經(jīng)轉(zhuǎn)換成RGB的顏色值洞斯。當(dāng)使用該CIColor創(chuàng)建一個(gè)UIColor的時(shí)候毡庆,我們?cè)偻ㄟ^CIColor和CGColor屬性打印信息的時(shí)候,我們會(huì)發(fā)現(xiàn)CIColor的色彩空間依然是CMYK烙如,但是CGColor打印所得到的信息說明它已經(jīng)被轉(zhuǎn)換成RGB空間了么抗。

關(guān)于創(chuàng)建一個(gè)CGColor
最常用的函數(shù)是CGColorCreate,該函數(shù)有兩個(gè)參數(shù):

  1. colorspace亚铁,指定CGColor對(duì)應(yīng)的顏色空間蝇刀,Quartz就會(huì)retain該對(duì)象,因此調(diào)用完之后你就可以安全的釋放該對(duì)象徘溢。
  2. components吞琐,一個(gè)CGFloat的數(shù)組,該數(shù)組的元素個(gè)數(shù)是指定色彩空間包含的顏色分量數(shù)n然爆,加上對(duì)應(yīng)的alpha值站粟。

該函數(shù)該返回一個(gè)新創(chuàng)建的CGColorRef,當(dāng)我們不再使用該對(duì)象的時(shí)候使用CGColorRelease函數(shù)釋放該對(duì)象曾雕。

獲取CGColor的數(shù)據(jù)
在我們創(chuàng)建的時(shí)候傳入兩個(gè)重要的參數(shù)進(jìn)去奴烙,當(dāng)我們獲取到了CGColorRef以后當(dāng)然就可以拿到對(duì)應(yīng)的ColorSpace以及Components。

  1. 獲取ColorSpace
    通過CGColorGetColorSpace函數(shù)我們可以獲取到當(dāng)前CGColorRef對(duì)應(yīng)的ColorSpace,該函數(shù)只接受一個(gè)參數(shù)就是你要獲取ColorSpace的CGColorRef缸沃。

     CGColorRef cgColor = [UIColor redColor].CGColor;
     CGColorSpaceRef colorSpace = CGColorGetColorSpace(cgColor);
     NSLog(@"color space: %@", colorSpace);
    
  2. 獲取Color Components
    要獲取到CGColorRef對(duì)應(yīng)的顏色值恰起,我們需要用到CGColorGetNumberOfComponents和CGColorGetComponents兩個(gè)函數(shù)。我們先來看看兩個(gè)函數(shù)的函數(shù)原型:

     size_t CGColorGetNumberOfComponents (
     CGColorRef color
     );
    
     const CGFloat * CGColorGetComponents (
     CGColorRef color
     );
    

第一個(gè)函數(shù)是獲得CGColorRef的中包含的顏色組成部分的個(gè)數(shù)趾牧,第二個(gè)函數(shù)就是獲取實(shí)際的顏色組成部分的數(shù)組检盼。

NSUInteger num = CGColorGetNumberOfComponents(cgColor);
const CGFloat *colorComponents = CGColorGetComponents(cgColor);
for (int i = 0; i < num; ++i) {
NSLog(@"color components %d: %f", i, colorComponents[i]);
}

判斷兩個(gè)顏色是否相等
不管UIColor使用CIColor,CGColor還是其他方式初始化的翘单,其CGColor屬性都是可用的吨枉。CoreGraphics中提供一個(gè)方法可以判斷兩個(gè)CGColor是否相等,因此我們可以通過判斷兩個(gè)UIColor是否相等哄芜。

// judge two CGColor is equal
if (CGColorEqualToColor([UIColor whiteColor].CGColor, [UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor)) {
NSLog(@"The two CGColor is equal!");
}
else {
NSLog(@"The two CGColor is not equal!");
}

if (CGColorEqualToColor([UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor, [UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor)) {
NSLog(@"The two CGColor is equal!");
}
else {
NSLog(@"The two CGColor is not equal!");
}

例子中第一部分是判斷兩個(gè)白色的UIColor是否相等貌亭,雖然都是白色,但是顏色空間是不一樣的认臊。例子的第二部分簡(jiǎn)單的創(chuàng)建了兩個(gè)RGB空間的UIColor圃庭,運(yùn)行程序可以看出,這兩種顏色是相同的失晴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剧腻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涂屁,更是在濱河造成了極大的恐慌书在,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拆又,死亡現(xiàn)場(chǎng)離奇詭異儒旬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)帖族,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門栈源,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竖般,你說我怎么就攤上這事凉翻。” “怎么了捻激?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)前计。 經(jīng)常有香客問我胞谭,道長(zhǎng),這世上最難降的妖魔是什么男杈? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任丈屹,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旺垒。我一直安慰自己彩库,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布先蒋。 她就那樣靜靜地躺著骇钦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竞漾。 梳的紋絲不亂的頭發(fā)上眯搭,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音业岁,去河邊找鬼鳞仙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛笔时,可吹牛的內(nèi)容都是我干的棍好。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼允耿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼借笙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起右犹,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤提澎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后念链,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盼忌,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年掂墓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谦纱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡君编,死狀恐怖跨嘉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吃嘿,我是刑警寧澤祠乃,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站兑燥,受9級(jí)特大地震影響亮瓷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜降瞳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一嘱支、第九天 我趴在偏房一處隱蔽的房頂上張望蚓胸。 院中可真熱鬧,春花似錦除师、人聲如沸沛膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锹安。三九已至,卻和暖如春贞岭,著一層夾襖步出監(jiān)牢的瞬間八毯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工瞄桨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留话速,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓芯侥,卻偏偏與公主長(zhǎng)得像泊交,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柱查,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容