From 95401e3cca3a421ae8e9b58e4dc783a95c11c4bf Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Wed, 21 Aug 2024 16:58:36 +0800 Subject: [PATCH] Use the new way to detect JFIF, and do not apply EXIF orientation to workaround Apple's bug --- SDWebImage/Core/SDImageIOAnimatedCoder.m | 11 +++++------ Tests/Tests/SDImageCoderTests.m | 14 +++++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/SDWebImage/Core/SDImageIOAnimatedCoder.m b/SDWebImage/Core/SDImageIOAnimatedCoder.m index 27665b46..237d4ccb 100644 --- a/SDWebImage/Core/SDImageIOAnimatedCoder.m +++ b/SDWebImage/Core/SDImageIOAnimatedCoder.m @@ -27,8 +27,6 @@ static CGImageSourceRef (*SDCGImageGetImageSource)(CGImageRef); // Specify File Size for lossy format encoding, like JPEG static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestinationRequestedFileSize"; -// Avoid ImageIO translate JFIF orientation to EXIF orientation which cause bug because returned CGImage already apply the orientation transform -static NSString * kSDCGImageSourceSkipMetadata = @"kCGImageSourceSkipMetadata"; // This strip the un-wanted CGImageProperty, like the internal CGImageSourceRef in iOS 15+ // However, CGImageCreateCopy still keep those CGImageProperty, not suit for our use case @@ -440,12 +438,13 @@ static BOOL SDImageIOPNGPluginBuggyNeedWorkaround(void) { } } // Parse the image properties - NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, (__bridge CFDictionaryRef)@{kSDCGImageSourceSkipMetadata : @(YES)}); + NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, NULL); CGFloat pixelWidth = [properties[(__bridge NSString *)kCGImagePropertyPixelWidth] doubleValue]; CGFloat pixelHeight = [properties[(__bridge NSString *)kCGImagePropertyPixelHeight] doubleValue]; - CGImagePropertyOrientation exifOrientation = (CGImagePropertyOrientation)[properties[(__bridge NSString *)kCGImagePropertyOrientation] unsignedIntegerValue]; - if (!exifOrientation) { - exifOrientation = kCGImagePropertyOrientationUp; + CGImagePropertyOrientation exifOrientation = kCGImagePropertyOrientationUp; + NSNumber *exifOrientationValue = properties[(__bridge NSString *)kCGImagePropertyOrientation]; + if (exifOrientationValue != NULL) { + exifOrientation = [exifOrientationValue unsignedIntValue]; } NSMutableDictionary *decodingOptions; diff --git a/Tests/Tests/SDImageCoderTests.m b/Tests/Tests/SDImageCoderTests.m index 32866943..26ad0f43 100644 --- a/Tests/Tests/SDImageCoderTests.m +++ b/Tests/Tests/SDImageCoderTests.m @@ -547,15 +547,23 @@ } - (void)test29ThatJFIFDecodeOrientationShouldNotApplyTwice { + // I don't think this is SDWebImage's issue, it's Apple's ImgeIO Bug, but user complain about this: #3594 + // In W3C standard, JFIF should always be orientation up, and should not contains EXIF orientation + // But some bad image editing tool will generate this kind of image :( NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestJFIF" withExtension:@"jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [SDImageIOCoder.sharedCoder decodedImageWithData:data options:nil]; + expect(image.sd_imageFormat).equal(SDImageFormatJPEG); #if SD_UIKIT UIImageOrientation orientation = image.imageOrientation; - expect(orientation).equal(UIImageOrientationUp); -#else - expect(image.sd_imageFormat).equal(SDImageFormatJPEG); + expect(orientation).equal(UIImageOrientationDown); +#endif + + UIImage *systemImage = [[UIImage alloc] initWithData:data]; +#if SD_UIKIT + orientation = image.imageOrientation; + expect(orientation).equal(UIImageOrientationDown); #endif // Manual test again for Apple's API