iOS gif 图片播放实现方法 (image 扩展方案)

原创 2016年05月31日 00:28:46

1 image 扩展方案:

1.导入头文件

#import <ImageIO/ImageIO.h>
#import <UIKit/UIKit.h>
#if __has_feature(objc_arc)
#define toCF (__bridge CFTypeRef)
#define fromCF (__bridge id)
#else
#define toCF (CFTypeRef)
#define fromCF (id)
#endif
/**
        UIImage (animatedGIF)

    This category adds class methods to `UIImage` to create an animated `UIImage` from an animated GIF.
*/
@interface UIImage (animatedGIF)

2.声明方法:

+ (UIImage * _Nullable)animatedImageWithAnimatedGIFData:(NSData * _Nonnull)theData;
+ (UIImage * _Nullable)animatedImageWithAnimatedGIFURL:(NSURL * _Nonnull)theURL;

3.实现方法:

@implementation UIImage (animatedGIF)

static int delayCentisecondsForImageAtIndex(CGImageSourceRef const source, size_t const i) {
    int delayCentiseconds = 1;
    CFDictionaryRef const properties = CGImageSourceCopyPropertiesAtIndex(source, i, NULL);
    if (properties) {
        CFDictionaryRef const gifProperties = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
        if (gifProperties) {
            NSNumber *number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime);
            if (number == NULL || [number doubleValue] == 0) {
                number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime);
            }
            if ([number doubleValue] > 0) {
                // Even though the GIF stores the delay as an integer number of centiseconds, ImageIO “helpfully” converts that to seconds for us.
                delayCentiseconds = (int)lrint([number doubleValue] * 100);
            }
        }
        CFRelease(properties);
    }
    return delayCentiseconds;
}

static void createImagesAndDelays(CGImageSourceRef source, size_t count, CGImageRef imagesOut[count], int delayCentisecondsOut[count]) {
    for (size_t i = 0; i < count; ++i) {
        imagesOut[i] = CGImageSourceCreateImageAtIndex(source, i, NULL);
        delayCentisecondsOut[i] = delayCentisecondsForImageAtIndex(source, i);
    }
}

static int sum(size_t const count, int const *const values) {
    int theSum = 0;
    for (size_t i = 0; i < count; ++i) {
        theSum += values[i];
    }
    return theSum;
}

static int pairGCD(int a, int b) {
    if (a < b)
        return pairGCD(b, a);
    while (true) {
        int const r = a % b;
        if (r == 0)
            return b;
        a = b;
        b = r;
    }
}

static int vectorGCD(size_t const count, int const *const values) {
    int gcd = values[0];
    for (size_t i = 1; i < count; ++i) {
        // Note that after I process the first few elements of the vector, `gcd` will probably be smaller than any remaining element.  By passing the smaller value as the second argument to `pairGCD`, I avoid making it swap the arguments.
        gcd = pairGCD(values[i], gcd);
    }
    return gcd;
}

static NSArray *frameArray(size_t const count, CGImageRef const images[count], int const delayCentiseconds[count], int const totalDurationCentiseconds) {
    int const gcd = vectorGCD(count, delayCentiseconds);
    size_t const frameCount = totalDurationCentiseconds / gcd;
    UIImage *frames[frameCount];
    for (size_t i = 0, f = 0; i < count; ++i) {
        UIImage *const frame = [UIImage imageWithCGImage:images[i]];
        for (size_t j = delayCentiseconds[i] / gcd; j > 0; --j) {
            frames[f++] = frame;
        }
    }
    return [NSArray arrayWithObjects:frames count:frameCount];
}

static void releaseImages(size_t const count, CGImageRef const images[count]) {
    for (size_t i = 0; i < count; ++i) {
        CGImageRelease(images[i]);
    }
}

static UIImage *animatedImageWithAnimatedGIFImageSource(CGImageSourceRef const source) {
    size_t const count = CGImageSourceGetCount(source);
    CGImageRef images[count];
    int delayCentiseconds[count]; // in centiseconds
    createImagesAndDelays(source, count, images, delayCentiseconds);
    int const totalDurationCentiseconds = sum(count, delayCentiseconds);
    NSArray *const frames = frameArray(count, images, delayCentiseconds, totalDurationCentiseconds);
    UIImage *const animation = [UIImage animatedImageWithImages:frames duration:(NSTimeInterval)totalDurationCentiseconds / 100.0];
    releaseImages(count, images);
    return animation;
}

static UIImage *animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceRef CF_RELEASES_ARGUMENT source) {
    if (source) {
        UIImage *const image = animatedImageWithAnimatedGIFImageSource(source);
        CFRelease(source);
        return image;
    } else {
        return nil;
    }
}

+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)data {
    return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithData(toCF data, NULL));
}

+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)url {
    return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL(toCF url, NULL));
}

@end

2 web view 方案(todo )

使用webview 直接加载gif 直接可以播放(代码有空再帖)

3 将gif分解为N张图片(todo)

然后导入工程依次播放.(代码有空再帖)

版权声明:本文为博主原创文章欢迎分享转载。

相关文章推荐

iOS 4种方法显示GIF

#pragma mark - Image content types /*  *  kUTTypeImage  *  *    abstract image data  *  *    U...

iOS知识 ----加载显示gif图片

iOS针对gif图片播放的问题,由于iOS无法直接播放gif图片,所以可以通过以下方式进行播放   UIImageView用来显示图片, 使用UIImageView中的动画数组来实现图片的动画...

IOS播放GIF图片

最近项目中需要播放GIF格式图片,很多软件现在都支持GIF格式图片播放,所以最开始以为很简单,UIImageView控件会自动播放GIF格式的图片,才发现是自己想简单了。后来上网查找了一些资料才找到方...

ios播放gif图片

以前一直听说ios不可以播放gif图片。也没取看看。其实想想有啥不能播放的。只是没有提供现成的api而已。最近看看资料以及别人的例子了解了一下实现原理 特记录一下: gif 其实本来就是一系列的图片...

iOS加载Gif图片的N种方式

1.系统UIImageView 多张图片组成动画 /** * UIImageView 动画 * Memory-23M */ -(void)gifPlay1 { // ...

iOS:GIF图片的预览以及生成

需求 需要在ios平台上实现GIF图片的展示以及生成 展示需求 通过调研发现有两种方式来实现 1. 根据gif的格式来自己解析出图片,或者使用ImageMagick这个库来做 ...

IOS显示gif图片,超简单方法

IOS 显示gif图片,超简单方法: 1.下载SCGIFImageView(源自网上的哪位大神我忘记了)我已标记哪里改播放速度了 http://pan.baidu.com/s/1jGDZg...

iOS播放Gif方案总结

iOS播放Gif最佳方案总结在iOS开发中常用的Gif播放有三种: 原生UIWebView播放 UIImageView逐帧播放 第三方GifView 当然最好的还是原生UIWebView播放,后面两种...

iOS 播放gif图片

不用任何第三方实现播放GIF图功能,可以单次播放,也可循环播放。如果用SDWebImage在网上下载下来的GIF图是循环播放的,如果需要指定比方次数,本篇一定对你有所帮助
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)