iOS:長圖切割并轉(zhuǎn)為動畫gif——精靈表單sprite Sheet的轉(zhuǎn)化
通常的,iOS顯示gif可以將文件轉(zhuǎn)為NSData
后再對其進(jìn)行解析,通過CADisplayLink
逐幀進(jìn)行提取流部、播放,判斷NSData
是否為gif圖的方法如下:
-(void)isGifData:(NSData *)data {
BOOL hasData = ([data length] > 0);
if (!hasData) {
return NO;
}
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data,
(__bridge CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache: @NO});
// Early return on failure!
if (!imageSource) {
return NO;
}
// Early return if not GIF!
//關(guān)鍵未知
CFStringRef imageSourceContainerType = CGImageSourceGetType(imageSource);
BOOL isGIFData = UTTypeConformsTo(imageSourceContainerType, kUTTypeGIF);
return isGIFData;
}
///參考第三方庫FLAnimatedImage中FLAniamtedImage.m
///- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled
(此方法稍微改造一下還可以同時識別PNG/JPEG)
而精靈表單的本質(zhì)上是一張大的圖片,是將所有幀的圖像堆到同一張圖片里,只需要在一定間隔內(nèi)讀取指定小區(qū)域的照片歇竟,利用人眼視覺殘留的特性,即可呈現(xiàn)動畫效果抵恋,本文將探討如何將此類圖轉(zhuǎn)為gif焕议。
//相關(guān)參數(shù),根據(jù)實(shí)際情況自行賦值,省略
CGFloat frameDurations;//幀間隔,單位為秒
NSMutableArray <NSValue *>* frameRects;//每一幀在大圖中的區(qū)域
NSURL *savePathURL;//保存gif圖片地址
UIImage *image;//sprite sheet大圖
//gif圖的參數(shù)
NSDictionary *fileSetting = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
}
};
NSDictionary *frameSetting = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFDelayTime: @(frameDurations), // a float (not double!) in seconds, rounded to centiseconds in the GIF data
}
};
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)savePathURL, kUTTypeGIF, frameRects.count, NULL);
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileSetting);
//開始處理
for (int i = 0; i < frameRects.count; i ++) {
CGRect rect = contentRects[i].CGRectValue;
@autoreleasepool {
//及時釋放循環(huán)中累計的內(nèi)存
CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
CGImageDestinationAddImage(destination, subImageRef, (__bridge CFDictionaryRef)frameSetting);
CGImageRelease(subImageRef);
}
}
//善后
if (!CGImageDestinationFinalize(destination)) {
NSLog(@"failed to finalize image destination");
}
CFRelease(destination);
//生成gif
NSData *fileData = [[NSData alloc] initWithContentsOfURL:savePathURL];
//根據(jù)情況是否刪除緩存文件
此段代碼參考從視頻中截取縮略圖生成gif圖片
還可以改進(jìn)的地方:文中實(shí)現(xiàn)了圖片->gif類型data的轉(zhuǎn)換弧关,需要將整個動畫生成后才能對其做下一步的操作(比如顯示動畫)盅安,但實(shí)際上我們還可以通過CADisplayLink實(shí)時顯示截取對應(yīng)幀數(shù)的區(qū)域.