解决显示多个gif图时,cpu使用过高导致手机温度上升或者内存占用过高问题

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

但是显示方式无非两种:
1:先一次性把gif图解析成多个图片,然后轮流播放这些图片,比如使用UIImageView和sdwebImage;这种方式因为要保存解析后的图片,所以占用内存比较高;
2,播放到哪一张图片时,去gif图中解析对应的这张照片,用完就释放,不占用内存,比如YYImage和webview,但是因为要频繁地解析图片,当照片分辨率很高时,会造成cpu占用率高,导致手机发热;

如果使用的gif图分辨率较低,影响还不是很大,个人测试当使用的gif图分辨率为1280*720,gif图大于8M,数量超过6个时,使用sdwebImage会由于内存暴涨导致崩溃;而使用YYImage虽然不会导致内存暴涨,但是cpu占用率过高导致手机温度上升;

综合考虑:不能使用内存暴增导致程序崩溃的方式,只能使用YYImage或者webview去显示;既然是因为图片分辨率高导致手机温度升高,如果把图片分辨率降低,就可以解决问题了。具体操作如下:
1,从相册选择图片后,使用ALAssetsLibrary取到图片的原始数据:

//获取选择的图片
-(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];//这个就是选取的图片的原二进制数据
             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.获取图片数据
    NSMutableArray *imageArray = [NSMutableArray arrayWithArray:imgArray];
    //每帧时长
    float perDuration = duration*1.0/imgArray.count;
    // 2.创建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的使用率都降低了,手机也不再发热了,能够解决问题。
4,如果需要把原始数据传给服务器,可以再发送数据时,对缩小后的data进行放大处理,然后再发送给服务器,但是这种方式会造成gif图显示模糊,可以保留原始数据进行发送,也可以发送压缩后的数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容