美文网首页
iOS压缩 gif 图片

iOS压缩 gif 图片

作者: 摘心 | 来源:发表于2018-12-04 14:45 被阅读82次
        最近发现相册可以直接存储、浏览 gif,感觉苹果开始注意 gif,所以总结一下自己的使用方法。一般 gif 在内存比较大,在 cell 上展示会比较卡,所以做下压缩还是很有必要的。查找很多资料也没法下可以直接操作的 api,所有的压缩原理似乎都是对 gif 的每帧图片分别压缩,然后再合成 gif,所以我也是按照这个思路实现了一下。下面直接上代码:
    
    + (NSData *)scallGIFWithData:(NSData *)data scallSize:(CGSize)scallSize {
      if (!data) {
        return nil;
      }
      CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
      size_t count = CGImageSourceGetCount(source);
      
      // 设置 gif 文件属性 (0:无限次循环)
      NSDictionary *fileProperties = [self filePropertiesWithLoopCount:0];
      
      NSString *tempFile = [NSTemporaryDirectory() stringByAppendingString:@"scallTemp.gif"];
      NSFileManager *manager = [NSFileManager defaultManager];
      if ([manager fileExistsAtPath:tempFile]) {
        [manager removeItemAtPath:tempFile error:nil];
      }
      NSURL *fileUrl = [NSURL fileURLWithPath:tempFile];
      CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileUrl, kUTTypeGIF , count, NULL);
      
      NSTimeInterval duration = 0.0f;
      for (size_t i = 0; i < count; i++) {
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
        UIImage *image = [UIImage imageWithCGImage:imageRef];
        UIImage *scallImage = [self scallImageWidthScallSize:scallSize];
        
        NSTimeInterval delayTime = [self frameDurationAtIndex:i source:source];
        duration += delayTime;
        // 设置 gif 每针画面属性
        NSDictionary *frameProperties = [self framePropertiesWithDelayTime:delayTime];
        CGImageDestinationAddImage(destination, scallImage.CGImage, (CFDictionaryRef)frameProperties);
        CGImageRelease(imageRef);
      }
      CGImageDestinationSetProperties(destination, (CFDictionaryRef)fileProperties);
      // Finalize the GIF
      if (!CGImageDestinationFinalize(destination)) {
        NSLog(@"Failed to finalize GIF destination");
        if (destination != nil) {
          CFRelease(destination);
        }
        return nil;
      }
      CFRelease(destination);
      CFRelease(source);
      return [NSData dataWithContentsOfFile:tempFile];
    }
    

    按照 size 压缩每帧图片

    + (UIImage *)scallImageWidthScallSize:(CGSize)scallSize{
      CGFloat width = self.size.width;
      CGFloat height = self.size.height;
      
      CGFloat scaleFactor = 0.0;
      CGFloat scaledWidth = scallSize.width;
      CGFloat scaledHeight = scallSize.height;
      CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
      
      if (!CGSizeEqualToSize(self.size, scallSize))
      {
        CGFloat widthFactor = scaledWidth / width;
        CGFloat heightFactor = scaledHeight / height;
        
        scaleFactor = MAX(widthFactor, heightFactor);
        
        scaledWidth= width * scaleFactor;
        scaledHeight = height * scaleFactor;
        
        // center the image
        if (widthFactor > heightFactor)
        {
          thumbnailPoint.y = (scallSize.height - scaledHeight) * 0.5;
        }
        else if (widthFactor < heightFactor)
        {
          thumbnailPoint.x = (scallSize.width - scaledWidth) * 0.5;
        }
      }
      CGRect rect;
      rect.origin = thumbnailPoint;
      rect.size = CGSizeMake(scaledWidth, scaledHeight);
      UIGraphicsBeginImageContext(rect.size);
      [self drawInRect:rect];
      UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      return  image;
    }
    

    读取帧率

    + (float)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
      float frameDuration = 0.1f;
      CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
      NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
      NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
      
      NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
      if (delayTimeUnclampedProp) {
        frameDuration = [delayTimeUnclampedProp floatValue];
      }
      else {
        
        NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
        if (delayTimeProp) {
          frameDuration = [delayTimeProp floatValue];
        }
      }
    
      if (frameDuration < 0.011f) {
        frameDuration = 0.100f;
      }
      CFRelease(cfFrameProperties);
      frameDuration += 0.1;
      return frameDuration;
    }
    

    合成新的 gif, 设置播放属性

    + (NSDictionary *)filePropertiesWithLoopCount:(int)loopCount {
      return @{(NSString *)kCGImagePropertyGIFDictionary:
                 @{(NSString *)kCGImagePropertyGIFLoopCount: @(loopCount)}
               };
    }
    
    + (NSDictionary *)framePropertiesWithDelayTime:(NSTimeInterval)delayTime {
      
      return @{(NSString *)kCGImagePropertyGIFDictionary:
                 @{(NSString *)kCGImagePropertyGIFDelayTime: @(delayTime)},
               (NSString *)kCGImagePropertyColorModel:(NSString *)kCGImagePropertyColorModelRGB
               };
    }
    
    

    相关文章

      网友评论

          本文标题:iOS压缩 gif 图片

          本文链接:https://www.haomeiwen.com/subject/eebmcqtx.html