demoiOS高质量博客Edison

iOS开发--GIF图片的选取,压缩,上传

2017-02-22  本文已影响3285人  半缘魔君

之前写了一篇关于PNG/JPEG图片的选取,压缩,上传(下边统一简称前文): http://www.jianshu.com/p/011b5ef47675, 文本依赖前文的UIImage+ZipSizeAndLength分类进行图片的压缩等.
总结一下: 用原生的 UIImagePickerController 选取图片; 用原生的UIImageJPEGRepresentation()和图形上下文对图片进行压缩; 用AFN进行上传操作.
好了,总结完之后进入今天的主题-----GIF图片的选取,压缩,上传;


目录:
一 前言
二 选取图片(重点)
三 获取GIF图片的原始完整二进制数据(重点)
四 压缩图片(重点)
五 上传图片


一 前言

  有的同学会疑惑,难道gif图片不能用前文说的PNG/JPEG图片的方法进行选取,压缩和上传吗?

我可以肯定的给你回答---不能(自己亲身敲代码做的test,如有疑问,欢迎留言)
原因如下:
1 前文说的选取图片的代码如下:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
}
对于GIF图片只能选取到第一帧,无法取到所有帧.
2 无法取到GIF所有帧,就不能对图片进行压缩
3 无法取到GIF所有帧,也不能将图片转化成二进制数据
4 没有二进制数据就无法进行上传操作
所以需要换另外一个方法,具体如下.


二 选取图片
首先判断是不是GIF图片,如果是才需要走GIF的逻辑,判断方法有如下两种:

第一种(比较取巧):
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *assetString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
if([assetString hasSuffix:@"GIF"]){
//这个图片是GIF图片
} else {
}
}
第二种:利用iOS9.0以后出的 Photos/Photos.h 里边的API进行判断,代码如下:

NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
PHFetchOptions *options = [[PHFetchOptions alloc]init];
PHFetchResult *set = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:options];
 //转化NSData
PHCachingImageManager *imageManager = [[PHCachingImageManager alloc] init];
PHImageRequestOptions *option = [PHImageRequestOptions new];
option.resizeMode = PHImageRequestOptionsResizeModeFast;
option.synchronous = YES;
PHAsset *asset = set.firstObject;//本文只是选取一张
[imageManager requestImageDataForAsset:asset
               options:option
         resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                 if ([dataUTI isEqualToString:(__bridge NSString *)kUTTypeGIF]) {
                      //这个图片是GIF图片
                      }else if([dataUTI isEqualToString:(__bridge NSString *)kUTTypePNG]){
                            NSLog(@"PNG图片");
                      }else if([dataUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]){
                            NSLog(@"JPEG图片");
                      }else if([dataUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG2000]){
                            NSLog(@"JPEG2000图片");
                      }else {
                      }
}];

本文用的是第一种(比较简单,效率高)


三 获取GIF图片的原始完整二进制数据(所有帧)
代码如下:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{      
   NSString *assetString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
   if([assetString hasSuffix:@"GIF"]){
       //这个图片是GIF图片
       ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc]init];
       [assetLibrary assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) {
        ALAssetRepresentation *re = [asset representationForUTI:(__bridge NSString *)kUTTypeGIF];;
        NSUInteger size = (NSUInteger)re.size;
        uint8_t *buffer = malloc(size);
        NSError *error;
        NSUInteger bytes = [re getBytes:buffer fromOffset:0 length:size error:&error];
        NSData *data = [NSData dataWithBytes:buffer length:bytes];//这个就是选取的GIF图片的原二进制数据
        free(buffer);
        } failureBlock:^(NSError *error) {
        
    }];
    } else {
   }
}

四 压缩图片

利用CoreGraphics/CoreGraphics.h API转换GIF图片并再次转成符合要求的图片的二进制文件:
封装方法如下:
+ (NSData *)zipGIFWithData:(NSData *)data {
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
UIImage *animatedImage = nil;
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval duration = 0.0f;
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
duration += [self frameDurationAtIndex:i source:source];
UIImage *ima = [UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
ima = [ima zip];
[images addObject:ima];
CGImageRelease(image);
if (!duration) {
duration = (1.0f / 10.0f) * count;
}
animatedImage = [UIImage animatedImageWithImages:images duration:duration];
}
CFRelease(source);
return UIImagePNGRepresentation(animatedImage);
}
将三种得到的gif图片的二进制数据精心压缩:
代码如下:

 ....
NSData *data = [NSData dataWithBytes:buffer length:bytes];//这个就是选取的GIF图片的原二进制数据
data = [self zipGIFWithData:data];
//上传二进制数据

五 上传图片,与前文上传图片一样

上一篇 下一篇

猜你喜欢

热点阅读