YYImage 源码解析

如何禁止某个类调用某些方法

@interface YYImageEncoder : NSObject
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
@end

// - 实现 不可以直接调用 init 方法 可以调用 initWithType: 并且在initWithType中调用的是 [super init];
- (instancetype)init {
    @throw [NSException exceptionWithName:@"YYImageEncoder init error" reason:@"YYImageEncoder must be initialized with a type. Use 'initWithType:' instead." userInfo:nil];
    return nil;
}
- (instancetype)initWithType:(YYImageType)type {
    self = [super init];
    if (!self) return nil;
    return self;
}

解析 CGBitmapInfo

请先阅读 谈谈 iOS 中图片的解压缩
CGBitmapInfo : alpha 的信息 | 颜色分量是否为浮点数 | 像素格式的字节顺序 (用这三个数据来表示CGBitmapInfo)

  • alpha 的信息 :

    • 是否有 alpha 信息
      CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
      BOOL hasAlpha = NO;
      if (alphaInfo == kCGImageAlphaPremultipliedLast ||
      alphaInfo == kCGImageAlphaPremultipliedFirst ||
      alphaInfo == kCGImageAlphaFirst ||
      alphaInfo == kCGImageAlphaLast) {
      hasAlpha = YES;
      }

    • 如果包含 alpha ,那么 alpha 信息所处的位置,在像素的最低有效位,比如 RGBA ,还是最高有效位,比如 ARGB ;
      如果包含 alpha ,那么每个颜色分量是否已经乘以 alpha 的值,这种做法可以加速图片的渲染时间,因为它避免了渲染时的额外乘法运算。比如,对于 RGB 颜色空间,用已经乘以 alpha 的数据来渲染图片,每个像素都可以避免 3 次乘法运算,红色乘以 alpha ,绿色乘以 alpha 和蓝色乘以 alpha
      CGImageAlphaInfo info = (hasAlpah) ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;

  • 至于颜色分量是否为浮点数,这个就比较简单了,直接逻辑或 kCGBitmapFloatComponents 就可以了; 我们一般用不上这个值

  • 们知道字节顺序的值应该使用的是 32 位的主机字节顺序 kCGBitmapByteOrder32Host ,这样的话不管当前设备采用的是小端模式还是大端模式,字节顺序始终与其保持一致。

[代码]

    CGImageRef imageRef = img.CGImage;
    size_t wid = CGImageGetWidth(imageRef);
    size_t hei = CGImageGetHeight(imageRef);
    
    // - 位图是否包含透明度
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
    BOOL hasAlpha = NO;
    if (alphaInfo == kCGImageAlphaPremultipliedLast ||
        alphaInfo == kCGImageAlphaPremultipliedFirst ||
        alphaInfo == kCGImageAlphaFirst ||
        alphaInfo == kCGImageAlphaLast) {
        hasAlpha = YES;
    }

    // - 位图的字节存出顺序
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;

    // - 位图的透明度的信息的位置
    bitmapInfo |= ((hasAlpha) ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst);
    
    // - 色彩空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    // - 创建图像上下文
    CGContextRef context = CGBitmapContextCreate(NULL, wid, hei, 8, 0, colorSpace, bitmapInfo);
    
    // - 将原始位图, 绘制到图形上下文;
    CGContextDrawImage(context, CGRectMake(0, 0, wid, hei), imageRef);
    
    // - 创建一个新的解压后的位图
    CGImageRef newImage = CGBitmapContextCreateImage(context);

YYImage中timer 和 target 不引起循环引用的方式(使用消息转发)

// - 声明  YYWeakProxy
@interface YYWeakProxy : NSProxy
@property (nullable, nonatomic, weak, readonly) id target;
@end

// - 定义 YYWeakProxy 
@implementation YYWeakProxy
+ (instancetype)proxyWithTarget:(id)target {
    return [[YYWeakProxy alloc] initWithTarget:target];
}
- (id)forwardingTargetForSelector:(SEL)selector {
    return _target;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
    void *null = NULL;
    [invocation setReturnValue:&null];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
    return [_target respondsToSelector:aSelector];
}
- (BOOL)isEqual:(id)object {
    return [_target isEqual:object];
}
- (NSUInteger)hash {
    return [_target hash];
}
- (Class)superclass {
    return [_target superclass];
}
- (Class)class {
    return [_target class];
}
- (BOOL)isKindOfClass:(Class)aClass {
    return [_target isKindOfClass:aClass];
}
- (BOOL)isMemberOfClass:(Class)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值