iOS_后缀为gif的图片显示


1、使用ImageView显示gif, 拖到项目,添加-fno-objc-arc


使用方法:

NSString* filePath = [[NSBundle mainBundle] pathForResource:@"a1.gif" ofType:nil];
    SGGIFImageView* gifImageView = [[SGGIFImageView alloc] initWithGIFFile:filePath] ;
    
    
    
    gifImageView.frame = CGRectMake(0, 0, gifImageView.image.size.width, gifImageView.image.size.height);
//    gifImageView.center = self.view.center;
    [self.view addSubview:gifImageView];


类文件如下:

//
//  SGGIFImageView.h
//  NiHongGo
//
//  Created by beyond on 16/4/3.
//  Copyright (c) 2016年 beyond. All rights reserved.
//  拖到项目,添加-fno-objc-arc

#import <UIKit/UIKit.h>

@interface AnimatedGifFrame : NSObject
{
    NSData *data;
    NSData *header;
    double delay;
    int disposalMethod;
    CGRect area;
}

@property (nonatomic, copy) NSData *header;
@property (nonatomic, copy) NSData *data;
@property (nonatomic) double delay;
@property (nonatomic) int disposalMethod;
@property (nonatomic) CGRect area;

@end

@interface SGGIFImageView : UIImageView {
    NSData *GIF_pointer;
    NSMutableData *GIF_buffer;
    NSMutableData *GIF_screen;
    NSMutableData *GIF_global;
    NSMutableArray *GIF_frames;
    
    int GIF_sorted;
    int GIF_colorS;
    int GIF_colorC;
    int GIF_colorF;
    int animatedGifDelay;
    
    int dataPointer;
}
@property (nonatomic, retain) NSMutableArray *GIF_frames;

- (id)initWithGIFFile:(NSString*)gifFilePath;
- (id)initWithGIFData:(NSData*)gifImageData;

- (void)loadImageData;

+ (NSMutableArray*)getGifFrames:(NSData*)gifImageData;
+ (BOOL)isGifImage:(NSData*)imageData;

- (void) decodeGIF:(NSData *)GIFData;
- (void) GIFReadExtensions;
- (void) GIFReadDescriptor;
- (bool) GIFGetBytes:(int)length;
- (bool) GIFSkipBytes: (int) length;
- (NSData*) getFrameAsDataAtIndex:(int)index;
- (UIImage*) getFrameAsImageAtIndex:(int)index;

@end


//
//  SGGIFImageView.m
//  NiHongGo
//
//  Created by beyond on 16/4/3.
//  Copyright (c) 2016年 beyond. All rights reserved.
//

#import "SGGIFImageView.h"

@implementation AnimatedGifFrame

@synthesize data, delay, disposalMethod, area, header;

- (void) dealloc
{
    [data release];
    [header release];
    [super dealloc];
}

@end

@implementation SGGIFImageView
@synthesize GIF_frames;

+ (BOOL)isGifImage:(NSData*)imageData {
    const char* buf = (const char*)[imageData bytes];
    if (buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 && buf[3] == 0x38) {
        return YES;
    }
    return NO;
}

+ (NSMutableArray*)getGifFrames:(NSData*)gifImageData {
    SGGIFImageView* gifImageView = [[SGGIFImageView alloc] initWithGIFData:gifImageData];
    if (!gifImageView) {
        return nil;
    }
    
    NSMutableArray* gifFrames = gifImageView.GIF_frames;
    [[gifFrames retain] autorelease];
    [gifImageView release];
    return gifFrames;
}

- (id)initWithGIFFile:(NSString*)gifFilePath {
    NSData* imageData = [NSData dataWithContentsOfFile:gifFilePath];
    return [self initWithGIFData:imageData];
}

- (id)initWithGIFData:(NSData*)gifImageData {
    if (gifImageData.length < 4) {
        return nil;
    }
    
    if (![SGGIFImageView isGifImage:gifImageData]) {
        UIImage* image = [UIImage imageWithData:gifImageData];
        return [super initWithImage:image];
    }
    
    [self decodeGIF:gifImageData];
    
    if (GIF_frames.count <= 0) {
        UIImage* image = [UIImage imageWithData:gifImageData];
        return [super initWithImage:image];
    }
    
    self = [super init];
    if (self) {
        [self loadImageData];
    }
    
    return self;
}

- (void)setGIF_frames:(NSMutableArray *)gifFrames {
    [gifFrames retain];
    
    if (GIF_frames) {
        [GIF_frames release];
    }
    GIF_frames = gifFrames;
    
    [self loadImageData];
}

- (void)loadImageData {
    // Add all subframes to the animation
    NSMutableArray *array = [[NSMutableArray alloc] init];
    for (NSUInteger i = 0; i < [GIF_frames count]; i++)
    {
        [array addObject: [self getFrameAsImageAtIndex:i]];
    }
    
    NSMutableArray *overlayArray = [[NSMutableArray alloc] init];
    UIImage *firstImage = [array objectAtIndex:0];
    CGSize size = firstImage.size;
    CGRect rect = CGRectZero;
    rect.size = size;
    
    UIGraphicsBeginImageContext(size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    int i = 0;
    AnimatedGifFrame *lastFrame = nil;
    for (UIImage *image in array)
    {
        // Get Frame
        AnimatedGifFrame *frame = [GIF_frames objectAtIndex:i];
        
        // Initialize Flag
        UIImage *previousCanvas = nil;
        
        // Save Context
        CGContextSaveGState(ctx);
        // Change CTM
        CGContextScaleCTM(ctx, 1.0, -1.0);
        CGContextTranslateCTM(ctx, 0.0, -size.height);
        
        // Check if lastFrame exists
        CGRect clipRect;
        
        // Disposal Method (Operations before draw frame)
        switch (frame.disposalMethod)
        {
            case 1: // Do not dispose (draw over context)
                // Create Rect (y inverted) to clipping
                clipRect = CGRectMake(frame.area.origin.x, size.height - frame.area.size.height - frame.area.origin.y, frame.area.size.width, frame.area.size.height);
                // Clip Context
                CGContextClipToRect(ctx, clipRect);
                break;
            case 2: // Restore to background the rect when the actual frame will go to be drawed
                // Create Rect (y inverted) to clipping
                clipRect = CGRectMake(frame.area.origin.x, size.height - frame.area.size.height - frame.area.origin.y, frame.area.size.width, frame.area.size.height);
                // Clip Context
                CGContextClipToRect(ctx, clipRect);
                break;
            case 3: // Restore to Previous
                // Get Canvas
                previousCanvas = UIGraphicsGetImageFromCurrentImageContext();
                
                // Create Rect (y inverted) to clipping
                clipRect = CGRectMake(frame.area.origin.x, size.height - frame.area.size.height - frame.area.origin.y, frame.area.size.width, frame.area.size.height);
                // Clip Context
                CGContextClipToRect(ctx, clipRect);
                break;
        }
        
        // Draw Actual Frame
        CGContextDrawImage(ctx, rect, image.CGImage);
        // Restore State
        CGContextRestoreGState(ctx);
        
        //delay must larger than 0, the minimum delay in firefox is 10.
        if (frame.delay <= 0) {
            frame.delay = 10;
        }
        [overlayArray addObject:UIGraphicsGetImageFromCurrentImageContext()];
        
        // Set Last Frame
        lastFrame = frame;
        
        // Disposal Method (Operations afte draw frame)
        switch (frame.disposalMethod)
        {
            case 2: // Restore to background color the zone of the actual frame
                // Save Context
                CGContextSaveGState(ctx);
                // Change CTM
                CGContextScaleCTM(ctx, 1.0, -1.0);
                CGContextTranslateCTM(ctx, 0.0, -size.height);
                // Clear Context
                CGContextClearRect(ctx, clipRect);
                // Restore Context
                CGContextRestoreGState(ctx);
                break;
            case 3: // Restore to Previous Canvas
                // Save Context
                CGContextSaveGState(ctx);
                // Change CTM
                CGContextScaleCTM(ctx, 1.0, -1.0);
                CGContextTranslateCTM(ctx, 0.0, -size.height);
                // Clear Context
                CGContextClearRect(ctx, lastFrame.area);
                // Draw previous frame
                CGContextDrawImage(ctx, rect, previousCanvas.CGImage);
                // Restore State
                CGContextRestoreGState(ctx);
                break;
        }
        
        // Increment counter
        i++;
    }
    UIGraphicsEndImageContext();
    
    [self setImage:[overlayArray objectAtIndex:0]];
    [self setAnimationImages:overlayArray];
    
    [overlayArray release];
    [array release];
    
    // Count up the total delay, since Cocoa doesn't do per frame delays.
    double total = 0;
    for (AnimatedGifFrame *frame in GIF_frames) {
        total += frame.delay;
    }
    
    // GIFs store the delays as 1/100th of a second,
    // UIImageViews want it in seconds.
    [self setAnimationDuration:total/100];
    
    // Repeat infinite
    [self setAnimationRepeatCount:0];
    
    [self startAnimating];
}

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

- (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];
    }
    
    [GIF_frames release];
    
    GIF_buffer = [[NSMutableData alloc] init];
    GIF_global = [[NSMutableData alloc] init];
    GIF_screen = [[NSMutableData alloc] init];
    GIF_frames = [[NSMutableArray alloc] init];
    
    // Reset file counters to 0
    dataPointer = 0;
    
    [self GIFSkipBytes: 6]; // GIF89a, throw away
    [self GIFGetBytes: 7]; // Logical Screen Descriptor
    
    // Deep copy
    [GIF_screen setData: GIF_buffer];
    
    // Copy the read bytes into a local buffer on the stack
    // For easy byte access in the following lines.
    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)];
        
        // Deep copy
        [GIF_global setData:GIF_buffer];
    }
    
    unsigned char bBuffer[1];
    while ([self GIFGetBytes:1] == YES)
    {
        [GIF_buffer getBytes:bBuffer length:1];
        
        if (bBuffer[0] == 0x3B)
        { // This is the end
            break;
        }
        
        switch (bBuffer[0])
        {
            case 0x21:
                // Graphic Control Extension (#n of n)
                [self GIFReadExtensions];
                break;
            case 0x2C:
                // Image Descriptor (#n of n)
                [self GIFReadDescriptor];
                break;
        }
    }
    
    // clean up stuff
    [GIF_buffer release];
    GIF_buffer = nil;
    
    [GIF_screen release];
    GIF_screen = nil;
    
    [GIF_global release];
    GIF_global = nil;
}

- (void) GIFReadExtensions {
    // 21! But we still could have an Application Extension,
    // so we want to check for the full signature.
    unsigned char cur[1], prev[1];
    [self GIFGetBytes:1];
    [GIF_buffer getBytes:cur length:1];
    
    while (cur[0] != 0x00)
    {
        
        // TODO: Known bug, the sequence F9 04 could occur in the Application Extension, we
        //       should check whether this combo follows directly after the 21.
        if (cur[0] == 0x04 && prev[0] == 0xF9)
        {
            [self GIFGetBytes:5];
            
            AnimatedGifFrame *frame = [[AnimatedGifFrame alloc] init];
            
            unsigned char buffer[5];
            [GIF_buffer getBytes:buffer length:5];
            frame.disposalMethod = (buffer[0] & 0x1c) >> 2;
            //NSLog(@"flags=%x, dm=%x", (int)(buffer[0]), frame.disposalMethod);
            
            // We save the delays for easy access.
            frame.delay = (buffer[1] | buffer[2] << 8);
            
            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];
            }
            
            frame.header = [NSData dataWithBytes:board length:8];
            
            [GIF_frames addObject:frame];
            [frame release];
            break;
        }
        
        prev[0] = cur[0];
        [self GIFGetBytes:1];
        [GIF_buffer getBytes:cur length:1];
    }
}

- (void) GIFReadDescriptor {
    [self GIFGetBytes:9];
    
    // Deep copy
    NSMutableData *GIF_screenTmp = [NSMutableData dataWithData:GIF_buffer];
    
    unsigned char aBuffer[9];
    [GIF_buffer getBytes:aBuffer length:9];
    
    CGRect rect;
    rect.origin.x = ((int)aBuffer[1] << 8) | aBuffer[0];
    rect.origin.y = ((int)aBuffer[3] << 8) | aBuffer[2];
    rect.size.width = ((int)aBuffer[5] << 8) | aBuffer[4];
    rect.size.height = ((int)aBuffer[7] << 8) | aBuffer[6];
    
    AnimatedGifFrame *frame = [GIF_frames lastObject];
    frame.area = rect;
    
    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];
    }
    
    // Add Graphic Control Extension Frame (for transparancy)
    [GIF_string appendData:frame.header];
    
    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)];
    
    // save the frame into the array of frames
    frame.data = GIF_string;
}

- (bool) GIFGetBytes:(int)length {
    if (GIF_buffer != nil)
    {
        [GIF_buffer release]; // Release old buffer
        GIF_buffer = nil;
    }
    
    if ((NSInteger)[GIF_pointer length] >= dataPointer + length) // Don't read across the edge of the file..
    {
        GIF_buffer = [[GIF_pointer subdataWithRange:NSMakeRange(dataPointer, length)] retain];
        dataPointer += length;
        return YES;
    }
    else
    {
        return NO;
    }
}

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

- (NSData*) getFrameAsDataAtIndex:(int)index {
    if (index < (NSInteger)[GIF_frames count])
    {
        return ((AnimatedGifFrame *)[GIF_frames objectAtIndex:index]).data;
    }
    else
    {
        return nil;
    }
}

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


@end


2、使用webView显示.gif图片


- (void)initGif
{
    DLog(@"gif is:%@",self.gifName);
    DLog(@"png is:%@",self.pngName);
    // 读取gif图片数据
    
    
    // 对data数据进行解密
    NSData *gifData = [SGTools decodeDataWithNameInBundleWithoutPrefix:_gifName];
    
    
    
    
    
    
    // view生成
    UIWebView *webView = _webView;
    webView.userInteractionEnabled = YES;//用户不可交互
    [webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
    
    
    // 缩放手势
    UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchView:)];
    [_webView addGestureRecognizer:pinchGestureRecognizer];
    _webView.layer.anchorPoint = CGPointMake(0.5, 0.15);
    
    
    
    
    // 初次放大
    UIImage *img = [UIImage imageWithData:[SGTools decodeDataWithNameInBundleWithoutPrefix:_gifName]];
    CGFloat scacle = ScreenWidth/img.size.width -1;
    DLog(@"sg____init___%f",scacle);
    _webView.transform = CGAffineTransformScale(_webView.transform, scacle, scacle);
    
}
// 处理缩放手势
// 处理缩放手势
- (void) pinchView:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
    UIView *view = pinchGestureRecognizer.view;
    if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan || pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) {
        
        DLog(@"sg__%d",pinchGestureRecognizer.scale);
        
        view.transform = CGAffineTransformScale(view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);
        
        pinchGestureRecognizer.scale = 1;
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1024app_ios_2.3.4是一款专为iOS设备设计的应用程序,其版本号为2.3.4。该应用程序在功能上提供了丰富的内容和服务,可以满足用户在不同方面的需求。 1024app_ios_2.3.4首先具备了强大的应用市场功能,用户可以通过该应用程序方便地浏览和搜索各种类型的应用,包括游戏、社交媒体、工具类等。用户可以根据自己的兴趣和需求下载和安装这些应用,并在手机上进行使用。 其次,1024app_ios_2.3.4还提供了个性化推荐功能,根据用户的使用习惯和喜好,推荐适合用户的应用程序。这样,用户可以更加高效地发现和使用他们感兴趣的应用,提高了用户体验。 另外,1024app_ios_2.3.4还支持应用的更新和升级。用户可以在应用程序中获得关于已安装应用的最新版本信息,并进行更新。这样,用户可以及时获得应用程序的最新功能和修复bug,提高了应用的稳定性和安全性。 最后,1024app_ios_2.3.4还具备了一些额外的功能,例如用户可以在应用中进行应用评分和评论,与其他用户交流和分享使用心得。此外,用户还可以通过该应用程序获取关于应用的详细信息,如应用的大小、开发者介绍等。 综上所述,1024app_ios_2.3.4是一款功能强大的iOS应用程序,用户可以在其中浏览和下载各种类型的应用,享受个性化推荐、应用更新和升级等服务。同时,用户还可以与其他用户互动交流,获取应用的详细信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值