iOS开发资料收集区iOS开发笔记iOS 开发每天分享优质文章

从视频中截取缩略图生成gif图片

2017-11-08  本文已影响21人  辉的书

从视频中获取缩略图生成GIF图片,首先需要了解思路和要用到的开发框架,先来说一下思路:

1.在视频中按一定的时间,去截取当前时间的帧(即缩略图),如:每0.1秒获取一张帧图片,连续获取2秒,此时就会获取20张图片;

2.对这20张图片进行合成为GIF图片,并保存到相应路径下面;

3.对路径下面的GIF进行UIImageView播放;

由此可知,难点就在于视频帧的截取、图片的合成、以及imageView播放本地合成的gif的问题;


视频帧的截取:

        用到了AVURLAsset,根据videoPath生成AVURLAsset对象asset,根据asset创建AVAssetImageGenerator图片发生器对象,进行帧图片的生成:

首先来看一下一张帧图片的获取:

- (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;

}

这里我们需要注意一点:当我们不设置gen.requestedTimeToleranceAfter=kCMTimeZero;

gen.requestedTimeToleranceBefore=kCMTimeZero;的话,我们给定的time和结果的actualTime很有可能是不一致的(请看:传送门 ,当你指定要获取time时刻的帧,如果不设置这两个属性,系统会默认如果在指定time段内有缓存,就从缓存中直接返回结果,但并不准确,这是为了优化性能),如果我们需要精确时间的帧,就需要加上这两句代码;

顺便我们来了解一下CMTime,它一般有两种创建方式:第一种:CMTimeMake(value,timescale),value是当前第几帧,timescale是每秒的帧数,我们可由value/timescale得到视频总秒数seconds;第二种是:CMTimeMakeWithSeconds(second,timescale),可知second是当前时间,second*timescale就是second时间内的总帧数;可用CMTimeShow(actualTime)输出看一下;

fps是指画面每秒传输帧数,即帧率;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>框架

主要是每一帧图片的属性设置进行合成:

- (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进行动画:

- (NSArray*)sssss{

NSURL *gifImageUrl = _fileURL;//获取Gif图的原数据

CGImageSourceRef gifSource = CGImageSourceCreateWithURL((CFURLRef)gifImageUrl, NULL);    //获取Gif图有多少帧

size_t gifcount = CGImageSourceGetCount(gifSource);

NSMutableArray *imageS = [[NSMutableArray alloc] init];

for (NSInteger i = 0; i < gifcount; i++) {

//由数据源gifSource生成一张CGImageRef类型的图片

CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);

UIImage *image = [UIImage imageWithCGImage:imageRef];

[imageS addObject:image];        CGImageRelease(imageRef);    }

//得到图片数组

return imageS;

}

- (void)setgifImgView:(NSArray*)images{

//把数组图片通过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;//动画进行几次结束

[imageView startAnimating];//开始动画

imageView.userInteractionEnabled = YES;

[[UIApplication sharedApplication].keyWindow addSubview:imageView];

}

OK,图像的处理需要多了解CoreGraphics框架,多了解SDWebImage 图片处理机制;

上一篇下一篇

猜你喜欢

热点阅读