iOS Color Misaligned Images優(yōu)化

最近在做GPU圖層顯示的優(yōu)化,其中關(guān)于Color Misaligned Images優(yōu)化文章有很多,但在具體優(yōu)化的時(shí)候還是遇到了點(diǎn)的問(wèn)題,特此記錄。

檢測(cè)方式

以下兩種方式均可發(fā)現(xiàn)存在Misaligned Images問(wèn)題的地方:

  • 模擬器調(diào)試時(shí),打開模擬器的Debug - Color Misaligned Images菜單選項(xiàng)。最快捷,但僅限模擬器上查看。
  • Instrument性能檢測(cè)時(shí),選中Core Animation模板,在Display Settings中勾選Color Misaligned Images選項(xiàng)。可針對(duì)模擬器和真機(jī),可查看真機(jī)上所有應(yīng)用的像素混合情況。

問(wèn)題定義

打開開關(guān)后,看到部分視圖會(huì)有黃色或洋紅色(Magenta)的圖層標(biāo)記,代表其像素不對(duì)齊。
不對(duì)齊:視圖或圖片的點(diǎn)數(shù)(point),不能換算成整數(shù)的像素值(pixel),導(dǎo)致顯示視圖的時(shí)候需要對(duì)沒(méi)對(duì)齊的邊緣進(jìn)行額外混合計(jì)算,影響性能。
洋紅色:UIView的frame像素不對(duì)齊,即不能換算成整數(shù)像素值。
黃色:UIImageView的圖片像素大小與其frame.size不對(duì)齊,圖片發(fā)生了縮放造成。

優(yōu)化方式

frame像素不對(duì)齊


針對(duì)frame像素不對(duì)齊,借助ceilf()、floorf()、CGRectIntegral()等將小數(shù)點(diǎn)后數(shù)據(jù)除去即可。
使用floorf時(shí),需要注意是否會(huì)因?yàn)橄蛳氯≌绊懸晥D的顯示。
關(guān)于CGRectIntegral的使用,《Aligned UIViews》這篇文章中提到一種非常特殊的情況,在layoutSubviews中使用CGRectIntegral來(lái)重新設(shè)置frame,可能導(dǎo)致同一個(gè)view在不同時(shí)候計(jì)算得到到的x和width不同的情況,但實(shí)際測(cè)試并沒(méi)有發(fā)現(xiàn)文章中描述的問(wèn)題。
0.5個(gè)點(diǎn),會(huì)造成像素不對(duì)齊嗎?
在@2x屏幕上不會(huì),但@3x屏幕上會(huì)。會(huì)不會(huì)由最終計(jì)算得像素值是不是整數(shù)判斷,比如上圖中在@3x屏幕上,第4個(gè)label高度為40.1導(dǎo)致了像素不對(duì)齊,但第3個(gè)label高度為40+1/3沒(méi)導(dǎo)致像素不對(duì)齊,在@2x屏幕上當(dāng)然這兩個(gè)寬度都會(huì)導(dǎo)致像素不對(duì)齊。

像素不對(duì)稱齊的元素一般為UILabel或UIImageView。
特別注意,上圖中UILabel寬度不為整數(shù)時(shí)并沒(méi)有有像素不對(duì)齊,但x、y、height不為整數(shù)就會(huì)導(dǎo)致像素不對(duì)齊。

圖片像素不對(duì)齊


上圖的前4個(gè)UIImageView,顯示的是同一張圖片,該圖片@2x像素為128x128px,@3x像素為192x192px,僅當(dāng)UIImageView的size為64x64的時(shí)候才沒(méi)有像素不對(duì)齊。
遇到這種情況需要嚴(yán)格約束Icon圖片和UIImageView的尺寸。

還有種情況即圖片是從服務(wù)端獲取到的,大小不規(guī)則。直接在UIImageView上顯示容易出現(xiàn)像素不對(duì)齊。
解決方法:將下載到的圖片,縮放到與UIImageView對(duì)應(yīng)的尺寸,再顯示出來(lái)。
多種圖片縮放方式及其性能比較可參考《Image Resizing Techniques》,此處提供一個(gè)簡(jiǎn)單實(shí)現(xiàn):

@implementation UIImage(Resize)

/**
 將UIImage縮放到指定大小

 @param boxSize 一般為UIImageView的size
 @return 縮放后的UIImage
 */
- (UIImage *)imageShowInSize:(CGSize)boxSize {
    if (CGSizeEqualToSize(boxSize, self.size)) {
        return self;
    }
    
    CGFloat screenScale = [[UIScreen mainScreen] scale];
    CGFloat rate = MAX(boxSize.width / self.size.width, boxSize.height / self.size.height);
    CGSize resize = CGSizeMake(self.size.width * rate , self.size.height * rate );
    CGRect drawRect = CGRectMake(-(resize.width - boxSize.width) / 2.0 ,
                                 -(resize.height - boxSize.height) / 2.0 ,
                                 resize.width,
                                 resize .height);
    boxSize = CGSizeMake(boxSize.width, boxSize.height);
    UIGraphicsBeginImageContextWithOptions(boxSize, YES, screenScale);
    [self drawInRect:drawRect];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
@end

注意

  • 具體使用時(shí),可能需要根據(jù)UIImageView的contentMode屬性調(diào)整縮放方式。
  • 該方法執(zhí)行會(huì)花費(fèi)一定的時(shí)間,在列表上顯示需要縮放的圖片,為了不影響列表滾動(dòng)流程體驗(yàn),該操作應(yīng)放到非主線進(jìn)行,并考慮將縮放后的結(jié)果緩存以便下次直接使用。
  • 根據(jù)原始圖片尺寸大小,當(dāng)前狀況是否明顯影響列表滾動(dòng)等具體情況再?zèng)Q定是否優(yōu)化,比如目前微博首頁(yè)的用戶頭像和九宮格圖片不存在像素不對(duì)齊情況,而微信朋友圈的用戶頭像和圖片是染成黃色的像素不對(duì)齊。

UITableview上UILabel的不對(duì)齊


在某些UITableview上,會(huì)發(fā)現(xiàn)盡管UILabel的frame已經(jīng)取整了,但所有Cell上Label還是全都被染成了紅色,非常不解。

打開Xcode的Debug View Hierarchy,可以看到進(jìn)入頁(yè)面UITableview還沒(méi)做任何滾動(dòng)時(shí),UILabel的frame沒(méi)有異常,但是UITableViewCell的y坐標(biāo)不是整數(shù),有個(gè)0.01的差值。

這次恍然大悟,父視圖的像素不對(duì)齊也會(huì)影響到子視圖。而此處0.01差值的來(lái)源,是UITableview的header高度。
在使用Group Style的UITableview時(shí),如果tableView:heightForHeaderInSection:回調(diào)返回0,系統(tǒng)會(huì)認(rèn)為沒(méi)有設(shè)置header的高度而重新提供一個(gè)默認(rèn)的header高度,導(dǎo)致在UITableview中看到一個(gè)空白的header。
一種簡(jiǎn)單但有隱患的處理方式,就是在回調(diào)里返回一個(gè)很小的高度,比如0.1、0.01,這樣能達(dá)到隱藏header的效果,但也造成了此處的像素不對(duì)齊問(wèn)題。
解決方法

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return CGFLOAT_MIN;
}

避免使用0.01這樣的具體數(shù)值(0.01還不足夠小,0.0001就能避免此處的不對(duì)齊),直接使用系統(tǒng)給的CGFLOAT_MIN,這個(gè)足夠小的值既能避免上述情況,又能讓代碼更直觀。
隱藏header的其它方法和原理可參考:0代碼隱藏GroupedTableView上邊多余的間隔。

參考文章:

我的博客原址:iOS Color Misaligned Images優(yōu)化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,614評(píng)論 4 61
  • [這是第1篇] 導(dǎo)語(yǔ):像素對(duì)齊并不是一個(gè)復(fù)雜的問(wèn)題,但是開發(fā)中稍不注意的話,是會(huì)造成像素不對(duì)齊的情況(恰恰容易被忽...
    南華coder閱讀 10,951評(píng)論 10 86
  • 時(shí)刻保持自己的關(guān)系,不停尋找動(dòng)力,讓自己變得更加多元化,別讓希望變成絕望。
    姜楊A(yù)da閱讀 203評(píng)論 0 0
  • 什么叫做“念”?“念”就是人的心念,就是人腦海里不斷跳過(guò),不斷幻化的各種想法。當(dāng)你嘗試打坐,嘗試讓自己平靜下來(lái)的時(shí)...
    alabiubiubiu閱讀 328評(píng)論 0 1
  • 促銷:站著無(wú)聊。但是穩(wěn)定拿錢。 督導(dǎo):可以動(dòng)換。但是活少錢少。時(shí)間寬裕。可以做別的事。(還沒(méi)定下來(lái)。) 禮儀:還沒(méi)...
    夏之兔耳閱讀 141評(píng)論 0 0

友情鏈接更多精彩內(nèi)容