iOS开发--PNG/JPEG图片的选取,压缩,上传

前段时间项目中有一个上传头像的需求,对图片有一些要求: 图片不能超过2M,宽高最大为200 并且相等,支持JPG/GIF/PNG格式图片,本文先写JPG/PNG,后续会再发GIF图片的选取,压缩,上传.

思考的步骤:

  • 1 从相册选取图片
  • 2 把图片的二进制数据准备好
  • 3 封装上传图片的方法
  • 4 上传图片

下面详细讲解如何实现每一步:
1 从相册选取图片,我这里是用的原生API,上代码:

//这部分代码是用来打开相册的
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;//是否允许编辑
picker.sourceType = sourceType;
[self presentViewController:picker animated:YES completion:nil];

下面是选取图片后代理方法内的代码:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
 {
  __block UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
  [self dismissViewControllerAnimated:YES completion:nil];
  NSString *assetString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
  __block NSData *data = [NSData data];
  if([assetString hasSuffix:@"GIF"]){
  //这个图片是GIF图,这一部分后续文章会出怎么处理
  } else {
    //准备图片的二进制数据
    //上传图片
  }
}

2 准备图片的二进制数据:
根据要求对图片的处理分为两步,第一步压缩体积,减小尺寸,第二步转化成二进制数据
2.1 对PNG和JPEG格式图片的处理
2.1.1 对图片进行压缩
我的做法是利用�图形上下文减小尺寸,利用UIImageJPEGRepresentation()压缩体积,上代码(我做了一个分类,方便调用):

UIImage+ZipSizeAndLength.h

#import <UIKit/UIKit.h>
@interface UIImage (ZipSizeAndLength)
- (UIImage *)compressToByte:(NSUInteger)maxLength;
//直接调用这个方法进行压缩体积,减小大小
- (UIImage *)zip;
@end

UIImage+ZipSizeAndLength.m

@implementation UIImage (ZipSizeAndLength)
- (UIImage *)compressToByte:(NSUInteger)maxLength {
// Compress by quality
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(self, compression);
if (data.length < maxLength) return self;

CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
    compression = (max + min) / 2;
    data = UIImageJPEGRepresentation(self, compression);
    if (data.length < maxLength * 0.9) {
        min = compression;
    } else if (data.length > maxLength) {
        max = compression;
    } else {
        break;
    }
}
UIImage *resultImage = [UIImage imageWithData:data];
if (data.length < maxLength) return resultImage;

// Compress by size
NSUInteger lastDataLength = 0;
while (data.length > maxLength && data.length != lastDataLength) {
    lastDataLength = data.length;

    CGSize size = CGSizeMake(200, 200);
    UIGraphicsBeginImageContext(size);
    [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
    resultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    data = UIImageJPEGRepresentation(resultImage, compression);
}
resultImage = [UIImage imageWithData:data];
return resultImage;
}
- (UIImage *)zipSize{
if (self.size.width < 200) {
    return self;
}
CGSize size = CGSizeMake(200, 200);
UIGraphicsBeginImageContext(size);
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return  image;
}

- (UIImage *)zip{
UIImage *image = [self compressToByte:2*1024*1024];
return  [image zipSize];
}

2.1.2 图片压缩完成之后,需要转成二进制数据,对于PNG和JPEG格式的图片转二进制数据很简单,苹果提供了非常简单实用的API:

// return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format
UIKIT_EXTERN  NSData * __nullable UIImagePNGRepresentation(UIImage * __nonnull image);    
// return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)                           
UIKIT_EXTERN  NSData * __nullable UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality);  

所以,上文中的准备图片的二进制数据,代码为:

    //准备图片的二进制数据
    image = [image zip];
    data = UIImagePNGRepresentation(image);
    //上传图片

3 上传文件的方法:
我用AFN做的上传,代码如下:

+(void)requestUrl:(NSString*)urlString paras:(id)paras datas:(NSArray *)datas 
success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
   NSURLSessionDataTask *datatask = [sessionManager POST:urlString 
                                              parameters:paras 
                               constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            for (int i = 0 ; i < datas.count ; i++){
                NSData *data = datas[i];
                [formData appendPartWithFileData:data name:@"facefile" fileName:@"facefile" mimeType:@"image/gif"];
            }
            
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            NSLog(@"-----%@",uploadProgress);
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"上传成功--%@",responseObject);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"上传失败%@",error);
     }];
 }

这里需要注意的一点是: 数据流的name和faileName mimeType 不能为空; 并且name是跟后台约定好的.
所以上文中的上传图片部分的代码为:

//上传图片
[self uploadImageWithData:data];

uploadImageWithData方法实现为:
- (void)uploadImageWithData:(NSData *)data{
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setValue:@"xx" forKey:@"xxx"];
[dic setValue:@"xx" forKey:@"yyy"];
[dic setValue:@"xx" forKey:@"zzz"];
NSString str = @"http://xx.xx.com";
requestUrl:(NSString
)urlString paras:(id)paras datas:(NSArray *)datas
[Request requestUrl:str paras:dic datas:@[data] success:^(id responds) {
//成功回调
} failure:^(NSError *error) {
//失败回调
}];
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容