YYImage 图片格式代码节选

2022-06-14  本文已影响0人  路在脚下了
/// Detect a data's image type by reading the data's header 16 bytes (very fast).
CG_EXTERN YYImageType YYImageDetectType(CFDataRef data);

/// Convert YYImageType to UTI (such as kUTTypeJPEG).
CG_EXTERN CFStringRef _Nullable YYImageTypeToUTType(YYImageType type);

/// Convert UTI (such as kUTTypeJPEG) to YYImageType.
CG_EXTERN YYImageType YYImageTypeFromUTType(CFStringRef uti);

/// Get image type's file extension (such as @"jpg").
CG_EXTERN NSString *_Nullable YYImageTypeGetExtension(YYImageType type);


YYImageType YYImageDetectType(CFDataRef data) {
    if (!data) return YYImageTypeUnknown;
    uint64_t length = CFDataGetLength(data);
    if (length < 16) return YYImageTypeUnknown;
    
    const char *bytes = (char *)CFDataGetBytePtr(data);
    
    uint32_t magic4 = *((uint32_t *)bytes);
    switch (magic4) {
        case YY_FOUR_CC(0x4D, 0x4D, 0x00, 0x2A): { // big endian TIFF
            return YYImageTypeTIFF;
        } break;
            
        case YY_FOUR_CC(0x49, 0x49, 0x2A, 0x00): { // little endian TIFF
            return YYImageTypeTIFF;
        } break;
            
        case YY_FOUR_CC(0x00, 0x00, 0x01, 0x00): { // ICO
            return YYImageTypeICO;
        } break;
            
        case YY_FOUR_CC(0x00, 0x00, 0x02, 0x00): { // CUR
            return YYImageTypeICO;
        } break;
            
        case YY_FOUR_CC('i', 'c', 'n', 's'): { // ICNS
            return YYImageTypeICNS;
        } break;
            
        case YY_FOUR_CC('G', 'I', 'F', '8'): { // GIF
            return YYImageTypeGIF;
        } break;
            
        case YY_FOUR_CC(0x89, 'P', 'N', 'G'): {  // PNG
            uint32_t tmp = *((uint32_t *)(bytes + 4));
            if (tmp == YY_FOUR_CC('\r', '\n', 0x1A, '\n')) {
                return YYImageTypePNG;
            }
        } break;
            
        case YY_FOUR_CC('R', 'I', 'F', 'F'): { // WebP
            uint32_t tmp = *((uint32_t *)(bytes + 8));
            if (tmp == YY_FOUR_CC('W', 'E', 'B', 'P')) {
                return YYImageTypeWebP;
            }
        } break;
        /*
        case YY_FOUR_CC('B', 'P', 'G', 0xFB): { // BPG
            return YYImageTypeBPG;
        } break;
        */
    }
    
    uint16_t magic2 = *((uint16_t *)bytes);
    switch (magic2) {
        case YY_TWO_CC('B', 'A'):
        case YY_TWO_CC('B', 'M'):
        case YY_TWO_CC('I', 'C'):
        case YY_TWO_CC('P', 'I'):
        case YY_TWO_CC('C', 'I'):
        case YY_TWO_CC('C', 'P'): { // BMP
            return YYImageTypeBMP;
        }
        case YY_TWO_CC(0xFF, 0x4F): { // JPEG2000
            return YYImageTypeJPEG2000;
        }
    }
    
    // JPG             FF D8 FF
    if (memcmp(bytes,"\377\330\377",3) == 0) return YYImageTypeJPEG;
    
    // JP2
    if (memcmp(bytes + 4, "\152\120\040\040\015", 5) == 0) return YYImageTypeJPEG2000;
    
    return YYImageTypeUnknown;
}

CFStringRef YYImageTypeToUTType(YYImageType type) {
    switch (type) {
        case YYImageTypeJPEG: return kUTTypeJPEG;
        case YYImageTypeJPEG2000: return kUTTypeJPEG2000;
        case YYImageTypeTIFF: return kUTTypeTIFF;
        case YYImageTypeBMP: return kUTTypeBMP;
        case YYImageTypeICO: return kUTTypeICO;
        case YYImageTypeICNS: return kUTTypeAppleICNS;
        case YYImageTypeGIF: return kUTTypeGIF;
        case YYImageTypePNG: return kUTTypePNG;
        default: return NULL;
    }
}

YYImageType YYImageTypeFromUTType(CFStringRef uti) {
    static NSDictionary *dic;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dic = @{(id)kUTTypeJPEG : @(YYImageTypeJPEG),
                (id)kUTTypeJPEG2000 : @(YYImageTypeJPEG2000),
                (id)kUTTypeTIFF : @(YYImageTypeTIFF),
                (id)kUTTypeBMP : @(YYImageTypeBMP),
                (id)kUTTypeICO : @(YYImageTypeICO),
                (id)kUTTypeAppleICNS : @(YYImageTypeICNS),
                (id)kUTTypeGIF : @(YYImageTypeGIF),
                (id)kUTTypePNG : @(YYImageTypePNG)};
    });
    if (!uti) return YYImageTypeUnknown;
    NSNumber *num = dic[(__bridge __strong id)(uti)];
    return num.unsignedIntegerValue;
}

NSString *YYImageTypeGetExtension(YYImageType type) {
    switch (type) {
        case YYImageTypeJPEG: return @"jpg";
        case YYImageTypeJPEG2000: return @"jp2";
        case YYImageTypeTIFF: return @"tiff";
        case YYImageTypeBMP: return @"bmp";
        case YYImageTypeICO: return @"ico";
        case YYImageTypeICNS: return @"icns";
        case YYImageTypeGIF: return @"gif";
        case YYImageTypePNG: return @"png";
        case YYImageTypeWebP: return @"webp";
        default: return nil;
    }
}
上一篇下一篇

猜你喜欢

热点阅读