| | |
| | | return hasAlpha; |
| | | } |
| | | |
| | | + (BOOL)CGImageIsLazy:(CGImageRef)cgImage { |
| | | if (!cgImage) { |
| | | return NO; |
| | | } |
| | | // CoreGraphics use CGImage's C struct filed (offset 0xd8 on iOS 17.0) |
| | | // But since the description of `CGImageRef` always contains the `[DP]` (DataProvider) and `[IP]` (ImageProvider), we can use this as a hint |
| | | NSString *description = (__bridge_transfer NSString *)CFCopyDescription(cgImage); |
| | | if (description) { |
| | | // Solution 1: Parse the description to get provider |
| | | // <CGImage 0x10740ffe0> (IP) -> YES |
| | | // <CGImage 0x10740ffe0> (DP) -> NO |
| | | NSArray<NSString *> *lines = [description componentsSeparatedByString:@"\n"]; |
| | | if (lines.count > 0) { |
| | | NSString *firstLine = lines[0]; |
| | | NSRange startRange = [firstLine rangeOfString:@"("]; |
| | | NSRange endRange = [firstLine rangeOfString:@")"]; |
| | | if (startRange.location != NSNotFound && endRange.location != NSNotFound) { |
| | | NSRange resultRange = NSMakeRange(startRange.location + 1, endRange.location - startRange.location - 1); |
| | | NSString *providerString = [firstLine substringWithRange:resultRange]; |
| | | if ([providerString isEqualToString:@"IP"]) { |
| | | return YES; |
| | | } else if ([providerString isEqualToString:@"DP"]) { |
| | | return NO; |
| | | } else { |
| | | // New cases ? fallback |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // Solution 2: Use UTI metadata |
| | | CFStringRef uttype = CGImageGetUTType(cgImage); |
| | | if (uttype) { |
| | | // Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier` metadata for lazy decoded CGImage |
| | | return YES; |
| | | } else { |
| | | return NO; |
| | | } |
| | | } |
| | | |
| | | + (CGImageRef)CGImageCreateDecoded:(CGImageRef)cgImage { |
| | | return [self CGImageCreateDecoded:cgImage orientation:kCGImagePropertyOrientationUp]; |
| | | } |
| | |
| | | // Check policy (automatic) |
| | | CGImageRef cgImage = image.CGImage; |
| | | if (cgImage) { |
| | | CFStringRef uttype = CGImageGetUTType(cgImage); |
| | | if (uttype) { |
| | | // Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier` |
| | | // Check if it's lazy CGImage wrapper or not |
| | | BOOL isLazy = [SDImageCoderHelper CGImageIsLazy:cgImage]; |
| | | if (isLazy) { |
| | | // Lazy CGImage should trigger force decode before rendering |
| | | return YES; |
| | | } else { |
| | | // Now, let's check if the CGImage is hardware supported (not byte-aligned will cause extra copy) |
| | | // Now, let's check if this non-lazy CGImage is hardware supported (not byte-aligned will cause extra copy) |
| | | BOOL isSupported = [SDImageCoderHelper CGImageIsHardwareSupported:cgImage]; |
| | | return !isSupported; |
| | | } |