• iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片


    图片上传时必要将图片进行压缩,不然会上传失败

    首先是同系统相册选择图片和视频。iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项目要求需要支持多选,只能自己自定义。获取系统图库的框架有两个,一个是ALAssetsLibrary,兼容iOS低版本,但是在iOS9中是不建议使用的;另一个是PHAsset,但最低要求iOS8以上。兼容到iOS7,可以选择了ALAssetsLibrary 现在我们先说选择一张图的情况

     一、单图多图上传

    1.单张图上传

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];    [manager POST:urlString parameters:params constructingBodyWithBlock:^(id_Nonnull formData) {

    //使用日期生成图片名称

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

    NSString *fileName = [NSString stringWithFormat:@"%@.png",[formatter stringFromDate:[NSDate date]]];

    [formData appendPartWithFileData:imageData name:@"uploadFile" fileName:fileName mimeType:@"image/png"];

    } success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {

    //上传图片成功执行回调

    completion(responseObject,nil);

    } failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {

    //上传图片失败执行回调

    completion(nil,error);

    }];

    2.多图上传

    多图上传和单图上传区别在于文件名称

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];    [manager POST:urlString parameters:params constructingBodyWithBlock:^(id_Nonnull formData) {

    NSInteger imgCount = 0;

    for (NSData *imageData in imageDatas) {

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss:SSS";

    NSString *fileName = [NSString stringWithFormat:@"%@%@.png",[formatter stringFromDate:[NSDate date]],@(imgCount)];

    [formData appendPartWithFileData:imageData name:[NSString stringWithFormat:@"uploadFile%@",@(imgCount)] fileName:fileName mimeType:@"image/png"];

    imgCount++;

    }

    } success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {

    completion(responseObject,nil);

    } failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {

    completion(nil,error);

    }];

    二、获取图片,压缩图片

    当从摄像头/相册获取图片 我们需要过UIImagePickerController类来和用户交互  使用UIImagePickerController和用户交互,我们需要实现2个协议<UIImagePickerControllerDelegate,UINavigationControllerDelegate>

    1.获取图片(从相册中或摄像头中)

    1.1 我们首先要实例化UIImagePickerController对象,然后设置imagePicker对象为当前对象,设置imagePicker的图片来源为UIImagePickerControllerSourceTypePhotoLibrary,表明当前图片的来源为相册,除此之外还可以设置用户对图片是否可编辑

    #pragma mark 从用户相册获取活动图片
    - (void)pickImageFromAlbum
    {
        imagePicker = [[UIImagePickerController alloc] init];
        imagePicker.delegate = self;
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        imagePicker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
        imagePicker.allowsEditing = YES;
        
        [self presentModalViewController:imagePicker animated:YES];
    }

    1.2和从相册获取图片只是图片来源的设置不一样,摄像头图片的来源为UIImagePickerControllerSourceTypeCamera

     #pragma mark 从摄像头获取活动图片
    - (void)pickImageFromCamera
    {
        imagePicker = [[UIImagePickerController alloc] init];
        imagePicker.delegate = self;
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
        imagePicker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
        imagePicker.allowsEditing = YES;
        
        [self presentModalViewController:imagePicker animated:YES];
    }

    1.3在和用户交互之后,用户选择好图片后,会回调选择结束的方法

    - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
    {
        UIImage *image= [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) 
        {
    //        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
        }
        theImage = [UtilMethod imageWithImageSimple:image scaledToSize:CGSizeMake(120.0, 120.0)];
        UIImage *midImage = [UtilMethod imageWithImageSimple:image scaledToSize:CGSizeMake(210.0, 210.0)];
        UIImage *bigImage = [UtilMethod imageWithImageSimple:image scaledToSize:CGSizeMake(440.0, 440.0)];
        [self saveImage:theImage WithName:@"salesImageSmall.jpg"];
        [self saveImage:midImage WithName:@"salesImageMid.jpg"];
        [self saveImage:bigImage WithName:@"salesImageBig.jpg"];
        
        [self dismissModalViewControllerAnimated:YES];
        [self refreshData];

    在回调结束的方法中,我们对图片进行了大小的处理,为图片的上传做准备。缩放图片缩放图片比较简单

    //压缩图片(缩放图片)
    + (UIImage*)imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize
    {
        // Create a graphics image context
        UIGraphicsBeginImageContext(newSize);
        
        // Tell the old image to draw in this new context, with the desired
        // new size
        [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
        
        // Get the new image from the context
        UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
        
        // End the context
        UIGraphicsEndImageContext();
        
        // Return the new image.
        return newImage;

    // 存储图像

     pragma mark 保存图片到document
    - (void)saveImage:(UIImage *)tempImage WithName:(NSString *)imageName
    {
        NSData* imageData = UIImagePNGRepresentation(tempImage);
        NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString* documentsDirectory = [paths objectAtIndex:0];
        // Now we get the full path to the file
        NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:imageName];
        // and then we write it out
        [imageData writeToFile:fullPathToFile atomically:NO];
    }

     //从Documents目录下获取图片

     #pragma mark 从文档目录下获取Documents路径
    - (NSString *)documentFolderPath
    {
        return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    }

    然后,我们便可以通过文件名,去访问获取资源了

     补充:iOS 图片压缩处理

    首先,我们必须明确图片的压缩其实是两个概念:

    1. “压” 是指文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降。
    2. “缩” 是指文件的尺寸变小,也就是像素数减少,而长宽尺寸变小,文件体积同样会减小。

    图片“压”处理

    对于“压”的功能,我们可以使用UIImageJPEGRepresentationUIImagePNGRepresentation方法实现,如:

    NSData *imgData = UIImageJPEGRepresentation(image, 0.5);

    第一个参数是图片对象,第二个参数是压的系数,其值范围为0~1。

    UIImageJPEGRepresentation方法的官方注释是:return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)

    关于PNG和JPEG格式压缩

    1. UIImageJPEGRepresentation函数需要两个参数:图片的引用和压缩系数而UIImagePNGRepresentation只需要图片引用作为参数.

    2. UIImagePNGRepresentation(UIImage *image)要比UIImageJPEGRepresentation(UIImage* image, 1.0)返回的图片数据量大很多.

    同样的一张照片, 使用UIImagePNGRepresentation(image)返回的数据量大小为199K,而 UIImageJPEGRepresentation(image, 1.0)返回的数据量大小只为140K,比前者少了59K.

    如果对图片的清晰度要求不是极高,建议使用UIImageJPEGRepresentation,可以大幅度降低图片数据量.比如,刚才拍摄的图片,通过调用UIImageJPEGRepresentation(image, 1.0)读取数据时,返回的数据大小为140K,但更改压缩系数为0.5再读取数据时,返回的数据大小只有11K,大大压缩了图片的数据量,而且清晰度并没有相差多少,图片的质量并没有明显的降低。因此,在读取图片数据内容时,建议优先使用UIImageJPEGRepresentation,并可根据自己的实际使用场景,设置压缩系数,进一步降低图片数据量大小。

    提示:压缩系数不宜太低,通常是0.3~0.7,过小则可能会出现黑边等。

    我们看一下笔者使用UIImageJPEGRepresentation的数据表:


    image

    笔者统计了iphone设备上的全屏图和原始图在压缩前和压缩后的大小,我们需要根据图片压缩后在PC上的清晰度来决定最终选择哪个压缩系数。

    图片“缩”处理


    通过[sourceImage drawInRect:CGRectMake(0, 0, targetWidth, targetHeight)]可以进行图片“缩”的功能。如下是笔者对图片尺寸缩的api

    /*!
     *  @author 黄仪标, 15-12-01 16:12:01
     *
     *  压缩图片至目标尺寸
     *
     *  @param sourceImage 源图片
     *  @param targetWidth 图片最终尺寸的宽
     *
     *  @return 返回按照源图片的宽、高比例压缩至目标宽、高的图片
     */
    - (UIImage *)compressImage:(UIImage *)sourceImage toTargetWidth:(CGFloat)targetWidth {
      CGSize imageSize = sourceImage.size;
    
      CGFloat width = imageSize.width;
      CGFloat height = imageSize.height;
    
      CGFloat targetHeight = (targetWidth / width) * height;
    
      UIGraphicsBeginImageContext(CGSizeMake(targetWidth, targetHeight));
      [sourceImage drawInRect:CGRectMake(0, 0, targetWidth, targetHeight)];
    
      UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
    
      return newImage;
    }

    我们对图片只“压”而不缩,有时候是达不到我们的需求的。因此,适当地对图片“缩”一“缩“尺寸,就可以满足我们的需求。

    提示:我们获取到的全屏图的宽高不是指设备的宽高,通常会比设置的宽要大,高度可能相等。我们可以拍全景图,那么宽就很大了。

  • 相关阅读:
    EasyPR--开发详解(2)车牌定位
    EasyPR--中文开源车牌识别系统 开发详解(1)
    EasyPR--一个开源的中文车牌识别系统
    Ajax异步请求原理的分析
    ajax同步
    ajax解决跨域
    ajax及其工作原理
    python编码设置
    python编译hello
    WinForm通过操作注册表实现限制软件使用次数的方法
  • 原文地址:https://www.cnblogs.com/junhuawang/p/5624266.html
Copyright © 2020-2023  润新知