顯示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ù)逊移。