從視頻中獲取縮略圖生成GIF圖片,首先需要了解思路和要用到的開發(fā)框架摹迷,先來說一下思路:
1.在視頻中按一定的時間,去截取當(dāng)前時間的幀(即縮略圖),如:每0.1秒獲取一張幀圖片露氮,連續(xù)獲取2秒,此時就會獲取20張圖片钟沛;
2.對這20張圖片進(jìn)行合成為GIF圖片畔规,并保存到相應(yīng)路徑下面;
3.對路徑下面的GIF進(jìn)行UIImageView播放恨统;
由此可知叁扫,難點(diǎn)就在于視頻幀的截取、圖片的合成畜埋、以及imageView播放本地合成的gif的問題莫绣;
視頻幀的截取:
? ? ? ? 用到了AVURLAsset悠鞍,根據(jù)videoPath生成AVURLAsset對象asset对室,根據(jù)asset創(chuàng)建AVAssetImageGenerator圖片發(fā)生器對象,進(jìn)行幀圖片的生成:
首先來看一下一張幀圖片的獲瓤Ъ馈:
- (UIImage*) getVideoPreViewImage
{
AVURLAsset *asset= [[AVURLAsset alloc] initWithURL:videoPath options:nil];
AVAssetImageGenerator *gen= [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform=YES;
CMTime time=CMTimeMakeWithSeconds(0.0, 600);
NSError *error=nil;
CMTime actualTime;
CGImageRefimage= [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *img= [[[UIImage alloc] initWithCGImage:image] autorelease];
CGImageRelease(image);
return img;
}
這里我們需要注意一點(diǎn):當(dāng)我們不設(shè)置gen.requestedTimeToleranceAfter=kCMTimeZero;
gen.requestedTimeToleranceBefore=kCMTimeZero;的話掩宜,我們給定的time和結(jié)果的actualTime很有可能是不一致的(請看:傳送門 ,當(dāng)你指定要獲取time時刻的幀么翰,如果不設(shè)置這兩個屬性牺汤,系統(tǒng)會默認(rèn)如果在指定time段內(nèi)有緩存,就從緩存中直接返回結(jié)果浩嫌,但并不準(zhǔn)確檐迟,這是為了優(yōu)化性能)戴已,如果我們需要精確時間的幀,就需要加上這兩句代碼锅减;
順便我們來了解一下CMTime糖儡,它一般有兩種創(chuàng)建方式:第一種:CMTimeMake(value,timescale),value是當(dāng)前第幾幀怔匣,timescale是每秒的幀數(shù)握联,我們可由value/timescale得到視頻總秒數(shù)seconds;第二種是:CMTimeMakeWithSeconds(second,timescale)每瞒,可知second是當(dāng)前時間金闽,second*timescale就是second時間內(nèi)的總幀數(shù);可用CMTimeShow(actualTime)輸出看一下剿骨;
fps是指畫面每秒傳輸幀數(shù)代芜,即幀率;iOS中的CMTime的timescale為fps*1000浓利;
float fps = [[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] nominalFrameRate];(fps的獲取方式)
每0.1秒獲取一張幀圖挤庇,獲取前兩秒:代碼
- (void)getAllImages:(NSString *)videoFilePath
{
_imgAry = [NSMutableArray array];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:videoFilePath] options:nil];
CMTime duration = [asset duration];
CMTime startTime = kCMTimeZero;
NSMutableArray *array = [NSMutableArray array];
CMTime addTime = CMTimeMake(duration.timescale*0.1,duration.timescale);
CMTime selectTime = CMTimeMake(2*duration.timescale,duration.timescale);
while (CMTIME_COMPARE_INLINE(startTime, <, selectTime)) {
[array addObject:[NSValue valueWithCMTime:startTime]];
startTime = CMTimeAdd(startTime, addTime);
}
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform=TRUE;
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result == AVAssetImageGeneratorSucceeded) {
@autoreleasepool {
UIImage *image = [UIImage imageWithCGImage:im];
NSData *data = UIImageJPEGRepresentation(image, 1);
dispatch_sync(dispatch_get_main_queue(), ^{
[_imgAry addObject:[UIImage imageWithData:data]];
if (_imgAry.count == 20) {
[self makeAnimatedGif];
return ;
}
});
}
}else{
}
};
CGSize videoSize =? [QupaiSDK shared].videoSize;
generator.maximumSize = videoSize;
generator.requestedTimeToleranceAfter = kCMTimeZero;
generator.requestedTimeToleranceBefore = kCMTimeZero;
[generator generateCGImagesAsynchronouslyForTimes:array completionHandler:handler];
}
生成gif圖片:用到了#import<MobileCoreServices/MobileCoreServices.h>#import<ImageIO/ImageIO.h>框架
主要是每一幀圖片的屬性設(shè)置進(jìn)行合成:
- (UIImage*) makeAnimatedGif {
static NSUInteger kFrameCount = 20;//16;
NSDictionary *fileProperties = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
}
};
NSDictionary *frameProperties = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFDelayTime: @0.1f, // a float (not double!) in seconds, rounded to centiseconds in the GIF data
}
};
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
for (NSUInteger i = 0; i < kFrameCount; i++) {
@autoreleasepool {
UIImage *image = _imgAry[i];//[UIImage imageNamed:name];
CGImageDestinationAddImage(destination, image.CGImage, (__bridge CFDictionaryRef)frameProperties);
}
}
if (!CGImageDestinationFinalize(destination)) {
NSLog(@"failed to finalize image destination");
}
CFRelease(destination);
NSLog(@"url=%@", fileURL);
_fileURL = fileURL;
UIImage * img = [UIImage imageWithData:[NSData dataWithContentsOfURL:fileURL]];
return img;
}
從GIF中獲取每一張圖片用imageview進(jìn)行動畫:
- (NSArray*)sssss{
NSURL *gifImageUrl = _fileURL;//獲取Gif圖的原數(shù)據(jù)
CGImageSourceRef gifSource = CGImageSourceCreateWithURL((CFURLRef)gifImageUrl, NULL);? ? //獲取Gif圖有多少幀
size_t gifcount = CGImageSourceGetCount(gifSource);
NSMutableArray *imageS = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < gifcount; i++) {
//由數(shù)據(jù)源gifSource生成一張CGImageRef類型的圖片
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
UIImage *image = [UIImage imageWithCGImage:imageRef];
[imageS addObject:image];? ? ? ? CGImageRelease(imageRef);? ? }
//得到圖片數(shù)組
return imageS;
}
- (void)setgifImgView:(NSArray*)images{
//把數(shù)組圖片通過imageView的動畫添加? 然后開始動畫
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 100, 100, 100)];//初始化
imageView.backgroundColor = [UIColor cyanColor];//背景顏色
imageView.image = images.firstObject;
imageView.animationImages = images;
//動畫的總時長(一組動畫坐下來的時間 6張圖片顯示一遍的總時間)
imageView.animationDuration = 3;
imageView.animationRepeatCount = 0;//動畫進(jìn)行幾次結(jié)束
[imageView startAnimating];//開始動畫
imageView.userInteractionEnabled = YES;
[[UIApplication sharedApplication].keyWindow addSubview:imageView];
}
OK,圖像的處理需要多了解CoreGraphics框架贷掖,多了解SDWebImage 圖片處理機(jī)制嫡秕;