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

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

但是顯示方式無非兩種:
1:先一次性把gif圖解析成多個圖片,然后輪流播放這些圖片,比如使用UIImageView和sdwebImage;這種方式因為要保存解析后的圖片,所以占用內(nèi)存比較高;
2,播放到哪一張圖片時,去gif圖中解析對應(yīng)的這張照片,用完就釋放,不占用內(nèi)存,比如YYImage和webview,但是因為要頻繁地解析圖片,當照片分辨率很高時,會造成cpu占用率高,導致手機發(fā)熱;

如果使用的gif圖分辨率較低,影響還不是很大,個人測試當使用的gif圖分辨率為1280*720,gif圖大于8M,數(shù)量超過6個時,使用sdwebImage會由于內(nèi)存暴漲導致崩潰;而使用YYImage雖然不會導致內(nèi)存暴漲,但是cpu占用率過高導致手機溫度上升;

綜合考慮:不能使用內(nèi)存暴增導致程序崩潰的方式,只能使用YYImage或者webview去顯示;既然是因為圖片分辨率高導致手機溫度升高,如果把圖片分辨率降低,就可以解決問題了。具體操作如下:
1,從相冊選擇圖片后,使用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];//這個就是選取的圖片的原二進制數(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;//播放的總時長
    float scale = 1;
    float imgSize = data.length/1024/1024;
//小于2M不進行縮放,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);
  //重新生成一個縮放后的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];
    //每幀時長
    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的使用率都降低了,手機也不再發(fā)熱了,能夠解決問題。
4,如果需要把原始數(shù)據(jù)傳給服務(wù)器,可以再發(fā)送數(shù)據(jù)時,對縮小后的data進行放大處理,然后再發(fā)送給服務(wù)器,但是這種方式會造成gif圖顯示模糊,可以保留原始數(shù)據(jù)進行發(fā)送,也可以發(fā)送壓縮后的數(shù)據(jù)。

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

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

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