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) {
//失敗回調
}];
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容