美文网首页ios开发
解决显示多个gif图时,cpu使用过高导致手机温度上升或者内存占

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

作者: 微_涼 | 来源:发表于2022-07-27 09:40 被阅读0次

    显示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图显示模糊,可以保留原始数据进行发送,也可以发送压缩后的数据。

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/ryaairtx.html