0%

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

开始

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

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

目标

  用 Core Foundation 实现相同功能

流程

  • 创建 Translate 类的相关文件

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

    • 创建结果相关的 Blok

      1
      typedef void(^complet)(BOOL isSuccess);
    • 创建格式转换相关的枚举

      1
      2
      3
      4
      typedef NS_ENUM(NSUInteger, kUTType) {
      kUTTypeJPEG,
      kUTTypePNG
      };
    • 声明定义压缩转换方法

      1
      extern void TImageRepresentation(NSString *sourceImagePath,NSString *targetImagePatch,double compressionQuality,kUTType type,complet complet);
参数格式定义
sourceImagePathNSString *原图片文件路径
targetImagePatchNSString *输出路径, 必须包含文件名与后缀
compressionQualitydouble图片压缩质量, 范围 0~1, 1为最高质量
typekUTType输出格式, 务必与输出路径的后缀相同
completBlock输出结果的回调
  • Translate.m

    • 引入相关头文件

      1
      2
      #import <ImageIO/ImageIO.h>
      #import <UIKit/UIKit.h>
    • 开始实现压缩转换方法

      1
      2
      3
      4
      5
      6
      7
      void TImageRepresentation(NSString *sourceImagePath,
      NSString *targetImagePatch,
      double compressionQuality,
      kUTType type,
      complet complet) {
      // do something...
      }
    • 开启子线程

      1
      2
      3
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
      // do something...
      }
    • 获取图片源数据

      1
      CGImageRef image = [UIImage imageWithContentsOfFile:sourceImagePath].CGImage;
    • 创建接收最终数据的目标容器

      1
      CFMutableDataRef imageData = CFDataCreateMutable(NULL, 0);
    • 判断转换格式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      CFStringRef typeStr;
      switch (type) {
      case kUTTypeJPEG:
      typeStr = CFSTR("public.jpeg");
      break;

      case kUTTypePNG:
      typeStr = CFSTR("public.png");
      break;

      default:
      break;
      }
    • 创建转换者对象, 进行质量压缩和转换

      1
      CGImageDestinationRef destination = CGImageDestinationCreateWithData(imageData, typeStr, 1, NULL);

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

    • 创建所需参数

      1
      NSDictionary *properties = @{ (__bridge id)kCGImagePropertyMakerNikonQuality : @(compressionQuality) };
    • 向转换者对象添加图片数据和参数数据

      1
      CGImageDestinationAddImage(destination, image, (__bridge CFDictionaryRef)properties);

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

    • 检测转换是否成功, 如失败直接释放数据源与转换者对象, 并结束所有流程

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      if (!CGImageDestinationFinalize(destination)) {
      CFRelease(imageData);
      imageData = NULL;
      if (complet) {
      dispatch_async(dispatch_get_main_queue(), ^{
      complet(NO);
      });
      }
      // 释放转换者对象
      CFRelease(destination);
      return;
      }
    • 成功后释放转换者对象

      1
      CFRelease(destination);
    • 根据输出地址, 创建输出流

      1
      2
      3
      CFAllocatorRef allocator = CFAllocatorGetDefault();
      NSURL *fileUrl = [NSURL fileURLWithPath:targetImagePatch];
      CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(allocator, (__bridge CFURLRef)fileUrl);
    • 开启输出流

      1
      CFWriteStreamOpen(writeStream);
    • 向目标容器写入最终数据

      1
      CFIndex result = CFWriteStreamWrite(writeStream, CFDataGetBytePtr(imageData), CFDataGetLength(imageData));

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

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

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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      if (result != -1) {
      if (complet) {
      dispatch_async(dispatch_get_main_queue(), ^{
      complet(YES);
      });
      }
      } else {
      if (complet) {
      dispatch_async(dispatch_get_main_queue(), ^{
      complet(NO);
      });
      }
      }
    • 关闭输出流

      1
      CFWriteStreamClose(writeStream);
    • 释放目标容器

      1
      CFRelease(imageData);

使用

  简单使用:

1
2
3
4
5
6
7
8
9
10
11
12
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");
}
});

相关