解決顯示多個(gè)gif圖時(shí),cpu使用過高導(dǎo)致手機(jī)溫度上升或者內(nèi)存占用過高問題

顯示gif圖通常使用的方式如下:
1.使用UIImageView;
2,使用sdwebImage险毁;
3,使用YYImage;
4,使用webview效床;

但是顯示方式無非兩種:
1:先一次性把gif圖解析成多個(gè)圖片,然后輪流播放這些圖片,比如使用UIImageView和sdwebImage邓尤;這種方式因?yàn)橐4娼馕龊蟮膱D片拍鲤,所以占用內(nèi)存比較高;
2汞扎,播放到哪一張圖片時(shí)季稳,去gif圖中解析對(duì)應(yīng)的這張照片,用完就釋放澈魄,不占用內(nèi)存景鼠,比如YYImage和webview,但是因?yàn)橐l繁地解析圖片痹扇,當(dāng)照片分辨率很高時(shí)铛漓,會(huì)造成cpu占用率高溯香,導(dǎo)致手機(jī)發(fā)熱;

如果使用的gif圖分辨率較低票渠,影響還不是很大逐哈,個(gè)人測(cè)試當(dāng)使用的gif圖分辨率為1280*720附帽,gif圖大于8M缓苛,數(shù)量超過6個(gè)時(shí),使用sdwebImage會(huì)由于內(nèi)存暴漲導(dǎo)致崩潰承璃;而使用YYImage雖然不會(huì)導(dǎo)致內(nèi)存暴漲杜窄,但是cpu占用率過高導(dǎo)致手機(jī)溫度上升肠骆;

綜合考慮:不能使用內(nèi)存暴增導(dǎo)致程序崩潰的方式,只能使用YYImage或者webview去顯示塞耕;既然是因?yàn)閳D片分辨率高導(dǎo)致手機(jī)溫度升高蚀腿,如果把圖片分辨率降低,就可以解決問題了扫外。具體操作如下:
1莉钙,從相冊(cè)選擇圖片后,使用ALAssetsLibrary取到圖片的原始數(shù)據(jù):

//獲取選擇的圖片
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
    [picker dismissViewControllerAnimated:YES completion:nil];
    [MeetHUD showLoadingTo:self.view animated:YES];
    __weak typeof(self)weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
        NSString *assetString = [imageURL absoluteString];
        __strong typeof(weakSelf)strongSelf = weakSelf;
        ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc]init];
        [assetLibrary assetForURL:imageURL resultBlock:^(ALAsset *asset) {
            ALAssetRepresentation *re = nil;
            if([assetString hasSuffix:@"GIF"] || [assetString hasSuffix:@"gif"]){
                re = [asset representationForUTI:(__bridge NSString *)kUTTypeGIF];
            } else {
                re = [asset defaultRepresentation];
            }
            NSUInteger size = [re size];
             uint8_t *buffer = malloc(size);
             NSError *error;
             NSUInteger bytes = [re getBytes:buffer fromOffset:0 length:size error:&error];
             NSData *data = [NSData dataWithBytes:buffer length:bytes];//這個(gè)就是選取的圖片的原二進(jìn)制數(shù)據(jù)
             free(buffer);
           NSData*scaleData = [self DataToScaleGifData: data];
         } failureBlock:^(NSError *error) {

         }];
    });
}

2筛谚,解析出gif圖中的每張圖片磁玉;

-(NSData*)DataToScaleGifData:(NSData*)data{
    CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    size_t gifCount = CGImageSourceGetCount(gifSource);
    NSMutableArray *scaleImgArray = [NSMutableArray array];
    NSTimeInterval totalDuration = 0;//播放的總時(shí)長(zhǎng)
    float scale = 1;
    float imgSize = data.length/1024/1024;
//小于2M不進(jìn)行縮放,2M帶4M縮放60%驾讲,4M到8M縮放40%蚊伞,超過8M縮放20%
    if(imgSize <= 2){
        scale = 1;
    } else if (imgSize > 2 && imgSize < 4){
        scale = 0.6;
    } else if(imgSize >= 4 && imgSize < 8){
        scale = 0.4;
    } else {
        scale = 0.2;
    }
  float imgWidth = 0;
  float imgHeight = 0;
    for (size_t i = 0; i< gifCount; i++) {
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
        imgWidth = CGImageGetWidth(imageRef);
        imgHeight = CGImageGetHeight(imageRef);
        UIImage *uiImage = [UIImage imageWithCGImage:imageRef];
        if(scale == 1){
            [scaleImgArray addObject:uiImage];
        } else {
            UIImage *scaleImg = [[self class] imageCompresswithsimple:uiImage scaledtosize:CGSizeMake(imgWidth*scale, imgHeight*scale)];
            [scaleImgArray addObject:scaleImg];
        }
        NSTimeInterval duration = [MeetVirtualHeaderTool gifImageDeleyTime:gifSource index:i];
        totalDuration += duration;
        CGImageRelease(imageRef);
    }
    CFRelease(gifSource);
  //重新生成一個(gè)縮放后的gif圖data
    NSData *resultData = [[self class] creategifWithImgArray:scaleImgArray duration:totalDuration];
    return resultData;
}

圖片縮放方法如下:

+ (UIImage*)imageCompresswithsimple:(UIImage*)image scaledtosize:(CGSize)size{
  UIGraphicsBeginImageContext(size);
  [image drawInRect:CGRectMake(0,0,size.width,size.height)];
    UIImage* newimage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return newimage;
}

重新生成縮放后的gif圖data方法:

+ (NSData *)creategifWithImgArray:(NSArray *)imgArray duration:(float)duration{
    // 1.獲取圖片數(shù)據(jù)
    NSMutableArray *imageArray = [NSMutableArray arrayWithArray:imgArray];
    //每幀時(shí)長(zhǎng)
    float perDuration = duration*1.0/imgArray.count;
    // 2.創(chuàng)建gif文件
    NSArray *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docString = [document objectAtIndex:0];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *pathString = [docString stringByAppendingString:@"/gif"];
    [fileManager createDirectoryAtPath:pathString withIntermediateDirectories:YES attributes:nil error:nil];
    NSString *path = [pathString stringByAppendingString:@"test1.gif"];
    
    // 3.配置gif屬性
    CGImageDestinationRef destion;
    // 將 path 映射成 CFURLRef 的路徑
    CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)path, kCFURLPOSIXPathStyle, false);
    destion = CGImageDestinationCreateWithURL(url, kUTTypeGIF, imageArray.count, NULL);
    
//    [mutDict setObject:[NSNumber numberWithFloat:perDuration] forKey:kCGImagePropertyGIFUnclampedDelayTime];
    NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:perDuration],(NSString *)kCGImagePropertyGIFDelayTime, nil] forKey:(NSString *)kCGImagePropertyGIFDelayTime];
    
    NSMutableDictionary *mutDict = [NSMutableDictionary dictionaryWithCapacity:2];
    [mutDict setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCGImagePropertyGIFHasGlobalColorMap];
    [mutDict setObject:(NSString *)kCGImagePropertyColorModelRGB forKey:(NSString *)kCGImagePropertyColorModel];
    [mutDict setObject:[NSNumber numberWithInt:8] forKey:(NSString *)kCGImagePropertyDepth];
    [mutDict setObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount];
    NSDictionary *gifPropertyDict = [NSDictionary dictionaryWithObject:mutDict forKey:(NSString *)kCGImagePropertyGIFDictionary];
    
    CGImageDestinationSetProperties(destion, (__bridge CFDictionaryRef)gifPropertyDict);
    // 單幀添加到gif
    for (UIImage *image in imageArray) {
        CGImageDestinationAddImage(destion, image.CGImage, (__bridge CFDictionaryRef)dict);
    }
    CGImageDestinationFinalize(destion);
    CFRelease(destion);
    NSData *gifData = [NSData dataWithContentsOfFile:path];
    NSError *err;
    [fileManager removeItemAtPath:path error:&err];
    if(err == nil){
        
    }
    return gifData;
}

3,使用縮放后的data,不管是使用yyImage還是webView吮铭,cpu的使用率都降低了时迫,手機(jī)也不再發(fā)熱了,能夠解決問題谓晌。
4掠拳,如果需要把原始數(shù)據(jù)傳給服務(wù)器,可以再發(fā)送數(shù)據(jù)時(shí)纸肉,對(duì)縮小后的data進(jìn)行放大處理溺欧,然后再發(fā)送給服務(wù)器,但是這種方式會(huì)造成gif圖顯示模糊毁靶,可以保留原始數(shù)據(jù)進(jìn)行發(fā)送胧奔,也可以發(fā)送壓縮后的數(shù)據(jù)逊移。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末预吆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胳泉,更是在濱河造成了極大的恐慌拐叉,老刑警劉巖岩遗,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異凤瘦,居然都是意外死亡宿礁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門蔬芥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梆靖,“玉大人,你說我怎么就攤上這事笔诵》滴牵” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵乎婿,是天一觀的道長(zhǎng)测僵。 經(jīng)常有香客問我,道長(zhǎng)谢翎,這世上最難降的妖魔是什么捍靠? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮森逮,結(jié)果婚禮上榨婆,老公的妹妹穿的比我還像新娘。我一直安慰自己吊宋,他們只是感情好纲辽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著璃搜,像睡著了一般拖吼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上这吻,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天吊档,我揣著相機(jī)與錄音,去河邊找鬼唾糯。 笑死怠硼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的移怯。 我是一名探鬼主播香璃,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼舟误!你這毒婦竟也來了葡秒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眯牧,沒想到半個(gè)月后蹋岩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡学少,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年剪个,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片版确。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扣囊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绒疗,到底是詐尸還是另有隱情如暖,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布忌堂,位于F島的核電站盒至,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏士修。R本人自食惡果不足惜枷遂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棋嘲。 院中可真熱鬧酒唉,春花似錦、人聲如沸沸移。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雹锣。三九已至网沾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蕊爵,已是汗流浹背辉哥。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留攒射,地道東北人醋旦。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像会放,于是被迫代替她去往敵國和親饲齐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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