From 2fa1e1785aa7c8789e476f9387014a336d83148c Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Wed, 15 Nov 2023 17:48:03 +0800 Subject: [PATCH] Fix the previous wrong changes of iOS 17 indexed PNG color workaround Added test cases `test30ThatImageIOPNGPluginBuggyWorkaround` --- SDWebImage/Core/SDImageIOAnimatedCoder.m | 10 ++++++---- Tests/SDWebImage Tests.xcodeproj/project.pbxproj | 8 ++++++++ Tests/Tests/Images/IndexedPNG.png | Bin 0 -> 8271 bytes Tests/Tests/SDImageCoderTests.m | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 Tests/Tests/Images/IndexedPNG.png diff --git a/SDWebImage/Core/SDImageIOAnimatedCoder.m b/SDWebImage/Core/SDImageIOAnimatedCoder.m index f5d33a04..a543ac57 100644 --- a/SDWebImage/Core/SDImageIOAnimatedCoder.m +++ b/SDWebImage/Core/SDImageIOAnimatedCoder.m @@ -184,10 +184,10 @@ static CGImageRef SDImageIOPNGPluginBuggyCreateWorkaround(CGImageRef cgImage) CF CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(cgImage); CGImageAlphaInfo alphaInfo = (bitmapInfo & kCGBitmapAlphaInfoMask); CGImageAlphaInfo newAlphaInfo = alphaInfo; - if (alphaInfo == kCGImageAlphaPremultipliedLast) { - newAlphaInfo = kCGImageAlphaLast; - } else if (alphaInfo == kCGImageAlphaPremultipliedFirst) { - newAlphaInfo = kCGImageAlphaFirst; + if (alphaInfo == kCGImageAlphaLast) { + newAlphaInfo = kCGImageAlphaPremultipliedLast; + } else if (alphaInfo == kCGImageAlphaFirst) { + newAlphaInfo = kCGImageAlphaPremultipliedFirst; } if (newAlphaInfo != alphaInfo) { CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask; @@ -244,6 +244,8 @@ static BOOL SDImageIOPNGPluginBuggyNeedWorkaround(void) { #endif } } + CFRelease(source); + CGImageRelease(cgImage); }); return isBuggy; diff --git a/Tests/SDWebImage Tests.xcodeproj/project.pbxproj b/Tests/SDWebImage Tests.xcodeproj/project.pbxproj index c5746e28..862d94a5 100644 --- a/Tests/SDWebImage Tests.xcodeproj/project.pbxproj +++ b/Tests/SDWebImage Tests.xcodeproj/project.pbxproj @@ -47,6 +47,9 @@ 326E69482334C0C300B7252C /* TestLoopCount.gif in Resources */ = {isa = PBXBuildFile; fileRef = 326E69462334C0C200B7252C /* TestLoopCount.gif */; }; 327054E2206CEFF3006EA328 /* TestImageAnimated.apng in Resources */ = {isa = PBXBuildFile; fileRef = 327054E1206CEFF3006EA328 /* TestImageAnimated.apng */; }; 327054E3206CEFF3006EA328 /* TestImageAnimated.apng in Resources */ = {isa = PBXBuildFile; fileRef = 327054E1206CEFF3006EA328 /* TestImageAnimated.apng */; }; + 3278F5E22B04C1AC0004A6EE /* IndexedPNG.png in Resources */ = {isa = PBXBuildFile; fileRef = 3278F5E12B04C1AC0004A6EE /* IndexedPNG.png */; }; + 3278F5E32B04C1AC0004A6EE /* IndexedPNG.png in Resources */ = {isa = PBXBuildFile; fileRef = 3278F5E12B04C1AC0004A6EE /* IndexedPNG.png */; }; + 3278F5E42B04C1AC0004A6EE /* IndexedPNG.png in Resources */ = {isa = PBXBuildFile; fileRef = 3278F5E12B04C1AC0004A6EE /* IndexedPNG.png */; }; 327A418C211D660600495442 /* TestImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 327A418B211D660600495442 /* TestImage.heic */; }; 327A418D211D660600495442 /* TestImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 327A418B211D660600495442 /* TestImage.heic */; }; 328BB6DD20825E9800760D6C /* SDWebImageTestCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 328BB6DC20825E9800760D6C /* SDWebImageTestCache.m */; }; @@ -149,6 +152,7 @@ 3264FF2E205D42CB00F6BD48 /* SDWebImageTestTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestTransformer.m; sourceTree = ""; }; 326E69462334C0C200B7252C /* TestLoopCount.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = TestLoopCount.gif; sourceTree = ""; }; 327054E1206CEFF3006EA328 /* TestImageAnimated.apng */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageAnimated.apng; sourceTree = ""; }; + 3278F5E12B04C1AC0004A6EE /* IndexedPNG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = IndexedPNG.png; sourceTree = ""; }; 327A418B211D660600495442 /* TestImage.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImage.heic; sourceTree = ""; }; 328BAF262240C08E00FC70DD /* Test-Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Test-Shared.xcconfig"; sourceTree = ""; }; 328BAF272240C08E00FC70DD /* Test-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Test-Release.xcconfig"; sourceTree = ""; }; @@ -266,6 +270,7 @@ isa = PBXGroup; children = ( 32648066250232F7004FA0FC /* 1@2x.gif */, + 3278F5E12B04C1AC0004A6EE /* IndexedPNG.png */, 433BBBBA1D7EFA8B0086B6E9 /* MonochromeTestImage.jpg */, 324047432271956F007C53E1 /* TestEXIF.png */, 3264CD162AAB1E23001E338B /* TestJFIF.jpg */, @@ -497,6 +502,7 @@ 329922892365DC6C00EAFD97 /* TestImageLarge.jpg in Resources */, 32648069250232F7004FA0FC /* 1@2x.gif in Resources */, 3299228A2365DC6C00EAFD97 /* TestImage.png in Resources */, + 3278F5E42B04C1AC0004A6EE /* IndexedPNG.png in Resources */, 329922842365DC6C00EAFD97 /* MonochromeTestImage.jpg in Resources */, 329922882365DC6C00EAFD97 /* TestImage.jpg in Resources */, 32515F9E24AF1919005E8F79 /* TestImageAnimated.webp in Resources */, @@ -524,6 +530,7 @@ 32B99EA6203B31360017FD66 /* TestImage.png in Resources */, 32648068250232F7004FA0FC /* 1@2x.gif in Resources */, 3297A0A023374D1700814590 /* TestImageAnimated.heic in Resources */, + 3278F5E32B04C1AC0004A6EE /* IndexedPNG.png in Resources */, 32B99EA2203B31360017FD66 /* MonochromeTestImage.jpg in Resources */, 32905E65211D786E00460FCF /* TestImage.heif in Resources */, 32515F9D24AF1919005E8F79 /* TestImageAnimated.webp in Resources */, @@ -551,6 +558,7 @@ 433BBBB71D7EF8200086B6E9 /* TestImage.gif in Resources */, 32648067250232F7004FA0FC /* 1@2x.gif in Resources */, 433BBBB91D7EF8260086B6E9 /* TestImage.png in Resources */, + 3278F5E22B04C1AC0004A6EE /* IndexedPNG.png in Resources */, 3297A09F23374D1700814590 /* TestImageAnimated.heic in Resources */, 327054E2206CEFF3006EA328 /* TestImageAnimated.apng in Resources */, 32515F9C24AF1919005E8F79 /* TestImageAnimated.webp in Resources */, diff --git a/Tests/Tests/Images/IndexedPNG.png b/Tests/Tests/Images/IndexedPNG.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed105e14210beae2b9bfea6931c2d71c398ebd6 GIT binary patch literal 8271 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