美文网首页iOS小功能点iOS Developer
Core Foundation 学习 -- 图片质量的压缩与转换

Core Foundation 学习 -- 图片质量的压缩与转换

作者: Norld | 来源:发表于2017-03-22 14:06 被阅读208次

    原地址: Norld's Blog -- Core Foundation 学习 -- 图片质量的压缩与转换

    开始

      在 UIKit 中有两种图片质量压缩与转换的写法:

    UIImageJPEGRepresentation(image, 0.75);
    UIImagePNGRepresentation(image);
    

    目标

      用 Core Foundation 实现相同功能

    流程

    • 创建 Translate 类的相关文件

      • 包含 Translate.hTranslate.m 文件
      • 删除所有 @interface@implementation 相关的内容
        • 这一步可不做, 之后的内容并没有操作 Translate 的类或实例对象
    • Translate.h

      • 创建结果相关的 Blok
      typedef void(^complet)(BOOL isSuccess);
      
      • 创建格式转换相关的枚举
      typedef NS_ENUM(NSUInteger, kUTType) {
          kUTTypeJPEG,
          kUTTypePNG
      };
      
      • 声明定义压缩转换方法
      extern void TImageRepresentation(NSString *sourceImagePath,NSString *targetImagePatch,double compressionQuality,kUTType type,complet complet);
      
    参数 格式 定义
    sourceImagePath NSString * 原图片文件路径
    targetImagePatch NSString * 输出路径, 必须包含文件名与后缀
    compressionQuality double 图片压缩质量, 范围 0~1, 1为最高质量
    type kUTType 输出格式, 务必与输出路径的后缀相同
    complet Block 输出结果的回调
    • Translate.m

      • 引入相关头文件
      #import <ImageIO/ImageIO.h>
      #import <UIKit/UIKit.h>
      
      • 开始实现压缩转换方法
      void TImageRepresentation(NSString *sourceImagePath,
                                  NSString *targetImagePatch,
                                  double compressionQuality,
                                  kUTType type,
                                  complet complet) {
          // do something...
      }
      
      • 开启子线程
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          // do something...
      }
      
      • 获取图片源数据
      CGImageRef image = [UIImage imageWithContentsOfFile:sourceImagePath].CGImage;
      
      • 创建接收最终数据的目标容器
      CFMutableDataRef imageData = CFDataCreateMutable(NULL, 0);
      
      • 判断转换格式
      CFStringRef typeStr;
      switch (type) {
          case kUTTypeJPEG:
              typeStr = CFSTR("public.jpeg");
              break;
                  
          case kUTTypePNG:
              typeStr = CFSTR("public.png");
              break;
                  
          default:
              break;
      }
      
      • 创建转换者对象, 进行质量压缩和转换
      CGImageDestinationRef destination = CGImageDestinationCreateWithData(imageData, typeStr, 1, NULL);
      

      CGImageDestinationCreateWithData(_,_,_,_) 函数的相关详情

      • 创建所需参数
      NSDictionary *properties = @{ (__bridge id)kCGImageDestinationLossyCompressionQuality : @(compressionQuality) };
      
      • 向转换者对象添加图片数据和参数数据
      CGImageDestinationAddImage(destination, image, (__bridge CFDictionaryRef)properties);
      

      CGImageDestinationAddImage(_,_,_) 函数的相关详情

      • 检测转换是否成功, 如失败直接释放数据源与转换者对象, 并结束所有流程
      if (!CGImageDestinationFinalize(destination)) {
          CFRelease(imageData);
          imageData = NULL;
          if (complet) {
              dispatch_async(dispatch_get_main_queue(), ^{
                  complet(NO);
              });
          }
          // 释放转换者对象
          CFRelease(destination);
          return;
      }
      
      • 成功后释放转换者对象
      CFRelease(destination);
      
      • 根据输出地址, 创建输出流
      CFAllocatorRef allocator = CFAllocatorGetDefault();
      NSURL *fileUrl = [NSURL fileURLWithPath:targetImagePatch];
      CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(allocator, (__bridge CFURLRef)fileUrl);
      
      • 开启输出流
      CFWriteStreamOpen(writeStream);
      
      • 向目标容器写入最终数据
      CFIndex result = CFWriteStreamWrite(writeStream, CFDataGetBytePtr(imageData), CFDataGetLength(imageData));
      

      CFWriteStreamWrite(_,_,_) 函数的相关详情

      • 判断最终数据写入是否成功

        不成功的返回值为 -1, 成功则为输出的字节流长度

      if (result != -1) {
          if (complet) {
              dispatch_async(dispatch_get_main_queue(), ^{
                  complet(YES);
              });
          }
      } else {
          if (complet) {
              dispatch_async(dispatch_get_main_queue(), ^{
                  complet(NO);
              });
          }
      }
      
      • 关闭输出流
      CFWriteStreamClose(writeStream);
      
      • 释放目标容器
      CFRelease(imageData);
      

    使用

      简单使用:

    NSString *sourceImagePath = @"要进行处理的图片的路径";
    NSString *targetImagePath = @"处理完成的输出路径";
    double compressionQuality = 0.75f;
    kUTType targetImageType = kUTTypeJPEG;
        
    TImageRepresentation(sourceImagePath, targetImagePath, compressionQuality, targetImageType, ^(BOOL isSuccess) {
        if (isSuccess) {
            NSLog(@"Winer");
        } else {
            NSLog(@"Loser");
        }
    });
    

    相关

    相关文章

      网友评论

      • 0e69335b0e64:压缩的属性写错了,不是kCGImagePropertyMakerNikonQuality,应该是kCGImageDestinationLossyCompressionQuality
        Norld:感谢指出文中的错误:+1:
        文章已修改
      • small路飞:谢谢楼主分享
        Vincent20481:@small路飞 路飞是你吗?

      本文标题:Core Foundation 学习 -- 图片质量的压缩与转换

      本文链接:https://www.haomeiwen.com/subject/fwjonttx.html