美文网首页
二、SDWebImage源码解析NSData + ImageCo

二、SDWebImage源码解析NSData + ImageCo

作者: 小强简书 | 来源:发表于2018-01-24 16:08 被阅读174次

    ● 我们先来看.h文件

    typedef NS_ENUM(NSInteger, SDImageFormat) {
        SDImageFormatUndefined = -1,
        SDImageFormatJPEG = 0,
        SDImageFormatPNG,
        SDImageFormatGIF,
        SDImageFormatTIFF,
        SDImageFormatWebP,
        SDImageFormatHEIC
    };
    

    一个枚举,列举出图片的类型

    /**
     *  Return image format  返回图片类型
     *
     *  @param data the input image data 
     *
     *  @return the image format as `SDImageFormat` (enum)
     */
    + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
    
    
    /**
     Convert SDImageFormat to UTType 转成系统type
    
     @param format Format as SDImageFormat
     @return The UTType as CFStringRef
     */
    + (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
    
    

    在看.m文件之前,我们先说一些知识
    ● SDWebImage通过文件头来获取图片的类型,已png为例,png的前8个字节依次为:0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A,再比如jpg图片,jpg文件比较复杂,JPG文件数据,分很多很多的数据段, 并且每个数据段都会以 0xFF开头 ,所以我们就能明白以下代码的含义,

    + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
        if (!data) {
            return SDImageFormatUndefined;
        }
        
        // File signatures table: http://www.garykessler.net/library/file_sigs.html
        uint8_t c;
        [data getBytes:&c length:1];
        switch (c) {
            case 0xFF:
                return SDImageFormatJPEG; //jpeg是 FF开头
            case 0x89:
                return SDImageFormatPNG; //png 是 89开头
            case 0x47:
                return SDImageFormatGIF; // gif 是 47开头
            case 0x49:
            case 0x4D:
                return SDImageFormatTIFF; // tiff 是 49 或者 4D开头
            case 0x52: {
                if (data.length >= 12) {
                    //RIFF....WEBP
                    NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
                    if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                        return SDImageFormatWebP;
                    }
                }
                break;
            }
            case 0x00: {
                if (data.length >= 12) {
                    //....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
                    NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
                    if ([testString isEqualToString:@"ftypheic"]
                        || [testString isEqualToString:@"ftypheix"]
                        || [testString isEqualToString:@"ftyphevc"]
                        || [testString isEqualToString:@"ftyphevx"]) {
                        return SDImageFormatHEIC;
                    }
                }
                break;
            }
        }
        return SDImageFormatUndefined;
    }
    
    

    ● 比较麻烦的是webp格式,webp是以524946462A73010057454250开头的,占用12个字节,当第一个字节为52时,如果长度<12 我们就认定为不是图片。因此返回nil。我们通过数据截取后获得testString,如果testString头部包含RIFF且尾部也包含WEBP,那么就认定该图片格式为webp。

    ● 关于.heic格式的图片
    1.什么是.heic格式图片?
    之前叫“live”图片,打开下图红框中的按钮即可打开该模式,拍照后会截取拍照前后大概两秒的一个片段,与“Gif”图不同的是,该格式还包含了声音(目前只有),只有在 iOS11系统下且CPU为A10及其以上(最低也得是iPhone 7),其他情况下拍出来的都是普通“live”图,即在需要转换格式的时候会自动转换为“.jpg/.jpeg”格式
    2.如何判断.heic格式图片?
    第四到第八个字节,分别等于:ftypheic,ftypheix,ftyphevc,ftyphevx,就可以认定他是.heic格式的图片

    ● 关于kSDUTTypeWebP和kSDUTTypeHEIC

    // Currently Image/IO does not support WebP
    #define kSDUTTypeWebP ((__bridge CFStringRef)@"public.webp")
    // AVFileTypeHEIC is defined in AVFoundation via iOS 11, we use this without import AVFoundation
    #define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
    

    因为webpiOS系统没有对应的type,所以手动创建了一个,heic格式只在iOS11以后才支持,所以也手动创建。

    + (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format {
        CFStringRef UTType;
        switch (format) {
            case SDImageFormatJPEG:
                UTType = kUTTypeJPEG;
                break;
            case SDImageFormatPNG:
                UTType = kUTTypePNG;
                break;
            case SDImageFormatGIF:
                UTType = kUTTypeGIF;
                break;
            case SDImageFormatTIFF:
                UTType = kUTTypeTIFF;
                break;
            case SDImageFormatWebP:
                UTType = kSDUTTypeWebP;
                break;
            case SDImageFormatHEIC:
                UTType = kSDUTTypeHEIC;
                break;
            default:
                // default is kUTTypePNG
                UTType = kUTTypePNG;
                break;
        }
        return UTType;
    }
    

    这个方法没什么可说的,就是讲枚举转化成系统type

    相关文章

      网友评论

          本文标题:二、SDWebImage源码解析NSData + ImageCo

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