iOS-圖片裁剪技巧

先貼一個案例,我們做類似的圖片展示的時候,都會需要對相應的圖片進行裁剪以適應我們現實的大小,不然圖片就會被拉伸或者壓縮。

C33F7F1A-22C3-44B6-BF2B-1D2ACE6DC076.png

不知大家有類似需求時會怎么處理,之前我一直是獲取到圖片數據,然后對圖片裁剪到與視圖框相應的比例,然后在展示。貼上代碼:


UIImage * image = (UIImage*)info[UIImagePickerControllerOriginalImage];
CGFloat scale = MIN(image.size.height / 124.0f, image.size.width / 124.0f);
UIImage *cropImage = [image cropToSize:CGSizeMake(124 * scale, 124 * scale) usingMode:NYXCropModeCenter];

我們需要顯示圖片時,第一時間會考慮到用 UIImageView這個類來實現,然而,在iOS中,UIView這個類本身就自帶類似功能的實現,相比上一種方法感覺更簡單快捷。

contents屬性

CALayer 有一個屬性叫做contents,這個屬性的類型被定義為id,意味著它可以是任何類型的對象。在這種情況下,你可以給contents屬性賦任何值,你的app仍然能夠編譯通過。但是,在實踐中,如果你給contents賦的不是CGImage,那么你得到的圖層將是空白的。

contents這個奇怪的表現是由Mac OS的歷史原因造成的。它之所以被定義為id類型,是因為在Mac OS系統上,這個屬性對CGImageNSImage類型的值都起作用。如果你試圖在iOS平臺上將UIImage的值賦給它,只能得到一個空白的圖層。一些初識Core Animation的iOS開發者可能會對這個感到困惑。

頭疼的不僅僅是我們剛才提到的這個問題。事實上,你真正要賦值的類型應該是CGImageRef,它是一個指向CGImage結構的指針。UIImage有一個CGImage屬性,它返回一個CGImageRef,如果你想把這個值直接賦值給CALayercontents,那你將會得到一個編譯錯誤。因為CGImageRef并不是一個真正的Cocoa對象,而是一個Core Foundation類型。

盡管Core Foundation類型跟Cocoa對象在運行時貌似很像(被稱作toll-free bridging),他們并不是類型兼容的,不過你可以通過bridged關鍵字轉換。如果要給圖層的寄宿圖賦值,你可以按照以下這個方法

layer.contents = (__bridge id)image.CGImage;

maskToBounds

默認情況下,UIView仍然會繪制超過邊界的內容或是子視圖,在CALayer下也是這樣的。

UIView有一個叫做clipsToBounds的屬性可以用來決定是否顯示超出邊界的內容,CALayer對應的屬性叫做masksToBounds

contentsRect

CALayercontentsRect屬性允許我們在圖層邊框里顯示寄宿圖的一個子域。這涉及到圖片是如何顯示和拉伸的,所以要比contentsGravity靈活多了

boundsframe不同,contentsRect不是按點來計算的,它使用了單位坐標,單位坐標指定在0到1之間,是一個相對值(像素和點就是絕對值)。所以他們是相對與寄宿圖的尺寸的。

結論

利用以上三個layer的屬性,我們就可以快速實現對示圖片裁剪,貼上代碼:

int width = pic.bmiddle.width;

int height = pic.bmiddle.height;

CGFloat scale = (height / width) / (imageView.height / imageView.width);

if (scale < 0.99 || isnan(scale)) {

 // 寬圖把左右兩邊裁掉

imageView.contentMode = UIViewContentModeScaleAspectFill;

imageView.layer.contentsRect = CGRectMake(0, 0, 1, 1);

} else {

 // 高圖只保留頂部

imageView.contentMode = UIViewContentModeScaleToFill;

imageView.layer.contentsRect = CGRectMake(0, 0, 1, (float)width / height);

}

這樣,我們就可以根據圖片的寬高比例,進行適當裁剪,達到我們所需的顯示效果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容