`
jsntghf
  • 浏览: 2542548 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

将gif转换成animated gif

    博客分类:
  • iOS
阅读更多

AnimatedGif.h

 

#ifdef TARGET_OS_IPHONE			
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif TARGET_OS_IPHONE	

@interface AnimatedGifQueueObject : NSObject {
    UIImageView *uiv;
    NSURL *url;
}

@property (nonatomic, retain) UIImageView *uiv;
@property (nonatomic, retain) NSURL *url;

@end

@interface AnimatedGif : NSObject {
	NSData *GIF_pointer;
	NSMutableData *GIF_buffer;
	NSMutableData *GIF_screen;
	NSMutableData *GIF_global;
	NSMutableData *GIF_frameHeader;
	
	NSMutableArray *GIF_delays;
	NSMutableArray *GIF_framesData;
    
    NSMutableArray *imageQueue;
	bool busyDecoding;
	
	int GIF_sorted;
	int GIF_colorS;
	int GIF_colorC;
	int GIF_colorF;
	int animatedGifDelay;
	
	int dataPointer;
    
    UIImageView *imageView;
}

@property (nonatomic, retain) UIImageView *imageView;
@property bool busyDecoding;

- (void) addToQueue: (AnimatedGifQueueObject *) agqo;
+ (UIImageView *) getAnimationForGifAtUrl: (NSURL *) animationUrl;
- (void) decodeGIF:(NSData *)GIF_Data;
- (void) GIFReadExtensions;
- (void) GIFReadDescriptor;
- (bool) GIFGetBytes:(int)length;
- (bool) GIFSkipBytes: (int) length;
- (NSMutableData *) getFrameAsDataAtIndex:(int)index;
- (UIImage *) getFrameAsImageAtIndex:(int)index;
- (UIImageView *) getAnimation;

@end

 

AnimatedGif.m

 

#import "AnimatedGif.h"

@implementation AnimatedGifQueueObject

@synthesize uiv;
@synthesize url;

@end

@implementation AnimatedGif

static AnimatedGif *instance;

@synthesize imageView;
@synthesize busyDecoding;

+ (AnimatedGif *) sharedInstance {
    if (instance == nil) {
        instance = [[AnimatedGif alloc] init];
    }
    
    return instance;
}

+ (UIImageView *) getAnimationForGifAtUrl:(NSURL *)animationUrl {   
    AnimatedGifQueueObject *agqo = [[AnimatedGifQueueObject alloc] init];
    [agqo setUiv: [[UIImageView alloc] init]];
    [[agqo uiv] autorelease]; 
    [agqo setUrl: animationUrl]; 
    [[AnimatedGif sharedInstance] addToQueue: agqo];
    [agqo release];
    
    if ([[AnimatedGif sharedInstance] busyDecoding] != YES) {
        [[AnimatedGif sharedInstance] setBusyDecoding: YES];
        [[AnimatedGif sharedInstance] performSelector:@selector(asynchronousLoading) withObject:nil afterDelay:0.0];
    }
    
    return [agqo uiv];
}

- (void) asynchronousLoading {
	while ([imageQueue count] > 0) {
    	NSData *data = [NSData dataWithContentsOfURL: [(AnimatedGifQueueObject *) [imageQueue objectAtIndex: 0] url]];
        imageView = [[imageQueue objectAtIndex: 0] uiv];
    	[self decodeGIF: data];
   	 	UIImageView *tempImageView = [self getAnimation];
   	 	[imageView setImage: [tempImageView image]];
    	[imageView sizeToFit];
    	[imageView setAnimationImages: [tempImageView animationImages]];
    	[imageView startAnimating];
        [imageQueue removeObjectAtIndex:0];
    }
    busyDecoding = NO;
}

- (void) addToQueue: (AnimatedGifQueueObject *) agqo {
    [imageQueue addObject: agqo];
}

- (id) init {
    if (self = [super init])
    {
        imageQueue = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)decodeGIF:(NSData *)GIFData {
	GIF_pointer = GIFData;
    
    if (GIF_buffer != nil) {
        [GIF_buffer release];
    }
    
    if (GIF_global != nil) {
        [GIF_global release];
    }
    
    if (GIF_screen != nil) {
        [GIF_screen release];
    }
    
	if (GIF_delays != nil) {
        [GIF_delays release];
    }
    
    if (GIF_framesData != nil) {
        [GIF_framesData release];
    }
    
    GIF_buffer = [[NSMutableData alloc] init];
	GIF_global = [[NSMutableData alloc] init];
	GIF_screen = [[NSMutableData alloc] init];
	GIF_frameHeader = nil;
    
	GIF_delays = [[NSMutableArray alloc] init];
	GIF_framesData = [[NSMutableArray alloc] init];
    
	dataPointer = 0;
	
	[self GIFSkipBytes: 6]; 
	[self GIFGetBytes: 7]; 
	
	[GIF_screen setData: GIF_buffer];
	
    int length = [GIF_buffer length];
	unsigned char aBuffer[length];
	[GIF_buffer getBytes:aBuffer length:length];
	
	if (aBuffer[4] & 0x80) GIF_colorF = 1; else GIF_colorF = 0; 
	if (aBuffer[4] & 0x08) GIF_sorted = 1; else GIF_sorted = 0;
	GIF_colorC = (aBuffer[4] & 0x07);
	GIF_colorS = 2 << GIF_colorC;
	
	if (GIF_colorF == 1) {
		[self GIFGetBytes: (3 * GIF_colorS)];
		[GIF_global setData:GIF_buffer];
	}
	
	unsigned char bBuffer[1];
	while ([self GIFGetBytes:1] == YES) {
        [GIF_buffer getBytes:bBuffer length:1];
        
        if (bBuffer[0] == 0x3B) { 
            break;
        }
        
        switch (bBuffer[0]) {
            case 0x21:
                [self GIFReadExtensions];
                break;
            case 0x2C:
                [self GIFReadDescriptor];
                break;
        }
	}
	
	[GIF_buffer release];
    GIF_buffer = nil;
    
	[GIF_screen release];
    GIF_screen = nil;
    
	[GIF_global release];	
    GIF_global = nil;
}

- (NSMutableData *) getFrameAsDataAtIndex:(int)index {
	if (index < [GIF_framesData count]) {
		return [GIF_framesData objectAtIndex:index];
	} else {
		return nil;
	}
}

- (UIImage *) getFrameAsImageAtIndex:(int)index {
    NSData *frameData = [self getFrameAsDataAtIndex: index];
    UIImage *image = nil;
    
    if (frameData != nil) {
		image = [UIImage imageWithData:frameData];
    }    
    return image;
}

- (UIImageView *) getAnimation {
	if ([GIF_framesData count] > 0) {
        if (imageView != nil) {
            [imageView setImage:[self getFrameAsImageAtIndex:0]];
            [imageView sizeToFit];
        } else {
            imageView = [[UIImageView alloc] initWithImage:[self getFrameAsImageAtIndex:0]];
        }
        
		NSMutableArray *array = [[NSMutableArray alloc] init];
		for (int i = 0; i < [GIF_framesData count]; i++) {		
			[array addObject: [self getFrameAsImageAtIndex:i]];
		}
		
		[imageView setAnimationImages:array];
        [array release];
        
		double total = 0;
		for (int i = 0; i < [GIF_delays count]; i++) {
			total += [[GIF_delays objectAtIndex:i] doubleValue];
		}
        
		[imageView setAnimationDuration:total / 100];
		[imageView setAnimationRepeatCount:0];
        [imageView startAnimating];
        [imageView autorelease];
        
		return imageView;
	} else {
		return nil;
	}
}

- (void)GIFReadExtensions {
	unsigned char cur[1], prev[1];
    [self GIFGetBytes:1];
    [GIF_buffer getBytes:cur length:1];
    
	while (cur[0] != 0x00) {
		if (cur[0] == 0x04 && prev[0] == 0xF9) {
			[self GIFGetBytes:5];
            
			unsigned char buffer[5];
			[GIF_buffer getBytes:buffer length:5];
            
			[GIF_delays addObject:[NSNumber numberWithInt:(buffer[1] | buffer[2] << 8)]];
            
			if (GIF_frameHeader == nil) {
			    unsigned char board[8];
				board[0] = 0x21;
				board[1] = 0xF9;
				board[2] = 0x04;
				
				for(int i = 3, a = 0; a < 5; i++, a++) {
					board[i] = buffer[a];
				}
                
				GIF_frameHeader = [NSMutableData dataWithBytes:board length:8];
			}            
			break;
		}		
		prev[0] = cur[0];
        [self GIFGetBytes:1];
		[GIF_buffer getBytes:cur length:1];
	}	
}

- (void) GIFReadDescriptor {	
	[self GIFGetBytes:9];
    
	NSMutableData *GIF_screenTmp = [NSMutableData dataWithData:GIF_buffer];
	
	unsigned char aBuffer[9];
	[GIF_buffer getBytes:aBuffer length:9];
	
	if (aBuffer[8] & 0x80) GIF_colorF = 1; else GIF_colorF = 0;
	
	unsigned char GIF_code = GIF_colorC, GIF_sort = GIF_sorted;
	
	if (GIF_colorF == 1) {
		GIF_code = (aBuffer[8] & 0x07);
        
		if (aBuffer[8] & 0x20) {
            GIF_sort = 1;
        } else {
        	GIF_sort = 0;
        }
	}
	
	int GIF_size = (2 << GIF_code);
	
	size_t blength = [GIF_screen length];
	unsigned char bBuffer[blength];
	[GIF_screen getBytes:bBuffer length:blength];
	
	bBuffer[4] = (bBuffer[4] & 0x70);
	bBuffer[4] = (bBuffer[4] | 0x80);
	bBuffer[4] = (bBuffer[4] | GIF_code);
	
	if (GIF_sort) {
		bBuffer[4] |= 0x08;
	}
	
    NSMutableData *GIF_string = [NSMutableData dataWithData:[[NSString stringWithString:@"GIF89a"] dataUsingEncoding: NSUTF8StringEncoding]];
	[GIF_screen setData:[NSData dataWithBytes:bBuffer length:blength]];
    [GIF_string appendData: GIF_screen];	
	
	if (GIF_colorF == 1) {
		[self GIFGetBytes:(3 * GIF_size)];
        [GIF_string appendData: GIF_buffer];
	} else {
		[GIF_string appendData: GIF_global];
	}
    
	[GIF_string appendData:GIF_frameHeader];
	
	char endC = 0x2c;
	[GIF_string appendBytes:&endC length:sizeof(endC)];
	
	size_t clength = [GIF_screenTmp length];
	unsigned char cBuffer[clength];
	[GIF_screenTmp getBytes:cBuffer length:clength];
	
	cBuffer[8] &= 0x40;
	
	[GIF_screenTmp setData:[NSData dataWithBytes:cBuffer length:clength]];
	
	[GIF_string appendData: GIF_screenTmp];
	[self GIFGetBytes:1];
	[GIF_string appendData: GIF_buffer];
	
	while (true) {
		[self GIFGetBytes:1];
		[GIF_string appendData: GIF_buffer];
		
		unsigned char dBuffer[1];
		[GIF_buffer getBytes:dBuffer length:1];
		
		long u = (long) dBuffer[0];
        
		if (u != 0x00) {
			[self GIFGetBytes:u];
			[GIF_string appendData: GIF_buffer];
        } else {
            break;
        }
	}
	
	endC = 0x3b;
	[GIF_string appendBytes:&endC length:sizeof(endC)];
    
	[GIF_framesData addObject:[GIF_string copy]];
}

- (bool) GIFGetBytes: (int) length {
    if (GIF_buffer != nil) {
        [GIF_buffer release]; 
        GIF_buffer = nil;
    }
    
	if ([GIF_pointer length] >= dataPointer + length) {
		GIF_buffer = [[GIF_pointer subdataWithRange:NSMakeRange(dataPointer, length)] retain];
        dataPointer += length;
		return YES;
	} else {
        return NO;
	}
}

- (bool) GIFSkipBytes: (int) length {
    if ([GIF_pointer length] >= dataPointer + length) {
        dataPointer += length;
        return YES;
    } else {
    	return NO;
    }
}

- (void) dealloc {
    if (GIF_buffer != nil) {
	    [GIF_buffer release];
    }
    
    if (GIF_screen != nil) {
		[GIF_screen release];
    }
    
    if (GIF_global != nil) {
        [GIF_global release];
    }
    
    if (GIF_delays != nil) {
		[GIF_delays release];
    }
    
    if (GIF_framesData != nil) {
		[GIF_framesData release];
    }
    
	[super dealloc];
}

@end

 

示例:

 

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"logo" ofType:@"gif"]];
UIImageView *animationGif = [AnimatedGif getAnimationForGifAtUrl: url];
[animatedGifImageView addSubview:animationGif];
分享到:
评论

相关推荐

    c#制作gif动图

    在这个例子中,`Gif_Animate.dll`是一个专门处理GIF动画的库,可能包含了将图片序列合并成GIF的函数或类。 3. **GIF编码与解码**:GIF是一种支持多帧的图像格式,用于创建动画效果。编码GIF涉及到对每帧图像的时间...

    动画Gif捕获「Animated Gif Capture」-crx插件

    动画Gif捕获Chrome扩展程序可帮助您将屏幕捕获转换为动画GIF图像。 将选项卡,桌面屏幕或选定的应用程序窗口的可见内容捕获为GIF动画图像。 特征。 -添加浏览器操作以捕获屏幕。 -可通过选项页面进行配置。 工作原理...

    matlab开发-AnimatedGIF

    然后,用`frame2im`将帧转换为图像矩阵,准备写入GIF。 ```matlab frames = cell(1, numFrames); % 用于存储所有帧 for i = 1:numFrames % 插入绘制代码,例如 plot(x, y) 或 imagesc(data) frames{i} = frame...

    Animated Gif Capture-crx插件

    动画Gif捕获Chrome扩展程序可帮助您将屏幕捕获转换为动画GIF图像。 将选项卡,桌面屏幕或选定的应用程序窗口的可见内容捕获为GIF动画图像。 特征。 -添加浏览器操作以捕获屏幕。 -可通过选项页面进行配置。 工作原理...

    Convert Animated Gifs to single .BMP or .GIF Used .OCX Bmp2G

    综上所述,这个压缩包提供了一整套解决方案,用于将动画GIF转换为单一的BMP或GIF文件,包括所需的ActiveX控件和一个用户友好的图形界面。用户可以通过运行Anima_Extractor.exe来执行转换,而源代码则可供开发者研究...

    PHP脚本对gif图片进行分解

    因此,如果选择GD库,我们需要借助第三方库,如`AnimatedGIF`,来实现这个功能。 2. **Imagick扩展**:Imagick是PHP的一个强大扩展,基于ImageMagick图像处理库。它不仅支持GIF的读取、写入,还支持分解GIF动画。...

    gif的实现 object-c

    首先,你需要将每个帧的`UIImage`转换为`CGImage`,然后通过`CGImageSourceCreateWithImagesAndProperties`创建一个包含所有帧的`CGImageSourceRef`。最后,用`CGImageDestinationCreateWithData`创建一个`...

    tgs-to-gif:将动画电报贴纸(* .tgs)转换为动画GIF(.gif)

    电报(* .tgs)到动画GIF转换器的动画贴纸 要将贴纸轻松转换为GIF,可以使用Telegram Bot :backhand_index_pointing_right: :backhand_index_pointing_left: 仅供参考: 分支中有一个用C ++编写的转换器测试版本。 ...

    MATLAB 动画生成gif图片

    在MATLAB中生成动画并将其转化为GIF图片是一项常见的任务,尤其对于数据可视化和科学研究非常有用。MATLAB虽然默认支持创建动画,但直接生成GIF格式的图片却并不直观。这个压缩包提供了一个小程序,旨在解决MATLAB不...

    animated-gif-script

    强烈建议您不要将文件保存在此脚本使用的文件夹中(默认情况下:$ {HOME} / Images / norben_animated_gifs)用法打开一个终端,然后运行以下命令: / &lt; path&gt; / &lt; to&gt; /manual_selection.sh (可选)您可以使用alt...

    swift-LivelyGIFs展示LivePhoto并导出成Gif的一个App

    - **GIF编码库**:在将Live Photo转换为GIF时,可能需要使用如`UIImage Animated GIF`这样的第三方库来实现GIF的编码。这些库可以解析Live Photo的视频部分,并生成一系列帧,然后将这些帧编码成GIF格式。 3. **...

    js实现GIF图片的分解和合成

    首先,分解GIF图片是将一个动态的GIF文件转化为一系列静态的帧图像。这里需要用到两个关键的第三方库:`libgif.js`用于分解GIF,`gif.js`则用于合成GIF。以下是分解GIF的步骤: 1. 引入`libgif.js`库。这个库提供了...

    js实现GIF动图分解成多帧图片上传

    在JavaScript开发中,有时我们需要处理动态GIF图像,例如在上传GIF时将其分解成多帧图片以便逐一显示。为了实现这一功能,我们可以利用第三方库libgif-js。本篇文章将详细讲解如何使用JavaScript来实现GIF动图分解并...

    animatedgif2e131:获取视频文件并使用节点将其输出到用于照明网格的 e131(sAcn) 协议

    将其转换为动画 gif,然后输出到 sAcn (E1.31) 默认情况下支持常见的蛇形布线 - 提供以您喜欢的任何方式映射的功能包括一个全面的测试套件##用法命令行Usage: animatedgif2e131 [options] &lt; file&gt; Options: -h, --...

    iOS之加载Gif图片的方法

    你可以通过`NSURL`和`NSURLRequest`将本地Gif文件路径转化为请求加载。例如: ```objc UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,200,200)]; [self.view addSubview:webView]; ...

    Node.js-ttystudio-记录您的终端并编译一个GIF或APNG没有任何外部依赖bash脚本GIF连接等等

    Node.js-ttystudio 是一个强大的开源工具,专为开发者设计,用于记录终端会话并将其转化为GIF或APNG格式的动画,无需依赖任何外部程序。这个工具基于Node.js,通过bash脚本实现,为那些想要在演示、教程或文档中展示...

    screengif:创建动画gif截屏视频

    将SCREENCAST.mov转换为ANIMATED.gif的命令行工具 将其应用于会发生以下情况 用法 screengif - Convert your screencast into a gif. Usage: screengif [options] [--input FILENAME.mov] [--output OUTPUTFILE....

    movtogif-cli:将movmp4转换为高质量的gif动画

    我正在手动使用和从QuickTime mov / mp4生成动画gif。 我创建了这个简单的cli,使我的生活更轻松。 我使用此工具拍摄交互式UI的快照并附加到拉取请求中。 默认选项针对质量和文件大小进行了优化。 公开的唯一选项是...

    jQuery实现点击静态图片变gif动态图片预览效果源码.zip

    var gifUrl = 'path/to/animated/gif.gif'; $(this).attr('src', gifUrl); ``` 4. **动画效果**:为了提升用户体验,我们可以添加一些过渡动画。例如,可以使用jQuery的`fadeIn`或`fadeOut`方法在切换图片时创建...

    PDF to GIF Converter-crx插件

    立即从首页和新标签页将PDF文档转换为Animated GIF或Simple GIF! 什么是PDF解决方案转换器? 我们了解处理pdf文件时遇到的麻烦,并且没有合适的软件来查看或转换这些文件。 Free PDF Solutions的我们使转换对所有...

Global site tag (gtag.js) - Google Analytics