zoukankan      html  css  js  c++  java
  • iOS

    转:http://blog.csdn.net/marujunyy/article/details/14455699

    最近由于项目需要,需要先把gif图拆解开,然后在每一张图片上添加一些图片和文字,最后再合成gif文件;写了一个工具类可以每一帧画面并遵循每一帧所对应的显示时间进行播放,并且可以用多张图片指定每一帧播放时间来合成gif图。下面是使用方法和工具类:(需要添加framework : ImageIO、QuartzCore、MobileCoreServices

    1. NSDate *date = [NSDate date];  
    2. //读取本地GIF图中每一帧图像的信息  
    3. NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"demo" withExtension:@"gif"];  
    4. NSDictionary *dic = [GifView getGifInfo:fileUrl];  
    5.   
    6. NSMutableArray *imageArray = [NSMutableArray array];  
    7. //在gif图的每一帧上面添加一段文字  
    8. for(int index=0;index<[dic[@"images"] count];index++)  
    9. {  
    10.     //绘制view 已GIf图中的某一帧为背景并在view上添加文字  
    11.     UIView *tempView = [[UIView alloc] initWithFrame:CGRectFromString(dic[@"bounds"])];  
    12.     tempView.backgroundColor = [UIColor colorWithPatternImage:dic[@"images"][index]];  
    13.     UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, 80, 20)];  
    14.     tempLabel.text = @"GIF测试";  
    15.     tempLabel.textColor = [UIColor redColor];  
    16.     tempLabel.backgroundColor = [UIColor clearColor];  
    17.     tempLabel.font = [UIFont boldSystemFontOfSize:20];  
    18.     [tempView addSubview:tempLabel];  
    19.   
    20.     //将UIView转换为UIImage  
    21.     UIGraphicsBeginImageContextWithOptions(tempView.bounds.size, NO, tempView.layer.contentsScale);  
    22.     [tempView.layer renderInContext:UIGraphicsGetCurrentContext()];  
    23.     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();  
    24.     [imageArray addObject:image];  
    25.     UIGraphicsEndImageContext();  
    26. }  
    27. //生成GIF图 -- loopCount 为0表示无限播放  
    28. NSString *path = [GifView exportGifImages:[imageArray copy] delays:dic[@"delays"] loopCount:0];  
    29.   
    30. //在页面上展示合成之后的GIF图  
    31. GifView *gifView = [[GifView alloc] initWithCenter:self.view.center fileURL:[NSURL fileURLWithPath:path]];  
    32. [self.view addSubview:gifView];  
    33. NSLog(@"合成GIF图用时:%f秒",[[NSDate date] timeIntervalSinceDate:date]);  



    //GifView.h

    1. #import <UIKit/UIKit.h>  
    2.   
    3. @interface GifView : UIView  
    4.   
    5. /* 
    6.  * @brief desingated initializer 
    7.  */  
    8. - (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;  
    9. - (void)initFileURL:(NSURL*)fileURL;  
    10.   
    11. /* 
    12.  * @brief start Gif Animation 
    13.  */  
    14. - (void)startGif;  
    15. - (void)startGifAnimation;  
    16.   
    17. /* 
    18.  * @brief stop Gif Animation 
    19.  */  
    20. - (void)stopGif;  
    21.   
    22. /* 
    23.  * @brief get frames image(CGImageRef) in Gif 
    24.  */  
    25. + (NSDictionary *)getGifInfo:(NSURL *)fileURL;  
    26. + (NSString *)exportGifImages:(NSArray *)images delays:(NSArray *)delays loopCount:(NSUInteger)loopCount;  
    27.   
    28. @end  


    //GifView.m

    1. //  
    2. //  GifView.m  
    3. //  
    4. //  Created by marujun on 13-11-7.  
    5. //  Copyright (c) 2013年 极致. All rights reserved.  
    6. //  
    7.   
    8. #import "GifView.h"  
    9. #import <ImageIO/ImageIO.h>  
    10. #import <QuartzCore/QuartzCore.h>  
    11. #import <MobileCoreServices/MobileCoreServices.h>  
    12.   
    13.   
    14. @interface GifView() {  
    15.     NSMutableArray *_frames;  
    16.     NSMutableArray *_frameDelayTimes;  
    17.   
    18.     CGPoint frameCenter;  
    19.     CADisplayLink *displayLink;  
    20.     int frameIndex;  
    21.     double frameDelay;  
    22.   
    23.     NSUInteger _loopCount;  
    24.     NSUInteger _currentLoop;  
    25.     CGFloat _totalTime;         // seconds  
    26.     CGFloat _width;  
    27.     CGFloat _height;  
    28. }  
    29.   
    30. @end  
    31.   
    32. @implementation GifView  
    33.   
    34.   
    35. - (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;  
    36. {  
    37.     self = [super initWithFrame:CGRectZero];  
    38.     if (self) {  
    39.   
    40.         _frames = [[NSMutableArray alloc] init];  
    41.         _frameDelayTimes = [[NSMutableArray alloc] init];  
    42.   
    43.         _width = 0;  
    44.         _height = 0;  
    45.         frameCenter = center;  
    46.         [self initFileURL:fileURL];  
    47.     }  
    48.     return self;  
    49. }  
    50.   
    51. - (void)initFileURL:(NSURL*)fileURL  
    52. {  
    53.     if (fileURL) {  
    54.         getFrameInfo((__bridge CFURLRef)fileURL, _frames, _frameDelayTimes, &_totalTime, &_width, &_height, _loopCount);  
    55.     }  
    56.     self.frame = CGRectMake(0, 0, _width, _height);  
    57.     self.center = frameCenter;  
    58.     self.backgroundColor = [UIColor clearColor];  
    59.     if(_frames && _frames[0]){  
    60.         self.layer.contents = (__bridge id)([_frames[0] CGImage]);  
    61.     }  
    62. }  
    63.   
    64. //使用displayLink播放  
    65. - (void)startGif  
    66. {  
    67.     frameIndex = 0;  
    68.     _currentLoop = 1;  
    69.     frameDelay =[_frameDelayTimes[0] doubleValue];  
    70.   
    71.     [self stopGif];  
    72.     displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateDisplay:)];  
    73.     [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  
    74. }  
    75. //每秒60帧刷新视图  
    76. - (void)updateDisplay:(CADisplayLink *)link  
    77. {  
    78.     if(frameDelay<=0){  
    79.         frameIndex ++;  
    80.         if(_loopCount!=0){  
    81.             if (_currentLoop>=_loopCount) {  
    82.                 [self stopGif];  
    83.             }else{  
    84.                 _currentLoop ++;  
    85.             }  
    86.         }  
    87.         if(frameIndex>=_frames.count){  
    88.             frameIndex = 0;  
    89.         }  
    90.         frameDelay = [_frameDelayTimes[frameIndex] doubleValue]+frameDelay;  
    91.         self.layer.contents = (__bridge id)([_frames[frameIndex] CGImage]);  
    92.     }  
    93.     frameDelay -= fmin(displayLink.duration, 1);   //To avoid spiral-o-death  
    94. }  
    95.   
    96. - (void)willMoveToSuperview:(UIView *)newSuperview  
    97. {  
    98.     if(newSuperview){  
    99.         [self startGif];  
    100.     }else{  
    101.         [self stopGif];  //视图将被移除  
    102.     }  
    103. }  
    104.   
    105. //使用Animation方式播放Gif  
    106. - (void)startGifAnimation  
    107. {  
    108.     [self stopGif];  
    109.   
    110.     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];  
    111.   
    112.     NSMutableArray *times = [NSMutableArray arrayWithCapacity:3];  
    113.     CGFloat currentTime = 0;  
    114.     int count = _frameDelayTimes.count;  
    115.     for (int i = 0; i < count; ++i) {  
    116.         [times addObject:[NSNumber numberWithFloat:(currentTime / _totalTime)]];  
    117.         currentTime += [[_frameDelayTimes objectAtIndex:i] floatValue];  
    118.     }  
    119.     [animation setKeyTimes:times];  
    120.   
    121.     NSMutableArray *images = [NSMutableArray arrayWithCapacity:3];  
    122.     for (int i = 0; i < count; ++i) {  
    123.         [images addObject:(__bridge id)[[_frames objectAtIndex:i] CGImage]];  
    124.     }  
    125.   
    126.     [animation setValues:images];  
    127.     [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];  
    128.     animation.duration = _totalTime;  
    129.     animation.delegate = self;  
    130.     if(_loopCount<=0){  
    131.         animation.repeatCount = INFINITY;  
    132.     }else{  
    133.         animation.repeatCount = _loopCount;  
    134.     }  
    135.     [self.layer addAnimation:animation forKey:@"gifAnimation"];  
    136. }  
    137.   
    138. - (void)stopGif  
    139. {  
    140.     [self.layer removeAllAnimations];  
    141.     [self removeDisplayLink];  
    142.   
    143.     if(_frames && _frames[0]){  
    144.         self.layer.contents = (__bridge id)([_frames[0] CGImage]);  
    145.     }  
    146. }  
    147.   
    148. - (void)removeDisplayLink  
    149. {  
    150.     [displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  
    151.     [displayLink invalidate];  
    152.     displayLink = nil;  
    153. }  
    154.   
    155. // remove contents when animation end  
    156. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag  
    157. {  
    158.     if(_frames && _frames[0]){  
    159.         self.layer.contents = (__bridge id)([_frames[0] CGImage]);  
    160.     }  
    161. }  
    162.   
    163. /* 
    164.  * @brief 获取gif图中每一帧的信息 
    165.  */  
    166. + (NSDictionary *)getGifInfo:(NSURL *)fileURL  
    167. {  
    168.     NSMutableArray *frames = [NSMutableArray arrayWithCapacity:3];  
    169.     NSMutableArray *delays = [NSMutableArray arrayWithCapacity:3];  
    170.     NSUInteger loopCount = 0;  
    171.     CGFloat totalTime;         // seconds  
    172.     CGFloat width;  
    173.     CGFloat height;  
    174.   
    175.     getFrameInfo((__bridge CFURLRef)fileURL, frames, delays, &totalTime, &width, &height, loopCount);  
    176.     NSDictionary *gifDic = @{@"images":frames,          //图片数组  
    177.                              @"delays":delays,          //每一帧对应的延迟时间数组  
    178.                              @"duration":@(totalTime),  //GIF图播放一遍的总时间  
    179.                              @"loopCount":@(loopCount), //GIF图播放次数  0-无限播放  
    180.                              @"bounds": NSStringFromCGRect(CGRectMake(0, 0, width, height))}; //GIF图的宽高  
    181.     return gifDic;  
    182. }  
    183. /* 
    184.  * @brief 指定每一帧播放时长把多张图片合成gif图 
    185.  */  
    186. + (NSString *)exportGifImages:(NSArray *)images delays:(NSArray *)delays loopCount:(NSUInteger)loopCount  
    187. {  
    188.     NSString *fileName = [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"gif"];  
    189.     NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];  
    190.     CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:filePath],  
    191.                                                                         kUTTypeGIF, images.count, NULL);  
    192.     if(!loopCount){  
    193.         loopCount = 0;  
    194.     }  
    195.     NSDictionary *gifProperties = @{ (__bridge id)kCGImagePropertyGIFDictionary: @{  
    196.                                                (__bridge id)kCGImagePropertyGIFLoopCount: @(loopCount), // 0 means loop forever  
    197.                                                }  
    198.                                        };  
    199.     float delay = 0.1; //默认每一帧间隔0.1秒  
    200.     for (int i=0; i<images.count; i++) {  
    201.         UIImage *itemImage = images[i];  
    202.         if(delays && i<delays.count){  
    203.             delay = [delays[i] floatValue];  
    204.         }  
    205.         //每一帧对应的延迟时间  
    206.         NSDictionary *frameProperties = @{(__bridge id)kCGImagePropertyGIFDictionary: @{  
    207.                                                   (__bridge id)kCGImagePropertyGIFDelayTime: @(delay), // a float (not double!) in seconds, rounded to centiseconds in the GIF data  
    208.                                                   }  
    209.                                           };  
    210.         CGImageDestinationAddImage(destination,itemImage.CGImage, (__bridge CFDictionaryRef)frameProperties);  
    211.     }  
    212.     CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)gifProperties);  
    213.     if (!CGImageDestinationFinalize(destination)) {  
    214.         NSLog(@"failed to finalize image destination");  
    215.     }  
    216.     CFRelease(destination);  
    217.     return filePath;  
    218. }  
    219.   
    220. /* 
    221.  * @brief resolving gif information 
    222.  */  
    223. void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime,CGFloat *gifWidth, CGFloat *gifHeight,NSUInteger loopCount)  
    224. {  
    225.     CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);  
    226.   
    227.     //获取gif的帧数  
    228.     size_t frameCount = CGImageSourceGetCount(gifSource);  
    229.   
    230.     //获取GfiImage的基本数据  
    231.     NSDictionary *gifProperties = (__bridge NSDictionary *) CGImageSourceCopyProperties(gifSource, NULL);  
    232.     //由GfiImage的基本数据获取gif数据  
    233.     NSDictionary *gifDictionary =[gifProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];  
    234.     //获取gif的播放次数 0-无限播放  
    235.     loopCount = [[gifDictionary objectForKey:(NSString*)kCGImagePropertyGIFLoopCount] integerValue];  
    236.     CFRelease((__bridge CFTypeRef)(gifProperties));  
    237.   
    238.     for (size_t i = 0; i < frameCount; ++i) {  
    239.         //得到每一帧的CGImage  
    240.         CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);  
    241.         [frames addObject:[UIImage imageWithCGImage:frame]];  
    242.         CGImageRelease(frame);  
    243.   
    244.         //获取每一帧的图片信息  
    245.         NSDictionary *frameDict = (__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);  
    246.   
    247.         //获取Gif图片尺寸  
    248.         if (gifWidth != NULL && gifHeight != NULL) {  
    249.             *gifWidth = [[frameDict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];  
    250.             *gifHeight = [[frameDict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];  
    251.         }  
    252.   
    253.         //由每一帧的图片信息获取gif信息  
    254.         NSDictionary *gifDict = [frameDict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];  
    255.         //取出每一帧的delaytime  
    256.         [delayTimes addObject:[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime]];  
    257.   
    258.         if (totalTime) {  
    259.             *totalTime = *totalTime + [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];  
    260.         }  
    261.         CFRelease((__bridge CFTypeRef)(frameDict));  
    262.     }  
    263.     CFRelease(gifSource);  
    264. }  
    265.   
    266. - (void)dealloc  
    267. {  
    268.     NSLog(@"%s",__FUNCTION__);  
    269. }  
    270.   
    271. @end  


    参考:http://stackoverflow.com/questions/14915138/create-and-and-export-an-animated-gif-via-ios


  • 相关阅读:
    动态类型
    unlink与close关系
    Google 历年笔试面试30题
    UNIX网络编程 卷2 源代码使用
    centos安装telnet
    python中安装第三方模块
    Linux平台 Oracle 18c RAC安装Part1:准备工作
    RHEL7 配置iSCSI模拟环境
    Solaris 10主机名和IP地址步骤
    设置sqlplus不显示除查询结果外的信息
  • 原文地址:https://www.cnblogs.com/jackljf/p/4768602.html
Copyright © 2011-2022 走看看