之前寫(xiě)了一篇關(guān)于PNG/JPEG圖片的選取,壓縮,上傳(下邊統(tǒng)一簡(jiǎn)稱前文): http://www.reibang.com/p/011b5ef47675, 文本依賴前文的UIImage+ZipSizeAndLength分類進(jìn)行圖片的壓縮等.
總結(jié)一下: 用原生的 UIImagePickerController 選取圖片; 用原生的UIImageJPEGRepresentation()和圖形上下文對(duì)圖片進(jìn)行壓縮; 用AFN進(jìn)行上傳操作.
好了,總結(jié)完之后進(jìn)入今天的主題-----GIF圖片的選取,壓縮,上傳;
目錄:
一 前言
二 選取圖片(重點(diǎn))
三 獲取GIF圖片的原始完整二進(jìn)制數(shù)據(jù)(重點(diǎn))
四 壓縮圖片(重點(diǎn))
五 上傳圖片
一 前言
有的同學(xué)會(huì)疑惑,難道gif圖片不能用前文說(shuō)的PNG/JPEG圖片的方法進(jìn)行選取,壓縮和上傳嗎?
我可以肯定的給你回答---不能(自己親身敲代碼做的test,如有疑問(wèn),歡迎留言)
原因如下:
1 前文說(shuō)的選取圖片的代碼如下:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
}
對(duì)于GIF圖片只能選取到第一幀,無(wú)法取到所有幀.
2 無(wú)法取到GIF所有幀,就不能對(duì)圖片進(jìn)行壓縮
3 無(wú)法取到GIF所有幀,也不能將圖片轉(zhuǎn)化成二進(jìn)制數(shù)據(jù)
4 沒(méi)有二進(jìn)制數(shù)據(jù)就無(wú)法進(jìn)行上傳操作
所以需要換另外一個(gè)方法,具體如下.
二 選取圖片
首先判斷是不是GIF圖片,如果是才需要走GIF的邏輯,判斷方法有如下兩種:
第一種(比較取巧):
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *assetString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
if([assetString hasSuffix:@"GIF"]){
//這個(gè)圖片是GIF圖片
} else {
}
}
第二種:利用iOS9.0以后出的 Photos/Photos.h 里邊的API進(jìn)行判斷,代碼如下:
NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
PHFetchOptions *options = [[PHFetchOptions alloc]init];
PHFetchResult *set = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:options];
//轉(zhuǎn)化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]) {
//這個(gè)圖片是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 {
}
}];
本文用的是第一種(比較簡(jiǎn)單,效率高)
三 獲取GIF圖片的原始完整二進(jìn)制數(shù)據(jù)(所有幀)
代碼如下:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *assetString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
if([assetString hasSuffix:@"GIF"]){
//這個(gè)圖片是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];//這個(gè)就是選取的GIF圖片的原二進(jìn)制數(shù)據(jù)
free(buffer);
} failureBlock:^(NSError *error) {
}];
} else {
}
}
四 壓縮圖片
利用CoreGraphics/CoreGraphics.h API轉(zhuǎn)換GIF圖片并再次轉(zhuǎn)成符合要求的圖片的二進(jìn)制文件:
封裝方法如下:
+ (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圖片的二進(jìn)制數(shù)據(jù)精心壓縮:
代碼如下:
....
NSData *data = [NSData dataWithBytes:buffer length:bytes];//這個(gè)就是選取的GIF圖片的原二進(jìn)制數(shù)據(jù)
data = [self zipGIFWithData:data];
//上傳二進(jìn)制數(shù)據(jù)
五 上傳圖片,與前文上傳圖片一樣