圖片拉伸詳解

分類:技術 時間:2016-10-25

導語:

有時候對一個圖片進行常規的縮放達不到我們想要的效果,比如聊天氣泡的大小、帶邊框的按鈕背景。通常我們會設置某個偏移值對圖片進行拉伸來實現我們想要的效果。iOS6以后有兩條相似的API可以解決這一問題,下文簡稱帶模式的縮放和不帶模式的縮放。

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;

下面是官方文檔對API的解釋:

Each inset defines the potion of the image that does not stretch in the given dimension. The regions inside an image’s top and bottom insets maintain a fixed height, and the areas inside the left and right insets maintain a fixed width. Figure 2 shows how each part of a nine-part image stretches as the image itself is stretched to fill the available space. The corners of the image do not change size because they are inside both a horizontal and vertical inset.

也就是說會傳入一個 UIEdgeInsets 類型的結構體將 UIImage 分為9個(也有可能是2個)部分,并對其中間部分和四個邊進行縮放,但是四個角會保持不變。

圖1

下面分別介紹這兩條API。

不帶模式的縮放

縮放模式有兩種,分別是 UIImageResizingModeTile 平鋪和 UIImageResizingModeStretch 拉伸。如果不指定縮放模式,則會根據傳入 UIEdgeInsets 類型的結構體的不同而進行不同的縮放。

原文是這么說的:

iOS uses different rendering techniques, with different performance characteristics, depending on the size of each resizable area in the image:

If resizable areas have a width or height of 1 pixel—that is, a horizontally resizable area is 1 pixel wide, a vertically resizable area is 1 pixel tall, or the center region of the image is 1 x 1 pixel—iOS draws the image by stretching the 1-pixel region. This mode provides the fastest performance (for nonzero cap insets).

If resizable areas have a width or height greater than 1 pixel, iOS draws the image by tiling the region. This mode provides reduced performance, but can be useful for images with textured (rather than solid-color) content in their resizable areas.

If the entire image is resizable—that is, the capInsets parameter is UIEdgeInsetsZero—and its size is greater than 1 x 1 pixel, iOS draws the image by tiling the entire image. This mode is faster than the tiling mode for nonzero cap insets.

也就是說,

  • 如果中間部分邊長都小于或等于1,這種情況下可變部分從上往下、從左至右按一個像素偏移值按照拉伸模式來放大。若中間部分有一邊大于1,則大于1的那邊按平鋪模式縮放,小于1的那邊以一個像素的默認偏移值按拉伸模式縮放。
  • 如果中間部分邊長大于1x1;在這種情況下可變部分按照平鋪模式來放大。
  • 如果中間部分大小等于圖片的大小,并且圖片大小大于1x1,也就是說傳入的參數為 UIEdgeInsetsZero ,在這種情況下可變部分按照平鋪模式來放大。

下面用一張對稱的圖片來測試,圖片大小是90x90, imageView 大小為180x180,上面是測試圖下面是原圖。

中間部分大小為0的情況,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.5, image.size.width*0.5, image.size.height*0.5, image.size.width*0.5)

圖2

中間部分疊加(小于0)的情況,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.5, image.size.width*0.5, image.size.height*0.5 20, image.size.width*0.5 20)

圖3

中間部分邊長均小于1的情況,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.5, image.size.width*0.5, image.size.height*0.5-0.5, image.size.width*0.5-0.5)

圖4

中間部分邊長均大于1的情況,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.3, image.size.width*0.3, image.size.height*0.3, image.size.width*0.3)

圖5

中間部分等于圖片大小的情況,傳入的參數為: UIEdgeInsetsZero

圖6

帶模式的縮放

這種縮放方式出現在iOS6 ,官方說明如下:

This method is exactly the same as its counterpart resizableImageWithCapInsets: except that the resizing mode of the new image object can be explicitly declared. You should only call this method in place of its counterpart if you specifically want your image to be resized with the UIImageResizingModeStretch resizing mode.

意思就是這種縮放方式和前面的差不多,除非你一定要用拉伸的方式來放大圖片,否則還是建議你使用不帶模式的方式來處理你的圖片。

拉伸模式,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.3, image.size.width*0.3, image.size.height*0.3, image.size.width*0.3)

圖7

平鋪模式,傳入的參數為: UIEdgeInsetsMake(image.size.height*0.3, image.size.width*0.3, image.size.height*0.5, image.size.width*0.3)

圖8

這兩種方法都不會改變原圖,而是返回一張新的圖片。其實在像素為1的情況下也看不出是平鋪模式還是拉伸模式,如果是純色背景兩種模式區別也不大。anyway,知道總比不知道要強。


Tags: iOS開發

文章來源:http://www.jianshu.com/p/421aad75e16b


ads
ads

相關文章
ads

相關文章

ad