原始碼閱讀:SDWebImage(三)——NSData+ImageContentType

堯少羽發表於2018-05-29

該文章閱讀的SDWebImage的版本為4.3.3。

從這個分類的名字我們就能猜到這個類的作用是通過圖片的二進位制資料獲取圖片型別。


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

這個列舉定義了圖片格式。


/**
 通過圖片的二進位制資料判斷圖片的格式
 */
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
複製程式碼
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
    if (!data) {
        // 如果未傳入二級制資料就返回“未定義型別”
        return SDImageFormatUndefined;
    }
    
    // 獲取圖片二級制資料的第一個位元組,也就是八個位元
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        // 根據位元組的不同返回不同的型別
        case 0xFF:
            return SDImageFormatJPEG;
        case 0x89:
            return SDImageFormatPNG;
        case 0x47:
            return SDImageFormatGIF;
        case 0x49:
        case 0x4D:
            return SDImageFormatTIFF;
        case 0x52: {
            // WebP格式的判斷要複雜些:首先圖片二級制的長度要超過12個位元組,並且開頭的12個位元組通過ASCII編碼後的字串要以“RIFF”開頭,並且以“WEBP”結束。
            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: {
            // HEIC格式的圖片判斷也比其他的要複雜些:首先圖片二級制的長度也要超過12個位元組,然後從第四個位元組開始取八個位元組並通過ASCII編碼轉換成字串,如果字串中包含“ftypheic”、“ftypheix”、“ftyphevc”和“ftyphevx”中的任意一個字串就可以
            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;
}
複製程式碼

// 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")
複製程式碼
  • 因為現在蘋果還不支援WebP格式的圖片,所以自定義一個WebP格式的標識。
  • HEIC格式是iOS11以後才出現的,所以為了相容之前的系統,也是自定義一個HEIC格式的標識

/**
 將指定的圖片格式轉換成格式標識
 */
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
複製程式碼
+ (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:
            // 預設的png型別
            UTType = kUTTypePNG;
            break;
    }
    return UTType;
}
複製程式碼

可以發現這個分類內容簡短明瞭,和我們在開頭猜測的一致,這就是個判斷圖片型別的分類。

原始碼閱讀系列:SDWebImage

原始碼閱讀:SDWebImage(一)——從使用入手

原始碼閱讀:SDWebImage(二)——SDWebImageCompat

原始碼閱讀:SDWebImage(三)——NSData+ImageContentType

原始碼閱讀:SDWebImage(四)——SDWebImageCoder

原始碼閱讀:SDWebImage(五)——SDWebImageFrame

原始碼閱讀:SDWebImage(六)——SDWebImageCoderHelper

原始碼閱讀:SDWebImage(七)——SDWebImageImageIOCoder

原始碼閱讀:SDWebImage(八)——SDWebImageGIFCoder

原始碼閱讀:SDWebImage(九)——SDWebImageCodersManager

原始碼閱讀:SDWebImage(十)——SDImageCacheConfig

原始碼閱讀:SDWebImage(十一)——SDImageCache

原始碼閱讀:SDWebImage(十二)——SDWebImageDownloaderOperation

原始碼閱讀:SDWebImage(十三)——SDWebImageDownloader

原始碼閱讀:SDWebImage(十四)——SDWebImageManager

原始碼閱讀:SDWebImage(十五)——SDWebImagePrefetcher

原始碼閱讀:SDWebImage(十六)——SDWebImageTransition

原始碼閱讀:SDWebImage(十七)——UIView+WebCacheOperation

原始碼閱讀:SDWebImage(十八)——UIView+WebCache

原始碼閱讀:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat

原始碼閱讀:SDWebImage(二十)——UIButton+WebCache

原始碼閱讀:SDWebImage(二十一)——UIImageView+WebCache/UIImageView+HighlightedWebCache

相關文章