参考YYImage,让页面自动支持gif、webp等格式图片

参考:


----软件---

brew install webp

将png一件全部转换成同名webp

find ./ -type f -name '*.png' | xargs -P 8 -I {} sh -c 'cwebp -q 80 $1 -o "${1%.png}.webp"' _ {} \;

删除找到的webp图片

find ./ -type f -name '*.webp' | xargs -P 8 -I {} sh -c 'rm $1' _ {} \;

删除找到的png图片

find ./ -type f -name '*.png' | xargs -P 8 -I {} sh -c 'rm $1' _ {} \;

在项目中实际转换后,发现部分图片,尤其是鲜艳高亮的蓝色会存在肉眼可见的色差,变得明细较灰暗,这种图片尽量用tinypng进行转换,效果明显,色差不大
https://tinypng.com/

jpg、png格式的图片转换成webp后颜色失真的问题


让项目中通过[UIImage imageNamed:xx]的图片支持大部分格式,png, jpeg, jpg, gif,webp, apng,heic
原理:将UIImage的方法hook,返回YYImage初始化好的对象

#import "UIImage+YYAllType.h"
#import <objc/runtime.h>
#import "YYImage.h"

static NSArray *YY_All_NSBundlePreferredScales() {
   static NSArray *scales;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       CGFloat screenScale = [UIScreen mainScreen].scale;
       if (screenScale <= 1) {
           scales = @[@1,@2,@3];
       } else if (screenScale <= 2) {
           scales = @[@2,@3,@1];
       } else {
           scales = @[@3,@2,@1];
       }
   });
   return scales;
}
static NSString *YY_All_NSStringByAppendingNameScale(NSString *string, CGFloat scale) {
   if (!string) return nil;
   if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@"/"]) return string.copy;
   return [string stringByAppendingFormat:@"@%@x", @(scale)];
}
@implementation UIImage (YYAllType)
+ (BOOL)swizzleMethod:(Class)class orgSel:(SEL)origSel swizzSel:(SEL)altSel {
   Method origMethod = class_getInstanceMethod(class, origSel);
   Method altMethod = class_getInstanceMethod(class, altSel);
   if (!origMethod || !altMethod) {
       return NO;
   }
   BOOL didAddMethod = class_addMethod(class,origSel,
                                       method_getImplementation(altMethod),
                                       method_getTypeEncoding(altMethod));
   
   if (didAddMethod) {
       class_replaceMethod(class,altSel,
                           method_getImplementation(origMethod),
                           method_getTypeEncoding(origMethod));
   } else {
       method_exchangeImplementations(origMethod, altMethod);
   }
   
   return YES;
}
+(void)load {
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       // 交换对象方法
       // 交换类方法
       [self swizzleMethod:object_getClass((id)self) orgSel:@selector(imageNamed:) swizzSel:@selector(yy_all_imageNamed:)];
       [self swizzleMethod:object_getClass((id)self) orgSel:@selector(imageNamed:inBundle:compatibleWithTraitCollection:) swizzSel:@selector(yy_all_imageNamed:inBundle:compatibleWithTraitCollection:)];
       
       
   });
}

+ (UIImage *)yy_all_imageNamed:(NSString *)name {
   
   return [UIImage imageNamed:name inBundle:NSBundle.mainBundle compatibleWithTraitCollection:nil];
}
+ (UIImage *)yy_all_imageNamed:(NSString *)name inBundle:(NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection {
   if (name.length == 0) return nil;
   if ([name hasSuffix:@"/"]) return nil;
   
   NSString *res = name.stringByDeletingPathExtension;
   NSString *ext = name.pathExtension;
   NSString *path = nil;
   CGFloat scale = 1;
   
   // If no extension, guess by system supported (same as UIImage).
   NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng",@"heic"];
   NSArray *scales = YY_All__NSBundlePreferredScales();
   for (int s = 0; s < scales.count; s++) {
       scale = ((NSNumber *)scales[s]).floatValue;
       NSString *scaledName = YY_All__NSStringByAppendingNameScale(res, scale);
       for (NSString *e in exts) {
           path = [bundle pathForResource:scaledName ofType:e];
           if (path) break;
       }
       if (path) break;
   }
   if (path.length == 0) return nil;
   
   NSData *data = [NSData dataWithContentsOfFile:path];
   if (data.length == 0) return nil;
   
   return [YYImage imageWithData:data scale:scale];
}
@end