Skip to content

Commit 3b27487

Browse files
authored
Merge pull request #77 from SDWebImage/performance/byte_alignment
Avoid force-decode by apply the byte alignment for static WebP images, using runtime detection for bitmap info
2 parents 76565bc + c0c65f1 commit 3b27487

File tree

7 files changed

+148
-40
lines changed

7 files changed

+148
-40
lines changed

Cartfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github "SDWebImage/SDWebImage" ~> 5.16
1+
github "SDWebImage/SDWebImage" ~> 5.17
22
github "SDWebImage/libwebp-Xcode" ~> 1.0

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let package = Package(
1717
dependencies: [
1818
// Dependencies declare other packages that this package depends on.
1919
// .package(url: /* package url */, from: "1.0.0"),
20-
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.16.0"),
20+
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.17.0"),
2121
.package(url: "https://github.com/SDWebImage/libwebp-Xcode.git", from: "1.1.0")
2222
],
2323
targets: [

SDWebImageWebPCoder.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ This is a SDWebImage coder plugin to support WebP image.
2828
'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'
2929
}
3030
s.framework = 'CoreGraphics'
31-
s.dependency 'SDWebImage/Core', '~> 5.16'
31+
s.dependency 'SDWebImage/Core', '~> 5.17'
3232
s.dependency 'libwebp', '~> 1.0'
3333

3434
end

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

+127-37
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
/// Used for animated WebP, which need a canvas for decoding (rendering), possible apply a scale transform for thumbnail decoding (avoiding post-rescale using vImage)
7272
/// See more in #73
7373
static inline CGContextRef _Nullable CreateWebPCanvas(BOOL hasAlpha, CGSize canvasSize, CGSize thumbnailSize, BOOL preserveAspectRatio) {
74-
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
75-
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
74+
// From SDWebImage v5.17.0, use runtime detection of bitmap info instead of hardcode.
75+
CGBitmapInfo bitmapInfo = [SDImageCoderHelper preferredPixelFormat:hasAlpha].bitmapInfo;
7676
// Check whether we need to use thumbnail
7777
CGSize scaledSize = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(canvasSize.width, canvasSize.height) scaleSize:thumbnailSize preserveAspectRatio:preserveAspectRatio shouldScaleUp:NO];
7878
CGContextRef canvas = CGBitmapContextCreate(NULL, scaledSize.width, scaledSize.height, 8, 0, [SDImageCoderHelper colorSpaceGetDeviceRGB], bitmapInfo);
@@ -88,18 +88,87 @@ static inline CGContextRef _Nullable CreateWebPCanvas(BOOL hasAlpha, CGSize canv
8888
return canvas;
8989
}
9090

91-
// TODO, share this logic for multiple coders, or do refactory in v6.0 (The coder plugin should provide image information back to Core, like `CGImageSourceCopyPropertiesAtIndex`)
92-
static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize originalSize, NSUInteger frameCount, NSUInteger bytesPerPixel) {
93-
if (CGSizeEqualToSize(originalSize, CGSizeZero)) return CGSizeMake(1, 1);
94-
NSUInteger totalFramePixelSize = limitBytes / bytesPerPixel / (frameCount ?: 1);
95-
CGFloat ratio = originalSize.height / originalSize.width;
96-
CGFloat width = sqrt(totalFramePixelSize / ratio);
97-
CGFloat height = width * ratio;
98-
width = MAX(1, floor(width));
99-
height = MAX(1, floor(height));
100-
CGSize size = CGSizeMake(width, height);
101-
102-
return size;
91+
WEBP_CSP_MODE ConvertCSPMode(CGBitmapInfo bitmapInfo) {
92+
// Get alpha info, byteOrder info
93+
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
94+
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
95+
BOOL byteOrderNormal = NO;
96+
switch (byteOrderInfo) {
97+
case kCGBitmapByteOrderDefault: {
98+
byteOrderNormal = YES;
99+
} break;
100+
case kCGBitmapByteOrder32Little: {
101+
} break;
102+
case kCGBitmapByteOrder32Big: {
103+
byteOrderNormal = YES;
104+
} break;
105+
default: break;
106+
}
107+
switch (alphaInfo) {
108+
case kCGImageAlphaPremultipliedFirst: {
109+
if (byteOrderNormal) {
110+
// ARGB8888, premultiplied
111+
return MODE_Argb;
112+
} else {
113+
// BGRA8888, premultiplied
114+
return MODE_bgrA;
115+
}
116+
}
117+
break;
118+
case kCGImageAlphaPremultipliedLast: {
119+
if (byteOrderNormal) {
120+
// RGBA8888, premultiplied
121+
return MODE_rgbA;
122+
} else {
123+
// ABGR8888, premultiplied
124+
// Unsupported!
125+
return MODE_LAST;
126+
}
127+
}
128+
break;
129+
case kCGImageAlphaNone: {
130+
if (byteOrderNormal) {
131+
// RGB
132+
return MODE_RGB;
133+
} else {
134+
// BGR
135+
return MODE_BGR;
136+
}
137+
}
138+
break;
139+
case kCGImageAlphaLast:
140+
case kCGImageAlphaNoneSkipLast: {
141+
if (byteOrderNormal) {
142+
// RGBA or RGBX
143+
return MODE_RGBA;
144+
} else {
145+
// ABGR or XBGR
146+
// Unsupported!
147+
return MODE_LAST;
148+
}
149+
}
150+
break;
151+
case kCGImageAlphaFirst:
152+
case kCGImageAlphaNoneSkipFirst: {
153+
if (byteOrderNormal) {
154+
// ARGB or XRGB
155+
return MODE_ARGB;
156+
} else {
157+
// BGRA or BGRX
158+
return MODE_BGRA;
159+
}
160+
}
161+
break;
162+
case kCGImageAlphaOnly: {
163+
// A
164+
// Unsupported
165+
return MODE_LAST;
166+
}
167+
break;
168+
default:
169+
break;
170+
}
171+
return MODE_LAST;
103172
}
104173

105174
@interface SDWebPCoderFrame : NSObject
@@ -245,7 +314,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
245314
if (limitBytes > 0) {
246315
// Hack 32 BitsPerPixel
247316
CGSize imageSize = CGSizeMake(canvasWidth, canvasHeight);
248-
CGSize framePixelSize = SDCalculateScaleDownPixelSize(limitBytes, imageSize, frameCount, 4);
317+
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:limitBytes bytesPerPixel:4 frameCount:frameCount];
249318
// Override thumbnail size
250319
thumbnailSize = framePixelSize;
251320
preserveAspectRatio = YES;
@@ -317,8 +386,8 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
317386
- (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)options {
318387
self = [super init];
319388
if (self) {
320-
// Progressive images need transparent, so always use premultiplied BGRA
321-
_idec = WebPINewRGB(MODE_bgrA, NULL, 0, 0);
389+
// Progressive images need transparent, so always use premultiplied RGBA
390+
_idec = WebPINewRGB(MODE_rgbA, NULL, 0, 0);
322391
CGFloat scale = 1;
323392
NSNumber *scaleFactor = options[SDImageCoderDecodeScaleFactor];
324393
if (scaleFactor != nil) {
@@ -394,7 +463,7 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
394463
if (_limitBytes > 0) {
395464
// Hack 32 BitsPerPixel
396465
CGSize imageSize = CGSizeMake(_canvasWidth, _canvasHeight);
397-
CGSize framePixelSize = SDCalculateScaleDownPixelSize(_limitBytes, imageSize, _frameCount, 4);
466+
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:_limitBytes bytesPerPixel:4 frameCount:_frameCount];
398467
// Override thumbnail size
399468
_thumbnailSize = framePixelSize;
400469
_preserveAspectRatio = YES;
@@ -428,17 +497,18 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
428497
CGDataProviderRef provider =
429498
CGDataProviderCreateWithData(NULL, rgba, rgbaSize, NULL);
430499
CGColorSpaceRef colorSpaceRef = [SDImageCoderHelper colorSpaceGetDeviceRGB];
431-
432-
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
500+
// Because _idec use MODE_rgbA
501+
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
433502
size_t components = 4;
503+
BOOL shouldInterpolate = YES;
434504
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
435505
// Why to use last_y for image height is because of libwebp's bug (https://bugs.chromium.org/p/webp/issues/detail?id=362)
436506
// It will not keep memory barrier safe on x86 architechure (macOS & iPhone simulator) but on ARM architecture (iPhone & iPad & tv & watch) it works great
437507
// If different threads use WebPIDecGetRGB to grab rgba bitmap, it will contain the previous decoded bitmap data
438508
// So this will cause our drawed image looks strange(above is the current part but below is the previous part)
439509
// We only grab the last_y height and draw the last_y height instead of total height image
440510
// Besides fix, this can enhance performance since we do not need to create extra bitmap
441-
CGImageRef imageRef = CGImageCreate(width, last_y, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
511+
CGImageRef imageRef = CGImageCreate(width, last_y, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, shouldInterpolate, renderingIntent);
442512

443513
CGDataProviderRelease(provider);
444514

@@ -546,20 +616,46 @@ - (nullable CGImageRef)sd_createWebpImageWithData:(WebPData)webpData colorSpace:
546616
}
547617

548618
BOOL hasAlpha = config.input.has_alpha;
549-
// iOS prefer BGRA8888 (premultiplied) or BGRX8888 bitmapInfo for screen rendering, which is same as `UIGraphicsBeginImageContext()` or `- [CALayer drawInContext:]`
550-
// use this bitmapInfo, combined with right colorspace, even without decode, can still avoid extra CA::Render::copy_image(which marked `Color Copied Images` from Instruments)
551-
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
552-
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
619+
// From SDWebImage v5.17.0, use runtime detection of bitmap info instead of hardcode.
620+
SDImagePixelFormat pixelFormat = [SDImageCoderHelper preferredPixelFormat:hasAlpha];
621+
CGBitmapInfo bitmapInfo = pixelFormat.bitmapInfo;
622+
WEBP_CSP_MODE mode = ConvertCSPMode(bitmapInfo);
623+
if (mode == MODE_LAST) {
624+
NSAssert(NO, @"Unsupported libwebp preferred CGBitmapInfo: %d", bitmapInfo);
625+
return nil;
626+
}
627+
config.output.colorspace = mode;
553628
config.options.use_threads = 1;
554-
config.output.colorspace = MODE_bgrA;
629+
555630

556631
// Use scaling for thumbnail
632+
size_t width = config.input.width;
633+
size_t height = config.input.height;
557634
if (scaledSize.width != 0 && scaledSize.height != 0) {
558635
config.options.use_scaling = 1;
559636
config.options.scaled_width = scaledSize.width;
560637
config.options.scaled_height = scaledSize.height;
638+
width = scaledSize.width;
639+
height = scaledSize.height;
561640
}
562641

642+
// We alloc the buffer and do byte alignment by ourself. libwebp defaults does not byte alignment to `bitsPerPixel`, which cause the CoreAnimation unhappy and always trigger the `CA::Render::copy_image`
643+
size_t bitsPerComponent = 8;
644+
size_t components = (mode == MODE_RGB || mode == MODE_BGR) ? 3 : 4; // Actually always 4
645+
size_t bitsPerPixel = bitsPerComponent * components;
646+
// Read: https://github.com/path/FastImageCache#byte-alignment
647+
// A properly aligned bytes-per-row value must be a multiple of 8 pixels × bytes per pixel
648+
// For a typical ARGB image, the aligned bytes-per-row value is a multiple of 64.
649+
size_t alignment = pixelFormat.alignment;
650+
size_t bytesPerRow = SDByteAlign(width * (bitsPerPixel / 8), alignment);
651+
//size_t bytesPerRow = 6688;
652+
653+
void *rgba = WebPMalloc(bytesPerRow * height);
654+
config.output.is_external_memory = 1;
655+
config.output.u.RGBA.rgba = rgba;
656+
config.output.u.RGBA.stride = (int)bytesPerRow;
657+
config.output.u.RGBA.size = height * bytesPerRow;
658+
563659
// Decode the WebP image data into a RGBA value array
564660
if (WebPDecode(webpData.bytes, webpData.size, &config) != VP8_STATUS_OK) {
565661
return nil;
@@ -568,13 +664,9 @@ - (nullable CGImageRef)sd_createWebpImageWithData:(WebPData)webpData colorSpace:
568664
// Construct a UIImage from the decoded RGBA value array
569665
CGDataProviderRef provider =
570666
CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
571-
size_t bitsPerComponent = 8;
572-
size_t bitsPerPixel = 32;
573-
size_t bytesPerRow = config.output.u.RGBA.stride;
574-
size_t width = config.output.width;
575-
size_t height = config.output.height;
667+
BOOL shouldInterpolate = YES;
576668
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
577-
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
669+
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, shouldInterpolate, renderingIntent);
578670

579671
CGDataProviderRelease(provider);
580672

@@ -756,9 +848,6 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef
756848
}
757849

758850
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
759-
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
760-
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
761-
size_t components = bitsPerPixel / bitsPerComponent;
762851
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
763852
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
764853
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
@@ -891,7 +980,7 @@ - (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config
891980
}
892981

893982
static void FreeImageData(void *info, const void *data, size_t size) {
894-
free((void *)data);
983+
WebPFree((void *)data);
895984
}
896985

897986
static int GetIntValueForKey(NSDictionary * _Nonnull dictionary, NSString * _Nonnull key, int defaultValue) {
@@ -968,7 +1057,7 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(nullable SDIma
9681057
if (_limitBytes > 0) {
9691058
// Hack 32 BitsPerPixel
9701059
CGSize imageSize = CGSizeMake(_canvasWidth, _canvasHeight);
971-
CGSize framePixelSize = SDCalculateScaleDownPixelSize(_limitBytes, imageSize, _frameCount, 4);
1060+
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:_limitBytes bytesPerPixel:4 frameCount:_frameCount];
9721061
// Override thumbnail size
9731062
_thumbnailSize = framePixelSize;
9741063
_preserveAspectRatio = YES;
@@ -1236,6 +1325,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
12361325
#else
12371326
image = [[UIImage alloc] initWithCGImage:imageRef scale:_scale orientation:kCGImagePropertyOrientationUp];
12381327
#endif
1328+
image.sd_imageFormat = SDImageFormatWebP;
12391329
CGImageRelease(imageRef);
12401330

12411331
WebPDemuxReleaseIterator(&iter);
92.8 KB
Binary file not shown.

Tests/SDWebImageWebPCoderTests.m

+12
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,18 @@ - (void)test45WebPEncodingMaxFileSize {
218218
XCTAssertLessThanOrEqual(dataWithLimit.length, maxFileSize);
219219
}
220220

221+
- (void)testWebPDecodeDoesNotTriggerCACopyImage {
222+
NSURL *staticWebPURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestColorspaceStatic" withExtension:@"webp"];
223+
NSData *data = [NSData dataWithContentsOfURL:staticWebPURL];
224+
UIImage *image = [SDImageWebPCoder.sharedCoder decodedImageWithData:data options:@{SDImageCoderDecodeThumbnailPixelSize: @(CGSizeMake(1023, 680))}]; // 1023 * 4 need aligned to 4096
225+
CGImageRef cgImage = [image CGImage];
226+
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
227+
XCTAssertEqual(bytesPerRow, 4096);
228+
CGColorSpaceRef colorspace = CGImageGetColorSpace(cgImage);
229+
NSString *colorspaceName = (__bridge_transfer NSString *)CGColorSpaceCopyName(colorspace);
230+
XCTAssertEqual(colorspaceName, (__bridge NSString *)kCGColorSpaceSRGB, @"Color space is not sRGB");
231+
}
232+
221233
- (void)testEncodingSettings {
222234
WebPConfig config;
223235
WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, 0.2);

Tests/SDWebImageWebPCoderTests.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
0EF5B6264833B7BC20894578 /* Pods_SDWebImageWebPCoderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */; };
1111
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */; };
1212
325E268E25C82BE1000B807B /* TestImageGrayscale.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */; };
13+
326420312A5D53E300EE3E46 /* TestColorspaceStatic.webp in Resources */ = {isa = PBXBuildFile; fileRef = 326420302A5D53E300EE3E46 /* TestColorspaceStatic.webp */; };
1314
808C918E213FD131004B0F7C /* SDWebImageWebPCoderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */; };
1415
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919A213FD2B2004B0F7C /* TestImageStatic.webp */; };
1516
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */; };
@@ -19,6 +20,7 @@
1920
28D8AA3D3015E075692FD3E3 /* Pods-SDWebImageWebPCoderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageWebPCoderTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-SDWebImageWebPCoderTests/Pods-SDWebImageWebPCoderTests.debug.xcconfig"; sourceTree = "<group>"; };
2021
3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageBlendAnimated.webp; sourceTree = "<group>"; };
2122
325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImageGrayscale.jpg; sourceTree = "<group>"; };
23+
326420302A5D53E300EE3E46 /* TestColorspaceStatic.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestColorspaceStatic.webp; sourceTree = "<group>"; };
2224
46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageWebPCoderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2325
808C918B213FD130004B0F7C /* SDWebImageWebPCoderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SDWebImageWebPCoderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
2426
808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageWebPCoderTests.m; sourceTree = "<group>"; };
@@ -80,6 +82,7 @@
8082
808C9199213FD2B2004B0F7C /* Images */ = {
8183
isa = PBXGroup;
8284
children = (
85+
326420302A5D53E300EE3E46 /* TestColorspaceStatic.webp */,
8386
325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */,
8487
808C919A213FD2B2004B0F7C /* TestImageStatic.webp */,
8588
808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */,
@@ -157,6 +160,7 @@
157160
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */,
158161
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */,
159162
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */,
163+
326420312A5D53E300EE3E46 /* TestColorspaceStatic.webp in Resources */,
160164
325E268E25C82BE1000B807B /* TestImageGrayscale.jpg in Resources */,
161165
);
162166
runOnlyForDeploymentPostprocessing = 0;
@@ -377,6 +381,7 @@
377381
"$(inherited)",
378382
);
379383
INFOPLIST_FILE = Info.plist;
384+
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
380385
PRODUCT_BUNDLE_IDENTIFIER = org.SDWebImage.SDWebImageWebPCoderTests;
381386
PRODUCT_NAME = "$(TARGET_NAME)";
382387
};
@@ -387,6 +392,7 @@
387392
baseConfigurationReference = D92E6791BF088D1A101E670E /* Pods-SDWebImageWebPCoderTests.release.xcconfig */;
388393
buildSettings = {
389394
INFOPLIST_FILE = Info.plist;
395+
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
390396
PRODUCT_BUNDLE_IDENTIFIER = org.SDWebImage.SDWebImageWebPCoderTests;
391397
PRODUCT_NAME = "$(TARGET_NAME)";
392398
};

0 commit comments

Comments
 (0)